Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FLW-1187 BIP 32 support #43

Merged
merged 29 commits into from
Aug 25, 2021
Merged

FLW-1187 BIP 32 support #43

merged 29 commits into from
Aug 25, 2021

Conversation

stas-litvinov
Copy link
Contributor

Add support for BIP32 address derivation

@stas-litvinov stas-litvinov marked this pull request as ready for review August 23, 2021 10:33
import BigInt
import IrohaCrypto

public struct BIP32JunctionFactory: JunctionFactoryProtocol {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have duplicated logic regarding junction parsing compared with JunctionFactory. Consider to turn to the class and make base class with common logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

private func createChaincodeFromJunction(_ junction: String, type: ChaincodeType) throws -> Chaincode {
guard
var numericJunction = UInt32(junction),
numericJunction < 0x80000000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move 0x8... to constants and give appropriate name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -22,6 +22,7 @@ public enum JunctionFactoryError: Error {
case multiplePassphrase
case emptyJunction
case invalidStart
case invalidBIP32Junction
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's create a separate error enum for BIP32

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -18,3 +18,9 @@ public protocol DerivableSeedFactoryProtocol: KeypairFactoryProtocol {
func deriveChildSeedFromParent(_ seed: Data,
chaincodeList: [Chaincode]) throws -> Data
}

public protocol DerivableChaincodeFactoryProtocol: KeypairFactoryProtocol {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we use this guy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should have been removed, ty

@@ -6,6 +6,7 @@ public typealias SeedFactoryResult = (seed: Data, mnemonic: IRMnemonicProtocol)
public protocol SeedFactoryProtocol {
func createSeed(from password: String, strength: IRMnemonicStrength) throws -> SeedFactoryResult
func deriveSeed(from mnemonicWords: String, password: String) throws -> SeedFactoryResult
func deriveNativeSeed(from mnemonicWords: String, password: String) throws -> SeedFactoryResult
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le't move this implementation to a separate factory BIP39SeedFactory and also please implement createSeed function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

public struct BIP32KeyFactory {
private let initialSeed = "Bitcoin seed"
Copy link
Contributor

@ERussel ERussel Aug 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could make it static to prevent from duplication in different instances

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please elaborate more? What is duplicated?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, fixed typos

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

let sourceData: Data = try {
switch chaincode.type {
case .hard:
let padding = try Data(hexString: "0x00")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like overhead, consider to use Data(repeating: 0 count: 1) to remove an option where we can receive exception but it never happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


var privateKeyInt = BigUInt(privateKeySourceData.rawData())

guard privateKeyInt < .secp256k1CurveOrder else {
Copy link
Contributor

@ERussel ERussel Aug 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also require from privateKey not to be zero?

Copy link
Contributor Author

@stas-litvinov stas-litvinov Aug 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I lost it somehow during refactoring


var privateKeyData = privateKeyInt.serialize()

if privateKeyData.count < 32 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider to use SECPrivateKey.length instead of 32

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure


if privateKeyData.count < 32 {
var paddedPrivateKeyData = Data(repeating: 0, count: 32)
paddedPrivateKeyData[(32 - privateKeyData.count)...] = privateKeyData
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider to use concatenation instead of indexing. It should be just like Data(repeating: 0, count: length-pk.length) + pk.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


private func createChaincodeFromJunction(_ junction: String, type: ChaincodeType) throws -> Chaincode {
guard
var numericJunction = UInt32(junction),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's separate this cases into different errors. So for a library user it will be clear what is going wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

try performTest(filename: "BIP32HDKD", keypairFactory: BIP32KeypairFactory(), useMiniSeed: false)
}

func testBIP32DerivationPathStandardData() throws {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider to rename to testBIP32DerivationPathForEtalonTestVectors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion, I definitely struggled with naming

}
}

private func performSeedReadyTest(filename: String, keypairFactory: KeypairFactoryProtocol) throws {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

performSeedTestForVectorsFrom(..)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -16,9 +16,9 @@ class KeypairDeriviationTests: XCTestCase {
try performTest(filename: "ecdsaHDKD", keypairFactory: EcdsaKeypairFactory())
}

private func performTest(filename: String, keypairFactory: KeypairFactoryProtocol) throws {
private func performTest(filename: String, keypairFactory: KeypairFactoryProtocol, useMiniSeed: Bool = true) throws {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need useMiniSeed if it is not used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's there if someone (us?) would want to use it (:
I needed it first for BIP32 tests then I decided to separate them, so I thought it might be a good idea to leave it there for future uses

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove it for now if it is not used

Copy link
Contributor Author

@stas-litvinov stas-litvinov Aug 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

try performSeedReadyTest(filename: "BIP32HDKDStandard", keypairFactory: BIP32KeypairFactory())
}

private func performTest(filename: String, keypairFactory: KeypairFactoryProtocol, useMiniSeed: Bool = true) throws {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need useMiniSeed option if it is not used

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we don't need it, yes

@ERussel ERussel merged commit d460c42 into develop Aug 25, 2021
@ERussel ERussel deleted the feature/FLW-1161-BIP32-support branch August 25, 2021 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants