Skip to content

Commit

Permalink
Merge pull request #12 from soramitsu/feature/factory-interface-impro…
Browse files Browse the repository at this point in the history
…vement

Seed factory improvements
  • Loading branch information
ERussel authored Aug 17, 2020
2 parents 353ce94 + 0f7bdbd commit e9e06e9
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 17 deletions.
2 changes: 1 addition & 1 deletion FearlessUtils.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
7 changes: 7 additions & 0 deletions FearlessUtils/Classes/Crypto/Data+Seed.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation

public extension Data {
var miniSeed: Data {
count > 32 ? Data(self[0..<32]) : self
}
}
13 changes: 8 additions & 5 deletions FearlessUtils/Classes/Crypto/EcdsaKeypairFactory.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation
import IrohaCrypto

public struct EcdsaKeypairFactory: KeypairFactoryProtocol {
public struct EcdsaKeypairFactory: DerivableSeedFactoryProtocol {
static let hdkdPrefix = "Secp256k1HDKD"

let internalFactory = SECKeyFactory()
Expand All @@ -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)
}
}
14 changes: 10 additions & 4 deletions FearlessUtils/Classes/Crypto/Ed25519KeypairFactory.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation
import IrohaCrypto

public struct Ed25519KeypairFactory: KeypairFactoryProtocol {
public struct Ed25519KeypairFactory: DerivableSeedFactoryProtocol {
static let hdkdPrefix = "Ed25519HDKD"

let internalFactory = EDKeyFactory()
Expand All @@ -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)
}
}
10 changes: 10 additions & 0 deletions FearlessUtils/Classes/Crypto/KeypairFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
15 changes: 13 additions & 2 deletions FearlessUtils/Classes/Crypto/SR25519KeypairFactory.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation
import IrohaCrypto

public struct SR25519KeypairFactory: KeypairFactoryProtocol {
public struct SR25519KeypairFactory: DerivableKeypairFactoryProtocol {
let internalFactory = SNKeyFactory()

public init() {}
Expand All @@ -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)
Expand Down
6 changes: 2 additions & 4 deletions FearlessUtils/Classes/Crypto/SeedFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -23,14 +21,14 @@ 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,
password: String) throws -> SeedFactoryResult {
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)
}
}
2 changes: 1 addition & 1 deletion Tests/Crypto/KeypairDeriviationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit e9e06e9

Please sign in to comment.