From f32feb786343b25869910c62278c4331793b8780 Mon Sep 17 00:00:00 2001 From: phuoc Date: Tue, 21 May 2024 15:57:33 +0700 Subject: [PATCH 01/13] fix: migrate BIP39Mnemonic to BIP39 Signed-off-by: phuoc --- Package.swift | 12 ++- Sources/LibAuk/LibAuk.swift | 11 ++- Sources/LibAuk/Storage/SecureStorage.swift | 77 ++++++++++--------- Sources/LibAuk/Utils/KeyCreator.swift | 4 +- Sources/LibAuk/Utils/Keys.swift | 62 +++++++-------- .../Storage/SecureStorage_Tests.swift | 32 ++++---- 6 files changed, 98 insertions(+), 100 deletions(-) diff --git a/Package.swift b/Package.swift index 3c2d89a..89642ae 100644 --- a/Package.swift +++ b/Package.swift @@ -14,10 +14,11 @@ let package = Package( ], dependencies: [ .package(name: "Web3.swift", url: "https://github.com/bitmark-inc/Web3.swift.git", .branch("master")), - .package(url: "https://github.com/BlockchainCommons/URKit.git", .exact("7.5.0")), + .package(url: "https://github.com/BlockchainCommons/URKit.git", .exact("14.0.2")), .package(url: "https://github.com/keefertaylor/Base58Swift.git", from: "2.1.0"), .package(name: "KukaiCoreSwift", url: "https://github.com/autonomy-system/kukai-core-swift.git", .branch("main")), - .package(name: "TweetNacl", url: "https://github.com/bitmark-inc/tweetnacl-swiftwrap", branch: "master") + .package(name: "TweetNacl", url: "https://github.com/bitmark-inc/tweetnacl-swiftwrap", branch: "master"), + .package(url: "https://github.com/BlockchainCommons/BCSwiftFoundation.git", .branch("master")) // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), ], @@ -27,19 +28,16 @@ let package = Package( .target( name: "LibAuk", dependencies: [ - .target(name: "LibWally"), .product(name: "Web3", package: "Web3.swift"), .product(name: "URKit", package: "URKit"), .product(name: "KukaiCoreSwift", package: "KukaiCoreSwift"), .product(name: "Base58Swift", package: "Base58Swift"), .product(name: "TweetNacl", package: "TweetNacl"), + .product(name: "BCFoundation", package: "BCSwiftFoundation"), ]), .testTarget( name: "LibAukTests", - dependencies: ["LibAuk"]), - .binaryTarget( - name: "LibWally", - path: "Frameworks/LibWally.xcframework") + dependencies: ["LibAuk"]) ], swiftLanguageVersions: [.v5] ) diff --git a/Sources/LibAuk/LibAuk.swift b/Sources/LibAuk/LibAuk.swift index 5595524..359081f 100644 --- a/Sources/LibAuk/LibAuk.swift +++ b/Sources/LibAuk/LibAuk.swift @@ -7,7 +7,6 @@ import Foundation import Combine -import LibWally public class LibAuk { @@ -33,15 +32,15 @@ public class LibAuk { } public func calculateEthFirstAddress(words: [String], passphrase: String) -> AnyPublisher { - Future { promise in + Future { promise in guard let entropy = Keys.entropy(words), - let mnemonic = Keys.mnemonic(entropy) else { + let bip39 = Keys.mnemonic(entropy) else { promise(.failure(LibAukError.invalidMnemonicError)) return } - promise(.success(mnemonic)) - }.tryMap({ mnemonic in - let ethPrivateKey = try Keys.ethereumPrivateKey(mnemonic: mnemonic, passphrase: passphrase) + promise(.success(bip39)) + }.tryMap({ bip39 in + let ethPrivateKey = try Keys.ethereumPrivateKey(bip39: bip39, passphrase: passphrase) return ethPrivateKey.address.hex(eip55: true) }) .eraseToAnyPublisher() diff --git a/Sources/LibAuk/Storage/SecureStorage.swift b/Sources/LibAuk/Storage/SecureStorage.swift index e8e46a6..d99c8bd 100644 --- a/Sources/LibAuk/Storage/SecureStorage.swift +++ b/Sources/LibAuk/Storage/SecureStorage.swift @@ -7,7 +7,7 @@ import Foundation import Combine -import LibWally +import BCFoundation import Web3 import KukaiCoreSwift import Base58Swift @@ -54,13 +54,13 @@ class SecureStorage: SecureStorageProtocol { self.keychain = keychain } - private func generateEthAddresses(mnemonic: BIP39Mnemonic, passphrase: String?, start: Int = 0, end: Int = 100) -> [Int: String] { + private func generateEthAddresses(bip39: BIP39, passphrase: String?, start: Int = 0, end: Int = 100) -> [Int: String] { var ethAddresses: [Int: String] = [:] for index in start...end { do { // Generate Ethereum private key for the current index - let privateKey = try Keys.ethereumPrivateKeyWithIndex(mnemonic: mnemonic, passphrase: passphrase, index: index) + let privateKey = try Keys.ethereumPrivateKeyWithIndex(bip39: bip39, passphrase: passphrase, index: index) // Derive Ethereum address from the private key let address = privateKey.address.hex(eip55: true) @@ -76,12 +76,12 @@ class SecureStorage: SecureStorageProtocol { return ethAddresses } - private func generateTezosPublicKeys(mnemonic: BIP39Mnemonic, passphrase: String?, start: Int, end: Int) -> [Int: String] { + private func generateTezosPublicKeys(bip39: BIP39, passphrase: String?, start: Int, end: Int) -> [Int: String] { var tezosPublicKeys: [Int: String] = [:] for index in start...end { // Generate Tezos wallet for the current index - let tezosWallet = Keys.tezosWalletWithIndex(mnemonic: mnemonic, passphrase: passphrase, index: index) + let tezosWallet = Keys.tezosWalletWithIndex(bip39: bip39, passphrase: passphrase, index: index) // Get the public key for the Tezos wallet let publicKey = tezosWallet?.publicKeyBase58encoded() @@ -93,8 +93,8 @@ class SecureStorage: SecureStorageProtocol { return tezosPublicKeys } - private func generateEthAddress(mnemonic: BIP39Mnemonic, passphrase: String?) throws -> String { - let ethPrivateKey = try Keys.ethereumPrivateKey(mnemonic: mnemonic, passphrase: passphrase) + private func generateEthAddress(bip39: BIP39, passphrase: String?) throws -> String { + let ethPrivateKey = try Keys.ethereumPrivateKey(bip39: bip39, passphrase: passphrase) let ethAddress = ethPrivateKey.address.hex(eip55: true) return ethAddress } @@ -106,9 +106,9 @@ class SecureStorage: SecureStorageProtocol { let name = seed.name /* accountDidKey */ - let mnemonic = Keys.mnemonic(seed.data)! + let bip39 = Keys.mnemonic(seed.data)! let passphrase = seed.passphrase - let privateKey = try Keys.accountDIDPrivateKey(mnemonic: mnemonic) + let privateKey = try Keys.accountDIDPrivateKey(bip39: bip39) // Multicodec encoded with prefix 0xe7 var bytes: [UInt8] = [231, 1] @@ -116,18 +116,18 @@ class SecureStorage: SecureStorageProtocol { let did = "did:key:z\(Base58.base58Encode(bytes))" /* pre-generate 100 eth addresses */ - let ethAddresses = self.generateEthAddresses(mnemonic: mnemonic, passphrase: passphrase, start: 0, end: self.preGenerateAddressLimit) + let ethAddresses = self.generateEthAddresses(bip39: bip39, passphrase: passphrase, start: 0, end: self.preGenerateAddressLimit) /* encryptionPrivateKey */ - let encryptionPrivateKey = try Keys.encryptionPrivateKey(mnemonic: mnemonic, passphrase: passphrase) + let encryptionPrivateKey = try Keys.encryptionPrivateKey(bip39: bip39, passphrase: passphrase) /* accountDIDPrivateKey */ - let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(mnemonic: mnemonic, passphrase: passphrase) + let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(bip39: bip39, passphrase: passphrase) /* tezos public key */ - let tezosPublicKeys = self.generateTezosPublicKeys(mnemonic: mnemonic, passphrase: passphrase, start: 0, end: self.preGenerateAddressLimit) + let tezosPublicKeys = self.generateTezosPublicKeys(bip39: bip39, passphrase: passphrase, start: 0, end: self.preGenerateAddressLimit) - let ethAddress = try self.generateEthAddress(mnemonic: mnemonic, passphrase: passphrase) + let ethAddress = try self.generateEthAddress(bip39: bip39, passphrase: passphrase) var seedPublicData = SeedPublicData(ethAddress: ethAddress, creationDate: Date(), @@ -164,6 +164,7 @@ class SecureStorage: SecureStorageProtocol { return } + guard let entropy = KeyCreator.createEntropy() else { promise(.failure(LibAukError.keyCreationError)) return @@ -320,13 +321,13 @@ class SecureStorage: SecureStorageProtocol { promise(.success(seed)) } .compactMap { seed in - guard let mnemonic = Keys.mnemonic(seed.data) else { + guard let bip39 = Keys.mnemonic(seed.data) else { return nil } - return (mnemonic, seed.passphrase) + return (bip39, seed.passphrase) } - .tryMap { (mnemonic: BIP39Mnemonic, passphrase: String?) in - let ethPrivateKey = try Keys.ethereumPrivateKeyWithIndex(mnemonic: mnemonic, passphrase: passphrase, index: index) + .tryMap { (bip39: BIP39, passphrase: String?) in + let ethPrivateKey = try Keys.ethereumPrivateKeyWithIndex(bip39: bip39, passphrase: passphrase, index: index) return ethPrivateKey.address.hex(eip55: true) } .eraseToAnyPublisher() @@ -358,13 +359,13 @@ class SecureStorage: SecureStorageProtocol { promise(.success(seed)) } .compactMap { seed in - guard let mnemonic = Keys.mnemonic(seed.data) else { + guard let bip39 = Keys.mnemonic(seed.data) else { return nil } - return (mnemonic, seed.passphrase) + return (bip39, seed.passphrase) } - .tryMap { (mnemonic: BIP39Mnemonic, passphrase: String?) in - let ethPrivateKey = try Keys.ethereumPrivateKey(mnemonic: mnemonic, passphrase: passphrase) + .tryMap { (bip39: BIP39, passphrase: String?) in + let ethPrivateKey = try Keys.ethereumPrivateKey(bip39: bip39, passphrase: passphrase) return try ethPrivateKey.sign(message: message) } .eraseToAnyPublisher() @@ -381,13 +382,13 @@ class SecureStorage: SecureStorageProtocol { promise(.success(seed)) } .compactMap { seed in - guard let mnemonic = Keys.mnemonic(seed.data) else { + guard let bip39 = Keys.mnemonic(seed.data) else { return nil } - return (mnemonic, seed.passphrase) + return (bip39, seed.passphrase) } - .tryMap { (mnemonic: BIP39Mnemonic, passphrase: String?) in - let ethPrivateKey = try Keys.ethereumPrivateKeyWithIndex(mnemonic: mnemonic, passphrase: passphrase, index: index) + .tryMap { (bip39: BIP39, passphrase: String?) in + let ethPrivateKey = try Keys.ethereumPrivateKeyWithIndex(bip39: bip39, passphrase: passphrase, index: index) return try ethPrivateKey.sign(message: message) } .eraseToAnyPublisher() @@ -404,13 +405,13 @@ class SecureStorage: SecureStorageProtocol { promise(.success(seed)) } .compactMap { seed in - guard let mnemonic = Keys.mnemonic(seed.data) else { + guard let bip39 = Keys.mnemonic(seed.data) else { return nil } - return (mnemonic, seed.passphrase) + return (bip39, seed.passphrase) } - .tryMap { (mnemonic: BIP39Mnemonic, passphrase: String?) in - let ethPrivateKey = try Keys.ethereumPrivateKey(mnemonic: mnemonic, passphrase: passphrase) + .tryMap { (bip39: BIP39, passphrase: String?) in + let ethPrivateKey = try Keys.ethereumPrivateKey(bip39: bip39, passphrase: passphrase) return try transaction.sign(with: ethPrivateKey, chainId: chainId) } @@ -428,13 +429,13 @@ class SecureStorage: SecureStorageProtocol { promise(.success(seed)) } .compactMap { seed in - guard let mnemonic = Keys.mnemonic(seed.data) else { + guard let bip39 = Keys.mnemonic(seed.data) else { return nil } - return (mnemonic, seed.passphrase) + return (bip39, seed.passphrase) } - .tryMap { (mnemonic: BIP39Mnemonic, passphrase: String?) in - let ethPrivateKey = try Keys.ethereumPrivateKeyWithIndex(mnemonic: mnemonic, passphrase: passphrase, index: index) + .tryMap { (bip39: BIP39, passphrase: String?) in + let ethPrivateKey = try Keys.ethereumPrivateKeyWithIndex(bip39: bip39, passphrase: passphrase, index: index) return try transaction.sign(with: ethPrivateKey, chainId: chainId) } @@ -616,8 +617,8 @@ class SecureStorage: SecureStorageProtocol { } return (mnemonic, seed.passphrase) } - .compactMap { (mnemonic: BIP39Mnemonic, passphrase: String?) in - Keys.tezosWallet(mnemonic: mnemonic, passphrase: passphrase) + .compactMap { (bip39: BIP39, passphrase: String?) in + Keys.tezosWallet(bip39: bip39, passphrase: passphrase) } .eraseToAnyPublisher() } @@ -638,8 +639,8 @@ class SecureStorage: SecureStorageProtocol { } return (mnemonic, seed.passphrase) } - .compactMap { (mnemonic: BIP39Mnemonic, passphrase: String?) in - Keys.tezosWalletWithIndex(mnemonic: mnemonic, passphrase: passphrase, index: index) + .compactMap { (bip39: BIP39, passphrase: String?) in + Keys.tezosWalletWithIndex(bip39: bip39, passphrase: passphrase, index: index) } .eraseToAnyPublisher() } diff --git a/Sources/LibAuk/Utils/KeyCreator.swift b/Sources/LibAuk/Utils/KeyCreator.swift index 2181253..e400fb5 100644 --- a/Sources/LibAuk/Utils/KeyCreator.swift +++ b/Sources/LibAuk/Utils/KeyCreator.swift @@ -6,13 +6,13 @@ // import Foundation -import LibWally +import BCFoundation class KeyCreator { static func createEntropy() -> Data? { guard let hex = Data.secureRandom(16)?.hexString, - let entropy = try? BIP39Mnemonic.Entropy(hex: hex) else { + let entropy = try? BIP39(hex: hex) else { return nil } diff --git a/Sources/LibAuk/Utils/Keys.swift b/Sources/LibAuk/Utils/Keys.swift index 5aa6fca..1aafca0 100644 --- a/Sources/LibAuk/Utils/Keys.swift +++ b/Sources/LibAuk/Utils/Keys.swift @@ -6,65 +6,65 @@ // import Foundation -import LibWally import Web3 +import BCFoundation import KukaiCoreSwift import CryptoKit import TweetNacl class Keys { - static func fingerprint(mnemonic: BIP39Mnemonic, passphrase: String? = "") -> String? { - guard let hdMasterKey = try? HDKey(seed: mnemonic.seedHex(passphrase: passphrase ?? "")) else { return nil } + static func fingerprint(bip39: BIP39, passphrase: String? = "") -> String? { + guard let hdMasterKey = try? HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) else { return nil } return hdMasterKey.fingerprint.hexString } static func validMnemonicArray(_ words: [String]) -> Bool { - guard (try? BIP39Mnemonic(words: words)) != nil else { return false } + guard (try? BIP39(words: words).data) != nil else { return false } return true } static func validMnemonicString(_ words: String) -> Bool { - guard (try? BIP39Mnemonic(words: words)) != nil else { return false } + guard (try? BIP39(words: words).data) != nil else { return false } return true } static func entropy(_ words: [String]) -> Data? { - guard let mnemonic = try? BIP39Mnemonic(words: words) else { return nil } + guard let mnemonic = try? BIP39(words: words).data else { return nil } return mnemonic.entropy.data } static func entropy(_ words: String) -> Data? { - guard let mnemonic = try? BIP39Mnemonic(words: words) else { return nil } + guard let mnemonic = try? BIP39(words: words)?.data else { return nil } return mnemonic.entropy.data } - static func mnemonic(_ entropy: Data) -> BIP39Mnemonic? { - let bip39entropy = BIP39Mnemonic.Entropy(entropy) + static func mnemonic(_ entropy: Data) -> BIP39? { + let bip39entropy = BIP39(data: entropy) - return try? BIP39Mnemonic(entropy: bip39entropy) + return bip39entropy } - static func accountDIDPrivateKey(mnemonic: BIP39Mnemonic, passphrase: String? = "") throws -> Secp256k1.Signing.PrivateKey { - let masterKey = try HDKey(seed: mnemonic.seedHex(passphrase: passphrase ?? "")) - let derivationPath = try BIP32Path(string: Constant.accountDerivationPath) + static func accountDIDPrivateKey(bip39: BIP39, passphrase: String? = "") throws -> Secp256k1.Signing.PrivateKey { + let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) + let derivationPath = try DerivationPath(string: Constant.accountDerivationPath) let account = try masterKey.derive(using: derivationPath) - guard let privateKey = account.privKey?.data.bytes else { + guard let privateKey = account.privateKey?.data.bytes else { throw LibAukError.keyDerivationError } return try Secp256k1.Signing.PrivateKey(rawRepresentation: privateKey) } - static func encryptionPrivateKey(mnemonic: BIP39Mnemonic, passphrase: String? = "") throws -> Secp256k1.Signing.PrivateKey { - let masterKey = try HDKey(seed: mnemonic.seedHex(passphrase: passphrase ?? "")) - let derivationPath = try BIP32Path(string: Constant.encryptionKeyDerivationPath) + static func encryptionPrivateKey(bip39: BIP39, passphrase: String? = "") throws -> Secp256k1.Signing.PrivateKey { + let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) + let derivationPath = try DerivationPath(string: Constant.encryptionKeyDerivationPath) let keyPair = try masterKey.derive(using: derivationPath) guard let privateKey = keyPair.privKey?.data.bytes else { @@ -74,37 +74,37 @@ class Keys { return try Secp256k1.Signing.PrivateKey(rawRepresentation: privateKey) } - static func ethereumPrivateKey(mnemonic: BIP39Mnemonic, passphrase: String? = "") throws -> EthereumPrivateKey { - let masterKey = try HDKey(seed: mnemonic.seedHex(passphrase: passphrase ?? "")) - let derivationPath = try BIP32Path(string: Constant.ethDerivationPath) - let account = try masterKey.derive(using: derivationPath) + static func ethereumPrivateKey(bip39: BIP39, passphrase: String? = "") throws -> EthereumPrivateKey { + let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) + let derivationPath = try DerivationPath(string: Constant.ethDerivationPath) + let account = try HDKey(parent: masterKey, childDerivationPath: derivationPath) - guard let privateKey = account.privKey?.data.bytes else { + guard let privateKey = account.privateKey?.data.bytes else { throw LibAukError.keyDerivationError } return try EthereumPrivateKey(privateKey) } - static func ethereumPrivateKeyWithIndex(mnemonic: BIP39Mnemonic, passphrase: String? = "", index: Int) throws -> EthereumPrivateKey { - let masterKey = try HDKey(seed: mnemonic.seedHex(passphrase: passphrase ?? "")) + static func ethereumPrivateKeyWithIndex(bip39: BIP39, passphrase: String? = "", index: Int) throws -> EthereumPrivateKey { + let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) let path = "m/44'/60'/0'/0/\(index)" - let derivationPath = try BIP32Path(string: path) - let account = try masterKey.derive(using: derivationPath) + let derivationPath = try DerivationPath(string: path) + let account = try HDKey(parent: masterKey, childDerivationPath: derivationPath) - guard let privateKey = account.privKey?.data.bytes else { + guard let privateKey = account.privateKey?.data.bytes else { throw LibAukError.keyDerivationError } return try EthereumPrivateKey(privateKey) } - static func tezosWallet(mnemonic: BIP39Mnemonic, passphrase: String? = "") -> HDWallet? { - HDWallet.create(withMnemonic: mnemonic.words.joined(separator: " "), passphrase: passphrase ?? "") + static func tezosWallet(bip39: BIP39, passphrase: String? = "") -> HDWallet? { + HDWallet.create(withMnemonic: bip39.mnemonic, passphrase: passphrase ?? "") } - static func tezosWalletWithIndex(mnemonic: BIP39Mnemonic, passphrase: String? = "", index: Int) -> HDWallet? { + static func tezosWalletWithIndex(bip39: BIP39, passphrase: String? = "", index: Int) -> HDWallet? { let path = "m/44'/1729'/\(index)'/0'" - return HDWallet.create(withMnemonic: mnemonic.words.joined(separator: " "), passphrase: passphrase ?? "", derivationPath: path) + return HDWallet.create(withMnemonic: bip39.mnemonic, passphrase: passphrase ?? "", derivationPath: path) } } diff --git a/Tests/LibAukTests/Storage/SecureStorage_Tests.swift b/Tests/LibAukTests/Storage/SecureStorage_Tests.swift index ac0709a..06e48c9 100644 --- a/Tests/LibAukTests/Storage/SecureStorage_Tests.swift +++ b/Tests/LibAukTests/Storage/SecureStorage_Tests.swift @@ -7,8 +7,8 @@ import Foundation import XCTest -import LibWally import Combine +import BCFoundation import Web3 import URKit @testable import LibAuk @@ -82,11 +82,11 @@ class SecureStorage_Tests: XCTestCase { func testIsWalletCreatedSuccessfully() throws { let words = "daring mix cradle palm crowd sea observe whisper rubber either uncle oak" let seed = Seed(data: Keys.entropy(words)!, name: "", creationDate: Date(), passphrase: "") - let mnemonic = Keys.mnemonic(seed.data)! + let bip39 = Keys.mnemonic(seed.data)! var seedPublicData = SeedPublicData(ethAddress: "0xA00cbE6a45102135A210F231901faA6c05D51465", creationDate: Date(), name: "", did: "did:key:zQ3shUnBWE7Dkskaozsnzsb78kVcgQFbtXf7zdCCDN3qepBGL", preGenerateEthAddress: [:], tezosPublicKeys: [:]) - let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(mnemonic: mnemonic, passphrase: "") - let encryptionPrivateKey = try Keys.encryptionPrivateKey(mnemonic: mnemonic, passphrase: "") + let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(bip39: bip39, passphrase: "") + let encryptionPrivateKey = try Keys.encryptionPrivateKey(bip39: bip39, passphrase: "") seedPublicData.encryptionPrivateKey = encryptionPrivateKey seedPublicData.accountDIDPrivateKey = accountDIDPrivateKey let seedPublicDataRaw = try JSONEncoder().encode(seedPublicData) @@ -113,11 +113,11 @@ class SecureStorage_Tests: XCTestCase { func testGetETHAddressSuccessfully() throws { let words = "daring mix cradle palm crowd sea observe whisper rubber either uncle oak" let seed = Seed(data: Keys.entropy(words)!, name: "", creationDate: Date(), passphrase: "") - let mnemonic = Keys.mnemonic(seed.data)! + let bip39 = Keys.mnemonic(seed.data)! var seedPublicData = SeedPublicData(ethAddress: "0xA00cbE6a45102135A210F231901faA6c05D51465", creationDate: Date(), name: "", did: "did:key:zQ3shUnBWE7Dkskaozsnzsb78kVcgQFbtXf7zdCCDN3qepBGL", preGenerateEthAddress: [:], tezosPublicKeys: [:]) - let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(mnemonic: mnemonic, passphrase: "") - let encryptionPrivateKey = try Keys.encryptionPrivateKey(mnemonic: mnemonic, passphrase: "") + let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(bip39: bip39, passphrase: "") + let encryptionPrivateKey = try Keys.encryptionPrivateKey(bip39: bip39, passphrase: "") seedPublicData.encryptionPrivateKey = encryptionPrivateKey seedPublicData.accountDIDPrivateKey = accountDIDPrivateKey let seedPublicDataRaw = try JSONEncoder().encode(seedPublicData) @@ -129,11 +129,11 @@ class SecureStorage_Tests: XCTestCase { func testGetAccountDIDSuccessfully() throws { let words = "daring mix cradle palm crowd sea observe whisper rubber either uncle oak" let seed = Seed(data: Keys.entropy(words)!, name: "", creationDate: Date(), passphrase: "") - let mnemonic = Keys.mnemonic(seed.data)! + let bip39 = Keys.mnemonic(seed.data)! var seedPublicData = SeedPublicData(ethAddress: "0xA00cbE6a45102135A210F231901faA6c05D51465", creationDate: Date(), name: "", did: "did:key:zQ3shUnBWE7Dkskaozsnzsb78kVcgQFbtXf7zdCCDN3qepBGL", preGenerateEthAddress: [:], tezosPublicKeys: [:]) - let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(mnemonic: mnemonic, passphrase: "") - let encryptionPrivateKey = try Keys.encryptionPrivateKey(mnemonic: mnemonic, passphrase: "") + let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(bip39: bip39, passphrase: "") + let encryptionPrivateKey = try Keys.encryptionPrivateKey(bip39: bip39, passphrase: "") seedPublicData.encryptionPrivateKey = encryptionPrivateKey seedPublicData.accountDIDPrivateKey = accountDIDPrivateKey let seedPublicDataRaw = try JSONEncoder().encode(seedPublicData) @@ -160,11 +160,11 @@ class SecureStorage_Tests: XCTestCase { func testGetAccountDIDSignatureSuccessfully() throws { let words = "daring mix cradle palm crowd sea observe whisper rubber either uncle oak" let seed = Seed(data: Keys.entropy(words)!, name: "", creationDate: Date(), passphrase: "") - let mnemonic = Keys.mnemonic(seed.data)! + let bip39 = Keys.mnemonic(seed.data)! var seedPublicData = SeedPublicData(ethAddress: "0xA00cbE6a45102135A210F231901faA6c05D51465", creationDate: Date(), name: "", did: "did:key:zQ3shUnBWE7Dkskaozsnzsb78kVcgQFbtXf7zdCCDN3qepBGL", preGenerateEthAddress: [:], tezosPublicKeys: [:]) - let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(mnemonic: mnemonic, passphrase: "") - let encryptionPrivateKey = try Keys.encryptionPrivateKey(mnemonic: mnemonic, passphrase: "") + let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(bip39: bip39, passphrase: "") + let encryptionPrivateKey = try Keys.encryptionPrivateKey(bip39: bip39, passphrase: "") seedPublicData.encryptionPrivateKey = encryptionPrivateKey seedPublicData.accountDIDPrivateKey = accountDIDPrivateKey let seedPublicDataRaw = try JSONEncoder().encode(seedPublicData) @@ -409,11 +409,11 @@ class SecureStorage_Tests: XCTestCase { func testRemoveKeysSuccessfully() throws { let words = "daring mix cradle palm crowd sea observe whisper rubber either uncle oak" let seed = Seed(data: Keys.entropy(words)!, name: "", creationDate: Date(), passphrase: "") - let mnemonic = Keys.mnemonic(seed.data)! + let bip39 = Keys.mnemonic(seed.data)! var seedPublicData = SeedPublicData(ethAddress: "0xA00cbE6a45102135A210F231901faA6c05D51465", creationDate: Date(), name: "", did: "did:key:zQ3shUnBWE7Dkskaozsnzsb78kVcgQFbtXf7zdCCDN3qepBGL", preGenerateEthAddress: [:], tezosPublicKeys: [:]) - let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(mnemonic: mnemonic, passphrase: "") - let encryptionPrivateKey = try Keys.encryptionPrivateKey(mnemonic: mnemonic, passphrase: "") + let accountDIDPrivateKey = try Keys.accountDIDPrivateKey(bip39: bip39, passphrase: "") + let encryptionPrivateKey = try Keys.encryptionPrivateKey(bip39: bip39, passphrase: "") seedPublicData.encryptionPrivateKey = encryptionPrivateKey seedPublicData.accountDIDPrivateKey = accountDIDPrivateKey let seedPublicDataRaw = try JSONEncoder().encode(seedPublicData) From 38001c0ab335bfcfd7c41a66f7236c42ef05f5f7 Mon Sep 17 00:00:00 2001 From: phuoc Date: Tue, 21 May 2024 16:16:51 +0700 Subject: [PATCH 02/13] swift tool version Signed-off-by: phuoc --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 89642ae..d0480de 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription From 544c66d22e21c13a87e28d972eb668ccc992f367 Mon Sep 17 00:00:00 2001 From: phuocbitmark <110799144+phuocbitmark@users.noreply.github.com> Date: Tue, 21 May 2024 16:30:24 +0700 Subject: [PATCH 03/13] Update swift.yml upgrade xcode version --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 73af1a7..eb0fb31 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -14,7 +14,7 @@ jobs: steps: - uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '14.0' + xcode-version: '15.0' - uses: actions/checkout@v2 - name: Build run: xcodebuild -scheme LibAuk build -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' From 9df9ffba18f0337752e05e238489b22efb56feb7 Mon Sep 17 00:00:00 2001 From: phuoc Date: Tue, 21 May 2024 16:31:59 +0700 Subject: [PATCH 04/13] feat: use macos 13 Signed-off-by: phuoc --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index eb0fb31..0f47e35 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -9,7 +9,7 @@ on: jobs: build: - runs-on: macos-12 + runs-on: macos-13 steps: - uses: maxim-lobanov/setup-xcode@v1 From 738f871c0e0ea8a444930a82f6953590416d1aec Mon Sep 17 00:00:00 2001 From: phuoc Date: Tue, 21 May 2024 16:57:48 +0700 Subject: [PATCH 05/13] name package Signed-off-by: phuoc --- Package.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index d0480de..e2f8a07 100644 --- a/Package.swift +++ b/Package.swift @@ -14,11 +14,13 @@ let package = Package( ], dependencies: [ .package(name: "Web3.swift", url: "https://github.com/bitmark-inc/Web3.swift.git", .branch("master")), - .package(url: "https://github.com/BlockchainCommons/URKit.git", .exact("14.0.2")), + .package(url: "https://github.com/BlockchainCommons/URKit.git", from: "14.0.2"), .package(url: "https://github.com/keefertaylor/Base58Swift.git", from: "2.1.0"), .package(name: "KukaiCoreSwift", url: "https://github.com/autonomy-system/kukai-core-swift.git", .branch("main")), .package(name: "TweetNacl", url: "https://github.com/bitmark-inc/tweetnacl-swiftwrap", branch: "master"), - .package(url: "https://github.com/BlockchainCommons/BCSwiftFoundation.git", .branch("master")) + .package(url: "https://github.com/BlockchainCommons/BCSwiftFoundation.git", .branch("master")), + .package(name: "secp256k1-zkp.swift", url: "https://github.com/BlockchainCommons/secp256k1-zkp.swift.git",from: "0.5.1"), + .package(name: "secp256k1.swift", url: "https://github.com/Boilertalk/secp256k1.swift.git", from: "0.1.7") // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), ], @@ -34,6 +36,8 @@ let package = Package( .product(name: "Base58Swift", package: "Base58Swift"), .product(name: "TweetNacl", package: "TweetNacl"), .product(name: "BCFoundation", package: "BCSwiftFoundation"), + .product(name: "secp256k1_zkp", package: "secp256k1-zkp.swift"), + .product(name: "secp256k1_swift", package: "secp256k1.swift") ]), .testTarget( name: "LibAukTests", From cc1f98b71b0da03a526e5e998e25e0c821fa0397 Mon Sep 17 00:00:00 2001 From: phuoc Date: Tue, 21 May 2024 17:02:03 +0700 Subject: [PATCH 06/13] edit package name Signed-off-by: phuoc --- Sources/LibAuk/Utils/secp256k1/Secp256k1.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift b/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift index 5fde27e..d153328 100644 --- a/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift +++ b/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift @@ -8,7 +8,7 @@ import Foundation import CryptoKit -import secp256k1 +import secp256k1_swift public enum Secp256k1 { } From 007e0ca527517cbbde1a367a9d7d521ffcd6400c Mon Sep 17 00:00:00 2001 From: phuoc Date: Tue, 21 May 2024 17:15:55 +0700 Subject: [PATCH 07/13] remove one lib Signed-off-by: phuoc --- Package.swift | 12 +++++------- Sources/LibAuk/Utils/secp256k1/Secp256k1.swift | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Package.swift b/Package.swift index e2f8a07..ae0acb1 100644 --- a/Package.swift +++ b/Package.swift @@ -13,14 +13,13 @@ let package = Package( targets: ["LibAuk"]), ], dependencies: [ - .package(name: "Web3.swift", url: "https://github.com/bitmark-inc/Web3.swift.git", .branch("master")), + .package(name: "Web3.swift", url: "https://github.com/bitmark-inc/Web3.swift.git", branch: "master"), .package(url: "https://github.com/BlockchainCommons/URKit.git", from: "14.0.2"), .package(url: "https://github.com/keefertaylor/Base58Swift.git", from: "2.1.0"), - .package(name: "KukaiCoreSwift", url: "https://github.com/autonomy-system/kukai-core-swift.git", .branch("main")), + .package(name: "KukaiCoreSwift", url: "https://github.com/autonomy-system/kukai-core-swift.git", branch: "main"), .package(name: "TweetNacl", url: "https://github.com/bitmark-inc/tweetnacl-swiftwrap", branch: "master"), - .package(url: "https://github.com/BlockchainCommons/BCSwiftFoundation.git", .branch("master")), - .package(name: "secp256k1-zkp.swift", url: "https://github.com/BlockchainCommons/secp256k1-zkp.swift.git",from: "0.5.1"), - .package(name: "secp256k1.swift", url: "https://github.com/Boilertalk/secp256k1.swift.git", from: "0.1.7") + .package(url: "https://github.com/BlockchainCommons/BCSwiftFoundation.git", branch: "master"), + .package(url: "https://github.com/BlockchainCommons/secp256k1-zkp.swift.git",from: "0.5.1") // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), ], @@ -36,8 +35,7 @@ let package = Package( .product(name: "Base58Swift", package: "Base58Swift"), .product(name: "TweetNacl", package: "TweetNacl"), .product(name: "BCFoundation", package: "BCSwiftFoundation"), - .product(name: "secp256k1_zkp", package: "secp256k1-zkp.swift"), - .product(name: "secp256k1_swift", package: "secp256k1.swift") + .product(name: "secp256k1", package: "secp256k1-zkp.swift") ]), .testTarget( name: "LibAukTests", diff --git a/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift b/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift index d153328..5fde27e 100644 --- a/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift +++ b/Sources/LibAuk/Utils/secp256k1/Secp256k1.swift @@ -8,7 +8,7 @@ import Foundation import CryptoKit -import secp256k1_swift +import secp256k1 public enum Secp256k1 { } From 994d95b35cb118c6f9fe07c49646c73cfc310ad6 Mon Sep 17 00:00:00 2001 From: phuoc Date: Wed, 22 May 2024 11:48:10 +0700 Subject: [PATCH 08/13] feat: update kukai lib Signed-off-by: phuoc --- Package.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index ae0acb1..6e1f201 100644 --- a/Package.swift +++ b/Package.swift @@ -16,10 +16,9 @@ let package = Package( .package(name: "Web3.swift", url: "https://github.com/bitmark-inc/Web3.swift.git", branch: "master"), .package(url: "https://github.com/BlockchainCommons/URKit.git", from: "14.0.2"), .package(url: "https://github.com/keefertaylor/Base58Swift.git", from: "2.1.0"), - .package(name: "KukaiCoreSwift", url: "https://github.com/autonomy-system/kukai-core-swift.git", branch: "main"), + .package(name: "KukaiCoreSwift", url: "https://github.com/autonomy-system/kukai-core-swift.git", branch: "migrate_secp256"), .package(name: "TweetNacl", url: "https://github.com/bitmark-inc/tweetnacl-swiftwrap", branch: "master"), - .package(url: "https://github.com/BlockchainCommons/BCSwiftFoundation.git", branch: "master"), - .package(url: "https://github.com/BlockchainCommons/secp256k1-zkp.swift.git",from: "0.5.1") + .package(url: "https://github.com/BlockchainCommons/BCSwiftFoundation.git", branch: "master") // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), ], @@ -34,8 +33,7 @@ let package = Package( .product(name: "KukaiCoreSwift", package: "KukaiCoreSwift"), .product(name: "Base58Swift", package: "Base58Swift"), .product(name: "TweetNacl", package: "TweetNacl"), - .product(name: "BCFoundation", package: "BCSwiftFoundation"), - .product(name: "secp256k1", package: "secp256k1-zkp.swift") + .product(name: "BCFoundation", package: "BCSwiftFoundation") ]), .testTarget( name: "LibAukTests", From f5db6f61a0de600d83111625dfb3c51260f92bca Mon Sep 17 00:00:00 2001 From: phuoc Date: Wed, 22 May 2024 13:44:38 +0700 Subject: [PATCH 09/13] feat: update web3.swift lib --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 6e1f201..5dd4cc3 100644 --- a/Package.swift +++ b/Package.swift @@ -13,7 +13,7 @@ let package = Package( targets: ["LibAuk"]), ], dependencies: [ - .package(name: "Web3.swift", url: "https://github.com/bitmark-inc/Web3.swift.git", branch: "master"), + .package(name: "Web3.swift", url: "https://github.com/bitmark-inc/Web3.swift.git", branch: "migrate_secp256"), .package(url: "https://github.com/BlockchainCommons/URKit.git", from: "14.0.2"), .package(url: "https://github.com/keefertaylor/Base58Swift.git", from: "2.1.0"), .package(name: "KukaiCoreSwift", url: "https://github.com/autonomy-system/kukai-core-swift.git", branch: "migrate_secp256"), From 299e1491c52e8f5ef643e917be2db18f842edc6c Mon Sep 17 00:00:00 2001 From: phuoc Date: Wed, 22 May 2024 13:49:59 +0700 Subject: [PATCH 10/13] feat: upgrade ios version 16 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 5dd4cc3..20b1d78 100644 --- a/Package.swift +++ b/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "LibAuk", - platforms: [.iOS("15.0")], + platforms: [.iOS("16.0")], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( From 3a839983717efc47048fa6a5603a0f65a04ff26d Mon Sep 17 00:00:00 2001 From: phuoc Date: Wed, 22 May 2024 14:57:21 +0700 Subject: [PATCH 11/13] fix: migrate HDKey --- Package.swift | 2 +- Sources/LibAuk/Storage/SecureStorage.swift | 5 +- Sources/LibAuk/Utils/Keys.swift | 84 +++++++++++++--------- 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/Package.swift b/Package.swift index 20b1d78..ce0a045 100644 --- a/Package.swift +++ b/Package.swift @@ -30,8 +30,8 @@ let package = Package( dependencies: [ .product(name: "Web3", package: "Web3.swift"), .product(name: "URKit", package: "URKit"), - .product(name: "KukaiCoreSwift", package: "KukaiCoreSwift"), .product(name: "Base58Swift", package: "Base58Swift"), + .product(name: "KukaiCoreSwift", package: "KukaiCoreSwift"), .product(name: "TweetNacl", package: "TweetNacl"), .product(name: "BCFoundation", package: "BCSwiftFoundation") ]), diff --git a/Sources/LibAuk/Storage/SecureStorage.swift b/Sources/LibAuk/Storage/SecureStorage.swift index d99c8bd..60e7ed0 100644 --- a/Sources/LibAuk/Storage/SecureStorage.swift +++ b/Sources/LibAuk/Storage/SecureStorage.swift @@ -4,7 +4,6 @@ // // Created by Ho Hien on 8/9/21. // - import Foundation import Combine import BCFoundation @@ -442,7 +441,7 @@ class SecureStorage: SecureStorageProtocol { .eraseToAnyPublisher() } - private func getEncryptKey(usingLegacy: Bool = false) -> AnyPublisher { + private func getEncryptKey(usingLegacy: Bool = false) -> AnyPublisher { return Future { promise in guard let seedPublicData = self.getSeedPublicData() else { promise(.failure(LibAukError.emptyKey)) @@ -455,7 +454,7 @@ class SecureStorage: SecureStorageProtocol { if (usingLegacy) { return SymmetricKey(data: privateKey.rawRepresentation) } else { - let encryptionKey = HKDF.deriveKey(inputKeyMaterial: SymmetricKey(data: privateKey.rawRepresentation), salt: Data(), outputByteCount: 32) + let encryptionKey = HKDF.deriveKey(inputKeyMaterial: SymmetricKey(data: privateKey.rawRepresentation), salt: Data(), outputByteCount: 32) return encryptionKey } }) diff --git a/Sources/LibAuk/Utils/Keys.swift b/Sources/LibAuk/Utils/Keys.swift index 1aafca0..7d80f5d 100644 --- a/Sources/LibAuk/Utils/Keys.swift +++ b/Sources/LibAuk/Utils/Keys.swift @@ -15,33 +15,26 @@ import TweetNacl class Keys { static func fingerprint(bip39: BIP39, passphrase: String? = "") -> String? { - guard let hdMasterKey = try? HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) else { return nil } - return hdMasterKey.fingerprint.hexString + guard let hdMasterKey = try? HDKey(bip39Seed: BIP39.Seed(bip39: bip39, passphrase: passphrase ?? "")) else { return nil } + + return hdMasterKey.keyFingerprint.hex } static func validMnemonicArray(_ words: [String]) -> Bool { - guard (try? BIP39(words: words).data) != nil else { return false } - - return true + return BIP39(words: words)?.data != nil } static func validMnemonicString(_ words: String) -> Bool { - guard (try? BIP39(words: words).data) != nil else { return false } - - return true + return BIP39(mnemonic: words)?.data != nil } static func entropy(_ words: [String]) -> Data? { - guard let mnemonic = try? BIP39(words: words).data else { return nil } - - return mnemonic.entropy.data + return BIP39(words: words)?.data } static func entropy(_ words: String) -> Data? { - guard let mnemonic = try? BIP39(words: words)?.data else { return nil } - - return mnemonic.entropy.data + return BIP39(mnemonic: words)?.data } static func mnemonic(_ entropy: Data) -> BIP39? { @@ -51,50 +44,73 @@ class Keys { } static func accountDIDPrivateKey(bip39: BIP39, passphrase: String? = "") throws -> Secp256k1.Signing.PrivateKey { - let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) - let derivationPath = try DerivationPath(string: Constant.accountDerivationPath) - let account = try masterKey.derive(using: derivationPath) - - guard let privateKey = account.privateKey?.data.bytes else { + guard let masterKey = try? HDKey(bip39Seed: BIP39.Seed(bip39: bip39, passphrase: passphrase ?? "")) else { + throw LibAukError.keyCreationError + } + guard let derivationPath = DerivationPath(string: Constant.accountDerivationPath) else { throw LibAukError.keyDerivationError } + guard let account = try? HDKey(parent: masterKey, childDerivationPath: derivationPath) else { + throw LibAukError.keyCreationError + } + + guard let privateKey = account.base58PrivateKey?.bytes else { + throw LibAukError.keyCreationError + } return try Secp256k1.Signing.PrivateKey(rawRepresentation: privateKey) } static func encryptionPrivateKey(bip39: BIP39, passphrase: String? = "") throws -> Secp256k1.Signing.PrivateKey { - let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) - let derivationPath = try DerivationPath(string: Constant.encryptionKeyDerivationPath) - let keyPair = try masterKey.derive(using: derivationPath) - - guard let privateKey = keyPair.privKey?.data.bytes else { + guard let masterKey = try? HDKey(bip39Seed: BIP39.Seed(bip39: bip39, passphrase: passphrase ?? "")) else { + throw LibAukError.keyCreationError + } + guard let derivationPath = DerivationPath(string: Constant.encryptionKeyDerivationPath) else { throw LibAukError.keyDerivationError } + guard let keyPair = try? HDKey(parent: masterKey, childDerivationPath: derivationPath) else { + throw LibAukError.keyCreationError + } + guard let privateKey = keyPair.base58PrivateKey?.bytes else { + throw LibAukError.keyCreationError + } return try Secp256k1.Signing.PrivateKey(rawRepresentation: privateKey) } static func ethereumPrivateKey(bip39: BIP39, passphrase: String? = "") throws -> EthereumPrivateKey { - let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) - let derivationPath = try DerivationPath(string: Constant.ethDerivationPath) - let account = try HDKey(parent: masterKey, childDerivationPath: derivationPath) - - guard let privateKey = account.privateKey?.data.bytes else { + guard let masterKey = try? HDKey(bip39Seed: BIP39.Seed(bip39: bip39, passphrase: passphrase ?? "")) else { + throw LibAukError.keyCreationError + } + guard let derivationPath = DerivationPath(string: Constant.ethDerivationPath) else { throw LibAukError.keyDerivationError } + guard let account = try? HDKey(parent: masterKey, childDerivationPath: derivationPath) else { + throw LibAukError.keyCreationError + } + + guard let privateKey = account.base58PrivateKey?.bytes else { + throw LibAukError.keyCreationError + } return try EthereumPrivateKey(privateKey) } static func ethereumPrivateKeyWithIndex(bip39: BIP39, passphrase: String? = "", index: Int) throws -> EthereumPrivateKey { - let masterKey = try HDKey(seed: BIP39(bip39: bip39, passphrase: passphrase ?? "")) + guard let masterKey = try? HDKey(bip39Seed: BIP39.Seed(bip39: bip39, passphrase: passphrase ?? "")) else { + throw LibAukError.keyCreationError + } let path = "m/44'/60'/0'/0/\(index)" - let derivationPath = try DerivationPath(string: path) - let account = try HDKey(parent: masterKey, childDerivationPath: derivationPath) - - guard let privateKey = account.privateKey?.data.bytes else { + guard let derivationPath = DerivationPath(string: path) else { throw LibAukError.keyDerivationError } + guard let account = try? HDKey(parent: masterKey, childDerivationPath: derivationPath) else { + throw LibAukError.keyCreationError + } + + guard let privateKey = account.base58PublicKey?.bytes else { + throw LibAukError.keyCreationError + } return try EthereumPrivateKey(privateKey) } From 2e5604b7e3ec6d49f6733e50b5cc810f3bf995fb Mon Sep 17 00:00:00 2001 From: phuoc Date: Wed, 22 May 2024 17:36:54 +0700 Subject: [PATCH 12/13] fix: add import --- Sources/LibAuk/LibAuk.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/LibAuk/LibAuk.swift b/Sources/LibAuk/LibAuk.swift index 359081f..29d823e 100644 --- a/Sources/LibAuk/LibAuk.swift +++ b/Sources/LibAuk/LibAuk.swift @@ -7,6 +7,7 @@ import Foundation import Combine +import BCFoundation public class LibAuk { From 6f9572adb36f0d0914da45e922e8c662e0a94f78 Mon Sep 17 00:00:00 2001 From: phuoc Date: Thu, 23 May 2024 15:20:04 +0700 Subject: [PATCH 13/13] test: migrate cbor --- Sources/LibAuk/Model/Seed.swift | 11 ++++-- Sources/LibAuk/Storage/SecureStorage.swift | 46 +++++++++++----------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/Sources/LibAuk/Model/Seed.swift b/Sources/LibAuk/Model/Seed.swift index e95c49e..119ad81 100644 --- a/Sources/LibAuk/Model/Seed.swift +++ b/Sources/LibAuk/Model/Seed.swift @@ -7,6 +7,7 @@ import Foundation import URKit +import OrderedCollections public class Seed: Codable { public let data: Data @@ -20,6 +21,7 @@ public class Seed: Codable { self.creationDate = creationDate self.passphrase = passphrase } + /* func cbor(nameLimit: Int? = nil, noteLimit: Int? = nil) -> CBOR { var a: [OrderedMap.Entry] = [ @@ -82,13 +84,13 @@ public class Seed: Codable { while let element = iterator.next() { let (indexElement, valueElement) = element - guard case let CBOR.unsignedInt(index) = indexElement else { + guard case let CBOR.unsigned(index) = indexElement else { throw LibAukError.other(reason: "ur:crypto-seed: CBOR contains invalid keys.") } switch index { case 1: - guard case let CBOR.data(data) = valueElement else { + guard case let CBOR.bytes(data) = valueElement else { throw LibAukError.other(reason: "ur:crypto-seed: CBOR doesn't contain data field.") } seedData = data @@ -98,12 +100,12 @@ public class Seed: Codable { } creationDate = d case 3: - guard case let CBOR.utf8String(s) = valueElement else { + guard case let CBOR.text(s) = valueElement else { throw LibAukError.other(reason: "ur:crypto-seed: Name field doesn't contain a string.") } name = s case 4: - guard case let CBOR.utf8String(s) = valueElement else { + guard case let CBOR.text(s) = valueElement else { throw LibAukError.other(reason: "ur:crypto-seed: Passphrase field doesn't contain a string.") } passphrase = s @@ -115,4 +117,5 @@ public class Seed: Codable { self.init(data: seedData!, name: name, creationDate: creationDate, passphrase: passphrase) } + */ } diff --git a/Sources/LibAuk/Storage/SecureStorage.swift b/Sources/LibAuk/Storage/SecureStorage.swift index 60e7ed0..eda7c46 100644 --- a/Sources/LibAuk/Storage/SecureStorage.swift +++ b/Sources/LibAuk/Storage/SecureStorage.swift @@ -170,9 +170,9 @@ class SecureStorage: SecureStorageProtocol { } let seed = Seed(data: entropy, name: name, creationDate: Date(), passphrase: passphrase) - let seedData = seed.urString.utf8 + //let seedData = seed.urString.utf8 - self.keychain.set(seedData, forKey: Constant.KeychainKey.seed, isSync: true, isPrivate: isPrivate) + self.keychain.set(seed.data, forKey: Constant.KeychainKey.seed, isSync: true, isPrivate: isPrivate) promise(.success(seed)) } .flatMap { seed in @@ -195,9 +195,9 @@ class SecureStorage: SecureStorageProtocol { if let entropy = Keys.entropy(words) { let seed = Seed(data: entropy, name: name, creationDate: creationDate ?? Date(), passphrase: passphrase) - let seedData = seed.urString.utf8 + //let seedData = seed.urString.utf8 - self.keychain.set(seedData, forKey: Constant.KeychainKey.seed, isSync: true, isPrivate: isPrivate) + self.keychain.set(seed.data, forKey: Constant.KeychainKey.seed, isSync: true, isPrivate: isPrivate) promise(.success(seed)) } else { promise(.failure(LibAukError.invalidMnemonicError)) @@ -217,7 +217,7 @@ class SecureStorage: SecureStorageProtocol { func setSeed(seed: Seed, isPrivate: Bool) -> AnyPublisher { Future { promise in - guard self.keychain.set(seed.urString.utf8, forKey: Constant.KeychainKey.seed, isSync: true, isPrivate: isPrivate) else { + guard self.keychain.set(seed.data, forKey: Constant.KeychainKey.seed, isSync: true, isPrivate: isPrivate) else { promise(.success(false)) return } @@ -311,8 +311,8 @@ class SecureStorage: SecureStorageProtocol { } .catch({ error in Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -336,8 +336,8 @@ class SecureStorage: SecureStorageProtocol { private func getSeed() -> AnyPublisher { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -349,8 +349,8 @@ class SecureStorage: SecureStorageProtocol { func ethSign(message: Bytes) -> AnyPublisher<(v: UInt, r: Bytes, s: Bytes), Error> { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -372,8 +372,8 @@ class SecureStorage: SecureStorageProtocol { func ethSignWithIndex(message: Bytes, index: Int) -> AnyPublisher<(v: UInt, r: Bytes, s: Bytes), Error> { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -395,8 +395,8 @@ class SecureStorage: SecureStorageProtocol { func ethSignTransaction(transaction: EthereumTransaction, chainId: EthereumQuantity) -> AnyPublisher { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -419,8 +419,8 @@ class SecureStorage: SecureStorageProtocol { func ethSignTransactionWithIndex(transaction: EthereumTransaction, chainId: EthereumQuantity, index: Int) -> AnyPublisher { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -551,8 +551,8 @@ class SecureStorage: SecureStorageProtocol { func exportSeed() -> AnyPublisher { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -602,8 +602,8 @@ class SecureStorage: SecureStorageProtocol { internal func getTezosWallet() -> AnyPublisher { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return } @@ -624,8 +624,8 @@ class SecureStorage: SecureStorageProtocol { internal func getTezosWalletWithIndex(index: Int) -> AnyPublisher { Future { promise in - guard let seedUR = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), - let seed = try? Seed(urString: seedUR.utf8) else { + guard let data = self.keychain.getData(Constant.KeychainKey.seed, isSync: true), + let seed = try? Seed(data: data, name: self.getName() ?? "") else { promise(.failure(LibAukError.emptyKey)) return }