-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
2,519 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// | ||
// BIP39.swift | ||
// TangemSdk | ||
// | ||
// Created by Alexander Osokin on 06.03.2023. | ||
// Copyright © 2023 Tangem AG. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
@available(iOS 13.0, *) | ||
public struct BIP39 { | ||
/// Generate a mnemonic. | ||
/// - Parameters: | ||
/// - entropyLength: An entropy length to use. Default is 128 bit. | ||
/// - wordlist: A wordlist to use. Default is english. | ||
/// - Returns: Generated mnemonic | ||
public func generateMnemonic(entropyLength: EntropyLength = .bits128, wordlist: Wordlist = .en) throws -> [String] { | ||
guard entropyLength.rawValue % 32 == 0 else { | ||
throw MnemonicError.mnenmonicCreationFailed | ||
} | ||
|
||
let entropyBytesCount = entropyLength.rawValue / 8 | ||
let entropyData = try CryptoUtils.generateRandomBytes(count: entropyBytesCount) | ||
return try generateMnemonic(from: entropyData, wordlist: wordlist) | ||
} | ||
|
||
/// Generate a mnemonic from data. Useful for testing purposes. | ||
/// - Parameters: | ||
/// - data: Entropy data in hex format | ||
/// - wordlist: A wordlist to use. | ||
/// - Returns: Generated mnemonic | ||
func generateMnemonic(from entropyData: Data, wordlist: Wordlist) throws -> [String] { | ||
guard let entropyLength = EntropyLength(rawValue: entropyData.count * 8) else { | ||
throw MnemonicError.invalidEntropyLength | ||
} | ||
|
||
let entropyHashBits = entropyData.getSha256().toBits() | ||
let checksumBitLength = entropyLength.rawValue / 32 | ||
let entropyChecksumBits = entropyHashBits.prefix(checksumBitLength) | ||
|
||
let entropyBits = entropyData.toBits() | ||
let concatenatedBits = entropyBits + entropyChecksumBits | ||
let bitIndexes = concatenatedBits.chunked(into: 11) | ||
let indexes = bitIndexes.compactMap { Int($0.joined(), radix: 2) } | ||
|
||
guard indexes.count == entropyLength.wordsCount else { | ||
throw MnemonicError.mnenmonicCreationFailed | ||
} | ||
|
||
let allWords = wordlist.words | ||
|
||
guard indexes.allSatisfy({ $0 < allWords.count }) else { | ||
throw MnemonicError.mnenmonicCreationFailed | ||
} | ||
|
||
let words = indexes.map { allWords[$0] } | ||
return words | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
TangemSdk/TangemSdk/Common/HDWallet/BIP39/EntropyLength.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// | ||
// EntropyLength.swift | ||
// TangemSdk | ||
// | ||
// Created by Alexander Osokin on 01.03.2023. | ||
// Copyright © 2023 Tangem AG. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum EntropyLength: Int { | ||
case bits128 = 128 | ||
case bits160 = 160 | ||
case bits192 = 192 | ||
case bits224 = 224 | ||
case bits256 = 256 | ||
|
||
var wordsCount: Int { | ||
switch self { | ||
case .bits128: return 12 | ||
case .bits160: return 15 | ||
case .bits192: return 18 | ||
case .bits224: return 21 | ||
case .bits256: return 24 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// Mnemonic.swift | ||
// TangemSdk | ||
// | ||
// Created by Alexander Osokin on 01.03.2023. | ||
// Copyright © 2023 Tangem AG. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
@available(iOS 13.0, *) | ||
public enum Mnemonic { | ||
public static func generateMnemonic(entropyLength: EntropyLength, wordlist: Wordlist) throws { | ||
|
||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
TangemSdk/TangemSdk/Common/HDWallet/BIP39/MnemonicError.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// MnemonicError.swift | ||
// TangemSdk | ||
// | ||
// Created by Alexander Osokin on 01.03.2023. | ||
// Copyright © 2023 Tangem AG. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
public enum MnemonicError: Error { | ||
case invalidEntropyLength | ||
case invalidWordCount | ||
case invalidWordsFile | ||
case mnenmonicCreationFailed | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// Wordlist.swift | ||
// TangemSdk | ||
// | ||
// Created by Alexander Osokin on 01.03.2023. | ||
// Copyright © 2023 Tangem AG. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
@available(iOS 13.0, *) | ||
public enum Wordlist { | ||
case en | ||
|
||
/// This var reads a big array from a file | ||
public var words: [String] { | ||
(try? readWords(from: fileName)) ?? [] | ||
} | ||
|
||
private var fileName: String { | ||
switch self { | ||
case .en: | ||
return "english" | ||
} | ||
} | ||
|
||
private func readWords(from fileName: String) throws -> [String] { | ||
guard let path = Bundle.sdkBundle.path(forResource: fileName, ofType: "txt") else { | ||
throw MnemonicError.invalidWordsFile | ||
} | ||
|
||
let content = try String(contentsOfFile: path, encoding: .utf8) | ||
let words = content.trim().components(separatedBy: "\n") | ||
guard words.count == 2048 else { | ||
throw MnemonicError.invalidWordCount | ||
} | ||
|
||
return words | ||
} | ||
} |
Oops, something went wrong.