From da8dc5b0b6942a09d85161f455463a426bed2380 Mon Sep 17 00:00:00 2001 From: Russel Date: Mon, 17 Aug 2020 12:32:17 +0300 Subject: [PATCH 1/2] add derivable secret protocols implementation --- FearlessUtils.podspec | 2 +- .../Classes/Crypto/EcdsaKeypairFactory.swift | 13 ++++++++----- .../Classes/Crypto/Ed25519KeypairFactory.swift | 14 ++++++++++---- FearlessUtils/Classes/Crypto/KeypairFactory.swift | 10 ++++++++++ .../Classes/Crypto/SR25519KeypairFactory.swift | 15 +++++++++++++-- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/FearlessUtils.podspec b/FearlessUtils.podspec index 7dcb460..e953ed1 100644 --- a/FearlessUtils.podspec +++ b/FearlessUtils.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'FearlessUtils' - s.version = '0.5.0' + s.version = '0.6.0' s.summary = 'Utility library that implements clients specific logic to interact with substrate based networks' s.homepage = 'https://github.com/soramitsu/fearless-utils-iOS' diff --git a/FearlessUtils/Classes/Crypto/EcdsaKeypairFactory.swift b/FearlessUtils/Classes/Crypto/EcdsaKeypairFactory.swift index e6deeea..b11720d 100644 --- a/FearlessUtils/Classes/Crypto/EcdsaKeypairFactory.swift +++ b/FearlessUtils/Classes/Crypto/EcdsaKeypairFactory.swift @@ -1,7 +1,7 @@ import Foundation import IrohaCrypto -public struct EcdsaKeypairFactory: KeypairFactoryProtocol { +public struct EcdsaKeypairFactory: DerivableSeedFactoryProtocol { static let hdkdPrefix = "Secp256k1HDKD" let internalFactory = SECKeyFactory() @@ -10,19 +10,22 @@ public struct EcdsaKeypairFactory: KeypairFactoryProtocol { public func createKeypairFromSeed(_ seed: Data, chaincodeList: [Chaincode]) throws -> IRCryptoKeypairProtocol { + let childSeed = try deriveChildSeedFromParent(seed, chaincodeList: chaincodeList) + let childPrivateKey = try SECPrivateKey(rawData: childSeed) + return try internalFactory.derive(fromPrivateKey: childPrivateKey) + } + + public func deriveChildSeedFromParent(_ seed: Data, chaincodeList: [Chaincode]) throws -> Data { let scaleEncoder = ScaleEncoder() try Self.hdkdPrefix.encode(scaleEncoder: scaleEncoder) let prefix = scaleEncoder.encode() - let childSeed = try chaincodeList.reduce(seed) { (currentSeed, chaincode) in + return try chaincodeList.reduce(seed) { (currentSeed, chaincode) in guard chaincode.type == .hard else { throw KeypairFactoryError.unsupportedChaincodeType } return try (prefix + currentSeed + chaincode.data).blake2b32() } - - let childPrivateKey = try SECPrivateKey(rawData: childSeed) - return try internalFactory.derive(fromPrivateKey: childPrivateKey) } } diff --git a/FearlessUtils/Classes/Crypto/Ed25519KeypairFactory.swift b/FearlessUtils/Classes/Crypto/Ed25519KeypairFactory.swift index d6804d4..7b74873 100644 --- a/FearlessUtils/Classes/Crypto/Ed25519KeypairFactory.swift +++ b/FearlessUtils/Classes/Crypto/Ed25519KeypairFactory.swift @@ -1,7 +1,7 @@ import Foundation import IrohaCrypto -public struct Ed25519KeypairFactory: KeypairFactoryProtocol { +public struct Ed25519KeypairFactory: DerivableSeedFactoryProtocol { static let hdkdPrefix = "Ed25519HDKD" let internalFactory = EDKeyFactory() @@ -10,18 +10,24 @@ public struct Ed25519KeypairFactory: KeypairFactoryProtocol { public func createKeypairFromSeed(_ seed: Data, chaincodeList: [Chaincode]) throws -> IRCryptoKeypairProtocol { + let childSeed = try deriveChildSeedFromParent(seed, + chaincodeList: chaincodeList) + + return try internalFactory.derive(fromSeed: childSeed) + } + + public func deriveChildSeedFromParent(_ seed: Data, + chaincodeList: [Chaincode]) throws -> Data { let scaleEncoder = ScaleEncoder() try Self.hdkdPrefix.encode(scaleEncoder: scaleEncoder) let prefix = scaleEncoder.encode() - let childSeed = try chaincodeList.reduce(seed) { (currentSeed, chaincode) in + return try chaincodeList.reduce(seed) { (currentSeed, chaincode) in guard chaincode.type == .hard else { throw KeypairFactoryError.unsupportedChaincodeType } return try (prefix + currentSeed + chaincode.data).blake2b32() } - - return try internalFactory.derive(fromSeed: childSeed) } } diff --git a/FearlessUtils/Classes/Crypto/KeypairFactory.swift b/FearlessUtils/Classes/Crypto/KeypairFactory.swift index 5d127f0..8ac16c9 100644 --- a/FearlessUtils/Classes/Crypto/KeypairFactory.swift +++ b/FearlessUtils/Classes/Crypto/KeypairFactory.swift @@ -8,3 +8,13 @@ enum KeypairFactoryError: Error { public protocol KeypairFactoryProtocol { func createKeypairFromSeed(_ seed: Data, chaincodeList: [Chaincode]) throws -> IRCryptoKeypairProtocol } + +public protocol DerivableKeypairFactoryProtocol: KeypairFactoryProtocol { + func deriveChildKeypairFromParent(_ keypair: IRCryptoKeypairProtocol, + chaincodeList: [Chaincode]) throws -> IRCryptoKeypairProtocol +} + +public protocol DerivableSeedFactoryProtocol: KeypairFactoryProtocol { + func deriveChildSeedFromParent(_ seed: Data, + chaincodeList: [Chaincode]) throws -> Data +} diff --git a/FearlessUtils/Classes/Crypto/SR25519KeypairFactory.swift b/FearlessUtils/Classes/Crypto/SR25519KeypairFactory.swift index 0c9efc5..ed549fb 100644 --- a/FearlessUtils/Classes/Crypto/SR25519KeypairFactory.swift +++ b/FearlessUtils/Classes/Crypto/SR25519KeypairFactory.swift @@ -1,7 +1,7 @@ import Foundation import IrohaCrypto -public struct SR25519KeypairFactory: KeypairFactoryProtocol { +public struct SR25519KeypairFactory: DerivableKeypairFactoryProtocol { let internalFactory = SNKeyFactory() public init() {} @@ -10,7 +10,18 @@ public struct SR25519KeypairFactory: KeypairFactoryProtocol { chaincodeList: [Chaincode]) throws -> IRCryptoKeypairProtocol { let masterKeypair = try internalFactory.createKeypair(fromSeed: seed) - let childKeypair = try chaincodeList.reduce(masterKeypair) { (keypair, chaincode) in + let parentKeypair = IRCryptoKeypair(publicKey: masterKeypair.publicKey(), + privateKey: masterKeypair.privateKey()) + return try deriveChildKeypairFromParent(parentKeypair, chaincodeList: chaincodeList) + } + + public func deriveChildKeypairFromParent(_ keypair: IRCryptoKeypairProtocol, + chaincodeList: [Chaincode]) throws -> IRCryptoKeypairProtocol { + let privateKey = try SNPrivateKey(rawData: keypair.privateKey().rawData()) + let publicKey = try SNPublicKey(rawData: keypair.publicKey().rawData()) + let snKeypair: SNKeypairProtocol = SNKeypair(privateKey: privateKey, publicKey: publicKey) + + let childKeypair = try chaincodeList.reduce(snKeypair) { (keypair, chaincode) in switch chaincode.type { case .soft: return try internalFactory.createKeypairSoft(keypair, chaincode: chaincode.data) From 0f7bdbdf8a759ea33c54d8410dbe82151ca6d963 Mon Sep 17 00:00:00 2001 From: Russel Date: Mon, 17 Aug 2020 15:53:01 +0300 Subject: [PATCH 2/2] fix seed factory --- FearlessUtils/Classes/Crypto/Data+Seed.swift | 7 +++++++ FearlessUtils/Classes/Crypto/SeedFactory.swift | 6 ++---- Tests/Crypto/KeypairDeriviationTests.swift | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 FearlessUtils/Classes/Crypto/Data+Seed.swift diff --git a/FearlessUtils/Classes/Crypto/Data+Seed.swift b/FearlessUtils/Classes/Crypto/Data+Seed.swift new file mode 100644 index 0000000..0c54a23 --- /dev/null +++ b/FearlessUtils/Classes/Crypto/Data+Seed.swift @@ -0,0 +1,7 @@ +import Foundation + +public extension Data { + var miniSeed: Data { + count > 32 ? Data(self[0..<32]) : self + } +} diff --git a/FearlessUtils/Classes/Crypto/SeedFactory.swift b/FearlessUtils/Classes/Crypto/SeedFactory.swift index 2571931..9dcee31 100644 --- a/FearlessUtils/Classes/Crypto/SeedFactory.swift +++ b/FearlessUtils/Classes/Crypto/SeedFactory.swift @@ -9,8 +9,6 @@ public protocol SeedFactoryProtocol { } public struct SeedFactory: SeedFactoryProtocol { - private static let seedLength: Int = 32 - private let seedFactory: SNBIP39SeedCreatorProtocol = SNBIP39SeedCreator() private let mnemonicCreator: IRMnemonicCreatorProtocol @@ -23,7 +21,7 @@ public struct SeedFactory: SeedFactoryProtocol { let mnemonic = try mnemonicCreator.randomMnemonic(strength) let seed = try seedFactory.deriveSeed(from: mnemonic.entropy(), passphrase: password) - return SeedFactoryResult(seed: seed.prefix(Self.seedLength), mnemonic: mnemonic) + return SeedFactoryResult(seed: seed, mnemonic: mnemonic) } public func deriveSeed(from mnemonicWords: String, @@ -31,6 +29,6 @@ public struct SeedFactory: SeedFactoryProtocol { let mnemonic = try mnemonicCreator.mnemonic(fromList: mnemonicWords) let seed = try seedFactory.deriveSeed(from: mnemonic.entropy(), passphrase: password) - return SeedFactoryResult(seed: seed.prefix(Self.seedLength), mnemonic: mnemonic) + return SeedFactoryResult(seed: seed, mnemonic: mnemonic) } } diff --git a/Tests/Crypto/KeypairDeriviationTests.swift b/Tests/Crypto/KeypairDeriviationTests.swift index 786c6c1..bdf9b4c 100644 --- a/Tests/Crypto/KeypairDeriviationTests.swift +++ b/Tests/Crypto/KeypairDeriviationTests.swift @@ -41,7 +41,7 @@ class KeypairDeriviationTests: XCTestCase { let seedResult = try seedFactory.deriveSeed(from: item.mnemonic, password: result.password ?? "") - let keypair = try keypairFactory.createKeypairFromSeed(seedResult.seed, + let keypair = try keypairFactory.createKeypairFromSeed(seedResult.seed.miniSeed, chaincodeList: result.chaincodes) let publicKey = keypair.publicKey().rawData()