From 4ad94f2550d6c6ae5daeb283b2168471f0d665dd Mon Sep 17 00:00:00 2001 From: Max Voloshinskii Date: Thu, 31 Oct 2024 12:35:17 +0300 Subject: [PATCH] Add registry --- Sources/URKit/Registry/CryptoHDKey.swift | 82 +++++++++++++++++++++ Sources/URKit/Registry/CryptoKeyPath.swift | 57 ++++++++++++++ Sources/URKit/Registry/CryptoPath.swift | 54 ++++++++++++++ Sources/URKit/Registry/TonSignRequest.swift | 55 ++++++++++++++ Sources/URKit/Registry/TonSignature.swift | 37 ++++++++++ 5 files changed, 285 insertions(+) create mode 100644 Sources/URKit/Registry/CryptoHDKey.swift create mode 100644 Sources/URKit/Registry/CryptoKeyPath.swift create mode 100644 Sources/URKit/Registry/CryptoPath.swift create mode 100644 Sources/URKit/Registry/TonSignRequest.swift create mode 100644 Sources/URKit/Registry/TonSignature.swift diff --git a/Sources/URKit/Registry/CryptoHDKey.swift b/Sources/URKit/Registry/CryptoHDKey.swift new file mode 100644 index 0000000..7a42128 --- /dev/null +++ b/Sources/URKit/Registry/CryptoHDKey.swift @@ -0,0 +1,82 @@ +import Foundation + +enum CryptoHDKeyError: Error { + case invalidCBORType +} + +public struct CryptoHDKey: Equatable { + public enum KEYS: UInt64 { + case masterKey = 1 + case privateKey = 2 + case keyData = 3 + case chainCode = 4 + case useInfo = 5 + case origin = 6 + case children = 7 + case parentFingerprint = 8 + case name = 9 + case note = 10 + } + + public var masterKey: Bool? = false + public var privateKey: Bool? = nil + public var keyData: Data? = nil + public var chainCode: Data? = nil + public var useInfo: Data? = nil + public var origin: CryptoKeyPath? = nil + public var children: CryptoKeyPath? = nil + public var parentFingerprint: Data? = nil + public var name: String? = nil + public var note: String? = nil + + public init(cbor: CBOR) throws { + switch cbor { + case .map(let map): + for (key, value) in map { + let keyUint = try UInt64(cbor: key) + if (keyUint == KEYS.masterKey.rawValue) { + masterKey = try Bool(cbor: value) + } + if (keyUint == KEYS.privateKey.rawValue) { + privateKey = try Bool(cbor: value) + } + if (keyUint == KEYS.keyData.rawValue) { + keyData = try Data(cbor: value) + } + if (keyUint == KEYS.chainCode.rawValue) { + chainCode = try Data(cbor: value) + } + if (keyUint == KEYS.useInfo.rawValue) { + useInfo = try Data(cbor: value) + } + if (keyUint == KEYS.origin.rawValue) { + switch (value) { + case.tagged(_, let keyPath): + origin = try CryptoKeyPath.init(cbor: keyPath) + default: + throw CryptoHDKeyError.invalidCBORType + } + } + if (keyUint == KEYS.children.rawValue) { + switch (value) { + case.tagged(_, let keyPath): + children = try CryptoKeyPath.init(cbor: keyPath) + default: + throw CryptoHDKeyError.invalidCBORType + } + } + if (keyUint == KEYS.parentFingerprint.rawValue) { + parentFingerprint = try Data(cbor: value) + } + if (keyUint == KEYS.name.rawValue) { + name = try String(cbor: value) + } + if (keyUint == KEYS.note.rawValue) { + note = try String(cbor: value) + } + } + default: + throw CryptoHDKeyError.invalidCBORType + } + } +} diff --git a/Sources/URKit/Registry/CryptoKeyPath.swift b/Sources/URKit/Registry/CryptoKeyPath.swift new file mode 100644 index 0000000..9c9d6fc --- /dev/null +++ b/Sources/URKit/Registry/CryptoKeyPath.swift @@ -0,0 +1,57 @@ +import Foundation + +enum CryptoKeyPathError: Error { + case invalidCBORType +} + +public struct CryptoKeyPath: Equatable { + public enum KEYS: UInt64 { + case components = 1 + case sourceFingerprint = 2 + case depth = 3 + } + + public var components: CryptoPath? = nil + public var sourceFingerprint: UInt64? = nil + public var depth: UInt64? = nil + + public init(components: CryptoPath?, sourceFingerprint: UInt64?, depth: UInt64?) { + self.components = components + self.sourceFingerprint = sourceFingerprint + self.depth = depth + } + + public init(cbor: CBOR) throws { + switch cbor { + case .map(let map): + for (key, value) in map { + let keyUint = try UInt64(cbor: key) + if (keyUint == KEYS.components.rawValue) { + components = try CryptoPath.init(cbor: value) + } + if (keyUint == KEYS.sourceFingerprint.rawValue) { + sourceFingerprint = try UInt64(cbor: value) + } + if (keyUint == KEYS.depth.rawValue) { + depth = try UInt64(cbor: value) + } + } + default: + throw CryptoKeyPathError.invalidCBORType + } + } + + public func toCBOR() throws -> CBOR { + var map = Map() + if let components = components { + map[CBOR.unsigned(KEYS.components.rawValue)] = CBOR.array(components.components) + } + if let sourceFingerprint = sourceFingerprint { + map[CBOR.unsigned(KEYS.sourceFingerprint.rawValue)] = CBOR.unsigned(sourceFingerprint) + } + if let depth = depth { + map[CBOR.unsigned(KEYS.depth.rawValue)] = CBOR.unsigned(depth) + } + return CBOR.tagged(Tag.init(304, ["crypto-keypath"]), CBOR.map(map)) + } +} diff --git a/Sources/URKit/Registry/CryptoPath.swift b/Sources/URKit/Registry/CryptoPath.swift new file mode 100644 index 0000000..b282bf2 --- /dev/null +++ b/Sources/URKit/Registry/CryptoPath.swift @@ -0,0 +1,54 @@ +import Foundation + +public struct CryptoPath: Equatable { + public var components: [CBOR] = [] + + public init(cbor: CBOR) throws { + switch cbor { + case .array(let arr): + var newComponents = Array() + for item in arr { + newComponents.append(item) + } + components = newComponents + default: + throw CryptoKeyPathError.invalidCBORType + } + } + + public init(string: String) throws { + String(string).split(separator: "/").forEach { component in + if component == "m" { + return + } + + let value = component.replacingOccurrences(of: "'", with: "") + if let value = UInt64(value) { + components.append(.unsigned(value)) + } + + if component.hasSuffix("'") { + components.append(.simple(.true)) + } + } + } +} + +public extension String { + init(_ value: CryptoPath) { + var path = "m" + for component in value.components { + switch component { + case .simple(let value): + if (value == .true) { + path += "'" + } + case .unsigned(let value): + path += "/\(value)" + default: + break + } + } + self = path + } +} diff --git a/Sources/URKit/Registry/TonSignRequest.swift b/Sources/URKit/Registry/TonSignRequest.swift new file mode 100644 index 0000000..8467ac2 --- /dev/null +++ b/Sources/URKit/Registry/TonSignRequest.swift @@ -0,0 +1,55 @@ +import Foundation + +public enum TonSignRequestError: Error { + case invalidCBORType +} + +public struct TonSignRequest: Equatable { + public enum KEYS: UInt64 { + case requestId = 1 + case signData = 2 + case dataType = 3 + case cryptoKeypath = 4 + case address = 5 + case origin = 6 + } + + public var requestId: Data? = nil + public var signData: Data? = nil + public var dataType: UInt64? = nil + public var cryptoKeypath: CryptoKeyPath? = nil + public var address: String? = nil + public var origin: String? = nil + + public init(requestId: Data? = nil, signData: Data? = nil, dataType: UInt64? = nil, cryptoKeypath: CryptoKeyPath? = nil, address: String? = nil, origin: String? = nil) { + self.requestId = requestId + self.signData = signData + self.dataType = dataType + self.cryptoKeypath = cryptoKeypath + self.address = address + self.origin = origin + } + + public func toCBOR() throws -> CBOR { + var map = Map() + if let requestId = requestId { + map[CBOR.unsigned(KEYS.requestId.rawValue)] = CBOR.tagged(Tag.init(37, ["uuid"]), CBOR.bytes(requestId)) + } + if let signData = signData { + map[CBOR.unsigned(KEYS.signData.rawValue)] = CBOR.bytes(signData) + } + if let dataType = dataType { + map[CBOR.unsigned(KEYS.dataType.rawValue)] = CBOR.unsigned(dataType) + } + if let cryptoKeypath = cryptoKeypath { + map[CBOR.unsigned(KEYS.cryptoKeypath.rawValue)] = try cryptoKeypath.toCBOR() + } + if let address = address { + map[CBOR.unsigned(KEYS.address.rawValue)] = CBOR.text(address) + } + if let origin = origin { + map[CBOR.unsigned(KEYS.origin.rawValue)] = CBOR.text(origin) + } + return CBOR.map(map) + } +} diff --git a/Sources/URKit/Registry/TonSignature.swift b/Sources/URKit/Registry/TonSignature.swift new file mode 100644 index 0000000..0d0210c --- /dev/null +++ b/Sources/URKit/Registry/TonSignature.swift @@ -0,0 +1,37 @@ +import Foundation + +enum TonSignatureError: Error { + case invalidCBORType +} + +public struct TonSignature: Equatable { + public enum KEYS: UInt64 { + case requestId = 1 + case signature = 2 + case origin = 3 + } + + public var signature: Data? = nil + public var requestId: Data? = nil + public var origin: String? = nil + + public init(cbor: CBOR) throws { + switch cbor { + case .map(let map): + for (key, value) in map { + let keyUint = try UInt64(cbor: key) + if (keyUint == KEYS.signature.rawValue) { + signature = try Data(cbor: value) + } + if (keyUint == KEYS.requestId.rawValue) { + requestId = try Data(cbor: value) + } + if (keyUint == KEYS.origin.rawValue) { + origin = try String(cbor: value) + } + } + default: + throw TonSignatureError.invalidCBORType + } + } +}