Skip to content

Commit b8876d5

Browse files
committed
Add checksum validation for bip39
1 parent fab15b5 commit b8876d5

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

Source/TonSwift/Mnemonic/Mnemonic.swift

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,51 @@ public enum Mnemonic {
147147
}
148148

149149
public static func isValidBip39Mnemonic(mnemonicArray: [String]) -> Bool {
150-
guard !mnemonicArray.isEmpty else { return false }
151-
guard mnemonicArray.allSatisfy({ words.contains($0) }) else { return false }
152-
return mnemonicArray.count % 3 == 0
150+
let mnemonic = normalizeMnemonic(src: mnemonicArray)
151+
152+
guard !mnemonic.isEmpty,
153+
mnemonic.allSatisfy({ words.contains($0) }),
154+
mnemonic.count % 3 == 0,
155+
(12...24).contains(mnemonic.count)
156+
else {
157+
return false
158+
}
159+
160+
var bits = ""
161+
for word in mnemonic {
162+
guard let idx = words.firstIndex(of: word) else { return false }
163+
let bin = String(idx, radix: 2)
164+
bits += String(repeating: "0", count: 11 - bin.count) + bin
165+
}
166+
167+
let entLength = mnemonic.count * 11 * 32 / 33
168+
let checksumLen = entLength / 32
169+
170+
let entBits = bits.prefix(entLength)
171+
let csBits = bits.suffix(checksumLen)
172+
173+
var entropyBytes: [UInt8] = []
174+
var i = entBits.startIndex
175+
while i < entBits.endIndex {
176+
let next = entBits.index(i, offsetBy: 8)
177+
let byteStr = String(entBits[i..<next])
178+
guard let byte = UInt8(byteStr, radix: 2) else { return false }
179+
entropyBytes.append(byte)
180+
i = next
181+
}
182+
183+
let hashData = Data(entropyBytes).sha256()
184+
185+
let hashBits =
186+
hashData
187+
.map { byte -> String in
188+
let bin = String(byte, radix: 2)
189+
return String(repeating: "0", count: 8 - bin.count) + bin
190+
}
191+
.joined()
192+
.prefix(checksumLen)
193+
194+
return csBits == hashBits
153195
}
154196

155197
public static func bip39MnemonicToSeed(mnemonicArray: [String], password: String = "") -> Data {

0 commit comments

Comments
 (0)