Skip to content

Commit 5a91bb5

Browse files
committed
revert changes
1 parent 40d3477 commit 5a91bb5

File tree

1 file changed

+126
-127
lines changed

1 file changed

+126
-127
lines changed

Sources/Web3Core/KeystoreManager/BIP32HDNode.swift

Lines changed: 126 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -128,121 +128,118 @@ public class HDNode {
128128
extension HDNode {
129129
public func derive(index: UInt32, derivePrivateKey: Bool, hardened: Bool = false) -> HDNode? {
130130
if derivePrivateKey {
131-
return deriveWithPrivateKey(index: index, hardened: hardened)
132-
} else { // deriving only the public key
133-
return deriveWithoutPrivateKey(index: index, hardened: hardened)
131+
return self.derivePrivateKey(index: index, hardened: hardened)
132+
} else {
133+
return derivePublicKey(index: index, hardened: hardened)
134134
}
135135
}
136136

137-
public func deriveWithoutPrivateKey(index: UInt32, hardened: Bool = false) -> HDNode? {
138-
var entropy: [UInt8] // derive public key when is itself public key
139-
if index >= Self.maxIterationIndex || hardened {
140-
return nil // no derivation of hardened public key from extended public key
141-
} else {
142-
let hmac: Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
143-
var inputForHMAC = Data()
144-
inputForHMAC.append(self.publicKey)
145-
inputForHMAC.append(index.serialize32())
146-
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else { return nil }
147-
guard ent.count == 64 else { return nil }
148-
entropy = ent
137+
public func derive(path: String, derivePrivateKey: Bool = true) -> HDNode? {
138+
let components = path.components(separatedBy: "/")
139+
var currentNode: HDNode = self
140+
var firstComponent = 0
141+
if path.hasPrefix("m") {
142+
firstComponent = 1
149143
}
150-
let I_L = entropy[0..<32]
151-
let I_R = entropy[32..<64]
152-
let cc = Data(I_R)
153-
let bn = BigUInt(Data(I_L))
154-
if bn > HDNode.curveOrder {
155-
if index < UInt32.max {
156-
return self.derive(index: index+1, derivePrivateKey: false, hardened: hardened)
144+
for component in components[firstComponent ..< components.count] {
145+
var hardened = false
146+
if component.hasSuffix("'") {
147+
hardened = true
157148
}
158-
return nil
159-
}
160-
guard let tempKey = bn.serialize().setLengthLeft(32) else { return nil }
161-
guard SECP256K1.verifyPrivateKey(privateKey: tempKey) else { return nil }
162-
guard let pubKeyCandidate = SECP256K1.privateToPublic(privateKey: tempKey, compressed: true) else { return nil }
163-
guard pubKeyCandidate.bytes.first == 0x02 || pubKeyCandidate.bytes.first == 0x03 else { return nil }
164-
guard let newPublicKey = SECP256K1.combineSerializedPublicKeys(keys: [self.publicKey, pubKeyCandidate], outputCompressed: true) else { return nil }
165-
guard newPublicKey.bytes.first == 0x02 || newPublicKey.bytes.first == 0x03 else { return nil }
166-
guard self.depth < UInt8.max else { return nil }
167-
let newNode = HDNode()
168-
newNode.chaincode = cc
169-
newNode.depth = self.depth + 1
170-
newNode.publicKey = newPublicKey
171-
newNode.childNumber = index
172-
guard let fprint = try? RIPEMD160.hash(message: self.publicKey.sha256())[0..<4] else {
173-
return nil
174-
}
175-
newNode.parentFingerprint = fprint
176-
var newPath = String()
177-
if newNode.isHardened {
178-
newPath = (self.path ?? "") + "/"
179-
newPath += String(newNode.index % HDNode.hardenedIndexPrefix) + "'"
180-
} else {
181-
newPath = (self.path ?? "") + "/" + String(newNode.index)
149+
guard let index = UInt32(component.trimmingCharacters(in: CharacterSet(charactersIn: "'"))) else { return nil }
150+
guard let newNode = currentNode.derive(index: index, derivePrivateKey: derivePrivateKey, hardened: hardened) else { return nil }
151+
currentNode = newNode
182152
}
183-
newNode.path = newPath
184-
return newNode
153+
return currentNode
185154
}
186-
public func deriveWithPrivateKey(index: UInt32, hardened: Bool = false) -> HDNode? {
187155

188-
guard let privateKey = self.privateKey else {
156+
/// Derive public key when is itself private key.
157+
/// Derivation of private key when is itself extended public key is impossible and will return `nil`.
158+
private func derivePrivateKey(index: UInt32, hardened: Bool) -> HDNode? {
159+
guard let privateKey = privateKey else {
160+
// derive private key when is itself extended public key (impossible)
189161
return nil
190162
}
191-
var entropy: [UInt8]
192-
var trueIndex: UInt32
193-
if index >= Self.maxIterationIndex || hardened {
194-
trueIndex = index
195-
if trueIndex < Self.maxIterationIndex {
196-
trueIndex = trueIndex + Self.maxIterationIndex
197-
}
198-
let hmac: Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
199-
var inputForHMAC = Data()
200-
inputForHMAC.append(Data([UInt8(0x00)]))
201-
inputForHMAC.append(privateKey)
202-
inputForHMAC.append(trueIndex.serialize32())
203-
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else { return nil }
204-
guard ent.count == 64 else { return nil }
205-
entropy = ent
206-
} else {
207-
trueIndex = index
208-
let hmac: Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
209-
var inputForHMAC = Data()
210-
inputForHMAC.append(self.publicKey)
211-
inputForHMAC.append(trueIndex.serialize32())
212-
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else { return nil }
213-
guard ent.count == 64 else { return nil }
214-
entropy = ent
163+
164+
var trueIndex = index
165+
if trueIndex < (UInt32(1) << 31) && hardened {
166+
trueIndex += (UInt32(1) << 31)
215167
}
168+
169+
guard let entropy = calculateEntropy(index: trueIndex, privateKey: privateKey, hardened: hardened) else { return nil }
170+
216171
let I_L = entropy[0..<32]
217172
let I_R = entropy[32..<64]
218-
let cc = Data(I_R)
173+
let chainCode = Data(I_R)
219174
let bn = BigUInt(Data(I_L))
220175
if bn > HDNode.curveOrder {
221176
if trueIndex < UInt32.max {
222-
return self.derive(index: index+1, derivePrivateKey: true, hardened: hardened)
177+
return self.derive(index: index + 1, derivePrivateKey: true, hardened: hardened)
223178
}
224179
return nil
225180
}
226-
let newPK = (bn + BigUInt(self.privateKey!)) % HDNode.curveOrder
181+
let newPK = (bn + BigUInt(privateKey)) % HDNode.curveOrder
227182
if newPK == BigUInt(0) {
228183
if trueIndex < UInt32.max {
229-
return self.derive(index: index+1, derivePrivateKey: true, hardened: hardened)
184+
return self.derive(index: index + 1, derivePrivateKey: true, hardened: hardened)
230185
}
231186
return nil
232187
}
233-
guard let privKeyCandidate = newPK.serialize().setLengthLeft(32) else { return nil }
234-
guard SECP256K1.verifyPrivateKey(privateKey: privKeyCandidate) else { return nil }
235-
guard let pubKeyCandidate = SECP256K1.privateToPublic(privateKey: privKeyCandidate, compressed: true) else { return nil }
236-
guard pubKeyCandidate.bytes[0] == 0x02 || pubKeyCandidate.bytes[0] == 0x03 else { return nil }
237-
guard self.depth < UInt8.max else { return nil }
188+
189+
guard
190+
let newPrivateKey = newPK.serialize().setLengthLeft(32),
191+
SECP256K1.verifyPrivateKey(privateKey: newPrivateKey),
192+
let newPublicKey = SECP256K1.privateToPublic(privateKey: newPrivateKey, compressed: true),
193+
(newPublicKey.bytes[0] == 0x02 || newPublicKey.bytes[0] == 0x03),
194+
self.depth < UInt8.max
195+
else { return nil }
196+
return createNode(chainCode: chainCode, depth: depth + 1, publicKey: newPublicKey, privateKey: newPrivateKey, childNumber: trueIndex)
197+
}
198+
199+
/// Derive public key when is itself public key.
200+
/// No derivation of hardened public key from extended public key is allowed.
201+
private func derivePublicKey(index: UInt32, hardened: Bool) -> HDNode? {
202+
if index >= (UInt32(1) << 31) || hardened {
203+
// no derivation of hardened public key from extended public key
204+
return nil
205+
}
206+
207+
guard let entropy = calculateEntropy(index: index, hardened: hardened) else { return nil }
208+
209+
let I_L = entropy[0..<32]
210+
let I_R = entropy[32..<64]
211+
let chainCode = Data(I_R)
212+
let bn = BigUInt(Data(I_L))
213+
if bn > HDNode.curveOrder {
214+
if index < UInt32.max {
215+
return self.derive(index: index+1, derivePrivateKey: false, hardened: hardened)
216+
}
217+
return nil
218+
}
219+
220+
guard
221+
let tempKey = bn.serialize().setLengthLeft(32),
222+
SECP256K1.verifyPrivateKey(privateKey: tempKey),
223+
let pubKeyCandidate = SECP256K1.privateToPublic(privateKey: tempKey, compressed: true),
224+
(pubKeyCandidate.bytes[0] == 0x02 || pubKeyCandidate.bytes[0] == 0x03),
225+
let newPublicKey = SECP256K1.combineSerializedPublicKeys(keys: [self.publicKey, pubKeyCandidate], outputCompressed: true),
226+
(newPublicKey.bytes[0] == 0x02 || newPublicKey.bytes[0] == 0x03),
227+
self.depth < UInt8.max
228+
else { return nil }
229+
230+
return createNode(chainCode: chainCode, depth: depth + 1, publicKey: newPublicKey, childNumber: index)
231+
}
232+
233+
private func createNode(chainCode: Data, depth: UInt8, publicKey: Data, privateKey: Data? = nil, childNumber: UInt32) -> HDNode? {
238234
let newNode = HDNode()
239-
newNode.chaincode = cc
240-
newNode.depth = self.depth + 1
241-
newNode.publicKey = pubKeyCandidate
242-
newNode.privateKey = privKeyCandidate
243-
newNode.childNumber = trueIndex
244-
guard let fprint = try? RIPEMD160.hash(message: self.publicKey.sha256())[0..<4],
245-
let path = path
235+
newNode.chaincode = chainCode
236+
newNode.depth = depth
237+
newNode.publicKey = publicKey
238+
newNode.privateKey = privateKey
239+
newNode.childNumber = childNumber
240+
guard
241+
let fprint = try? RIPEMD160.hash(message: self.publicKey.sha256())[0..<4],
242+
let path = path
246243
else { return nil }
247244
newNode.parentFingerprint = fprint
248245
var newPath = String()
@@ -254,58 +251,60 @@ extension HDNode {
254251
}
255252
newNode.path = newPath
256253
return newNode
257-
258254
}
259255

260-
public func derive(path: String, derivePrivateKey: Bool = true) -> HDNode? {
256+
private func calculateHMACInput(_ index: UInt32, privateKey: Data? = nil, hardened: Bool) -> Data {
257+
var inputForHMAC = Data()
261258

262-
let components = path.components(separatedBy: "/")
263-
var currentNode: HDNode = self
264-
var firstComponent = 0
265-
if path.hasPrefix("m") {
266-
firstComponent = 1
267-
}
268-
for component in components[firstComponent ..< components.count] {
269-
var hardened = false
270-
if component.hasSuffix("'") {
271-
hardened = true
272-
}
273-
guard let index = UInt32(component.trimmingCharacters(in: CharacterSet(charactersIn: "'"))) else { return nil }
274-
guard let newNode = currentNode.derive(index: index, derivePrivateKey: derivePrivateKey, hardened: hardened) else { return nil }
275-
currentNode = newNode
259+
if let privateKey = privateKey, (index >= (UInt32(1) << 31) || hardened) {
260+
inputForHMAC.append(Data([UInt8(0x00)]))
261+
inputForHMAC.append(privateKey)
262+
} else {
263+
inputForHMAC.append(self.publicKey)
276264
}
277-
return currentNode
265+
266+
inputForHMAC.append(index.serialize32())
267+
return inputForHMAC
278268
}
279269

280-
public func serializeToString(serializePublic: Bool = true) -> String? {
281-
guard let data = self.serialize(serializePublic: serializePublic) else { return nil }
282-
let encoded = Base58.base58FromBytes(data.bytes)
283-
return encoded
270+
/// Calculates entropy used for private or public key derivation.
271+
/// - Parameters:
272+
/// - index: index
273+
/// - privateKey: private key data or `nil` if entropy is calculated for a public key;
274+
/// - hardened: is hardened key
275+
/// - Returns: 64 bytes entropy or `nil`.
276+
private func calculateEntropy(index: UInt32, privateKey: Data? = nil, hardened: Bool) -> [UInt8]? {
277+
let inputForHMAC = calculateHMACInput(index, privateKey: privateKey, hardened: hardened)
278+
let hmac = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
279+
guard let entropy = try? hmac.authenticate(inputForHMAC.bytes), entropy.count == 64 else { return nil }
280+
return entropy
284281
}
285282

286-
public func serialize(serializePublic: Bool = true) -> Data? {
283+
public func serializeToString(serializePublic: Bool = true, version: HDversion = HDversion()) -> String? {
284+
guard let data = self.serialize(serializePublic: serializePublic, version: version) else { return nil }
285+
return Base58.base58FromBytes(data.bytes)
286+
}
287287

288+
public func serialize(serializePublic: Bool = true, version: HDversion = HDversion()) -> Data? {
288289
var data = Data()
289-
290-
guard serializePublic || privateKey != nil else {
291-
return nil
292-
}
293-
290+
/// Public or private key
291+
let keyData: Data
294292
if serializePublic {
295-
data.append(HDversion.publicPrefix)
293+
keyData = publicKey
294+
data.append(version.publicPrefix)
296295
} else {
297-
data.append(HDversion.privatePrefix)
296+
guard let privateKey = privateKey else { return nil }
297+
keyData = privateKey
298+
data.append(version.privatePrefix)
298299
}
299-
data.append(contentsOf: [self.depth])
300-
data.append(self.parentFingerprint)
301-
data.append(self.childNumber.serialize32())
302-
data.append(self.chaincode)
303-
if serializePublic {
304-
data.append(self.publicKey)
305-
} else {
300+
data.append(contentsOf: [depth])
301+
data.append(parentFingerprint)
302+
data.append(childNumber.serialize32())
303+
data.append(chaincode)
304+
if !serializePublic {
306305
data.append(contentsOf: [0x00])
307-
data.append(self.privateKey!)
308306
}
307+
data.append(keyData)
309308
let hashedData = data.sha256().sha256()
310309
let checksum = hashedData[0..<4]
311310
data.append(checksum)

0 commit comments

Comments
 (0)