Skip to content

Commit 58c7d08

Browse files
Merge pull request #852 from JeneaVranceanu/fix/bip39-wrong-language-used
fix: BIP39 use given language to generate mnemonics;
2 parents 34cf1e8 + d99c0f6 commit 58c7d08

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

Sources/Web3Core/KeystoreManager/BIP39.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import Foundation
77
import CryptoSwift
88

9-
public enum BIP39Language {
9+
public enum BIP39Language: CaseIterable {
1010
case english
1111
case chinese_simplified
1212
case chinese_traditional
@@ -36,7 +36,12 @@ public enum BIP39Language {
3636
return spanishWords
3737
}
3838
}
39+
3940
public var separator: String {
41+
return String(separatorCharacter)
42+
}
43+
44+
public var separatorCharacter: Character {
4045
switch self {
4146
case .japanese:
4247
return "\u{3000}"
@@ -124,7 +129,7 @@ public class BIP39 {
124129
public static func generateMnemonicsFromEntropy(entropy: Data, language: BIP39Language = .english) -> String? {
125130
guard entropy.count >= 16, entropy.count & 4 == 0 else { return nil }
126131
let separator = language.separator
127-
let wordList = generateMnemonicsFrom(entropy: entropy)
132+
let wordList = generateMnemonicsFrom(entropy: entropy, language: language)
128133
return wordList.joined(separator: separator)
129134
}
130135

Tests/web3swiftTests/localTests/BIP39Tests.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ final class BIP39Tests: XCTestCase {
151151
XCTAssert(keystore1?.addresses?.first == keystore2?.addresses?.first)
152152
}
153153

154+
/// It's expected for the entropy bits count to be [128, 256] and (bits mod 32) must return 0.
154155
func testWrongBitsOfEntropyMustThrow() throws {
155156
XCTAssertThrowsError(try BIP39.generateMnemonics(entropy: 127))
156157
XCTAssertThrowsError(try BIP39.generateMnemonics(entropy: 255))
@@ -166,4 +167,33 @@ final class BIP39Tests: XCTestCase {
166167
XCTAssertFalse(try BIP39.generateMnemonics(entropy: 256).isEmpty)
167168
}
168169

170+
func testBip39CorrectWordsCount() throws {
171+
XCTAssertEqual(try BIP39.generateMnemonics(entropy: 128).count, 12)
172+
XCTAssertEqual(try BIP39.generateMnemonics(entropy: 160).count, 15)
173+
XCTAssertEqual(try BIP39.generateMnemonics(entropy: 192).count, 18)
174+
XCTAssertEqual(try BIP39.generateMnemonics(entropy: 224).count, 21)
175+
XCTAssertEqual(try BIP39.generateMnemonics(entropy: 256).count, 24)
176+
}
177+
178+
func testAllLanguageMnemonics() throws {
179+
for language in BIP39Language.allCases {
180+
let mnemonicPhrase = try BIP39.generateMnemonics(entropy: 128, language: language)
181+
for word in mnemonicPhrase {
182+
guard language.words.contains(word) else {
183+
XCTFail("Given word is not contained in the list of words of selected language available for mnemonics generation: \(word); \(language)")
184+
return
185+
}
186+
}
187+
}
188+
}
189+
190+
func testBip39MnemonicSeparatorUse() throws {
191+
for language in BIP39Language.allCases {
192+
guard let mnemonicPhrase = try BIP39.generateMnemonics(bitsOfEntropy: 128, language: language) else {
193+
XCTFail("Failed to generate BIP39 mnemonics phrase with 128 bits of entropy using language: \(language)")
194+
return
195+
}
196+
XCTAssertEqual(mnemonicPhrase.split(whereSeparator: { $0 == language.separatorCharacter }).count, 12)
197+
}
198+
}
169199
}

0 commit comments

Comments
 (0)