Skip to content

Commit

Permalink
IOS-3059 Open validation, change regex
Browse files Browse the repository at this point in the history
  • Loading branch information
tureck1y committed Mar 17, 2023
1 parent de875a1 commit 977888c
Showing 1 changed file with 62 additions and 62 deletions.
124 changes: 62 additions & 62 deletions TangemSdk/TangemSdk/Crypto/BIP39/BIP39.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,67 @@ import Foundation
// https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
@available(iOS 13.0, *)
public struct BIP39 {
/// Validate a mnemonic.
/// - Parameter mnemonicComponents: Menemonic components to use
public func validate(mnemonicComponents: [String]) throws {
// Validate words count
if mnemonicComponents.isEmpty {
throw MnemonicError.wrongWordCount
}

guard let entropyLength = EntropyLength.allCases.first(where: { $0.wordCount == mnemonicComponents.count }) else {
throw MnemonicError.wrongWordCount
}

// Validate wordlist by the first word
let wordlistDictionary = try getWordlist(by: mnemonicComponents[0]).dictionary

// Validate all the words
var invalidWords = Set<String>()

// Generate an indices array inplace
var concatenatedBits = ""

for word in mnemonicComponents {
guard let wordIndex = wordlistDictionary.firstIndex(of: word) else {
invalidWords.insert(word)
continue
}

let indexBits = String(wordIndex, radix: 2).leadingZeroPadding(toLength: 11)
concatenatedBits.append(contentsOf: indexBits)
}

guard invalidWords.isEmpty else {
throw MnemonicError.invalidWords(words: Array(invalidWords))
}

// Validate checksum

let checksumBitsCount = mnemonicComponents.count / 3
guard checksumBitsCount == entropyLength.cheksumBitsCount else {
throw MnemonicError.invalidCheksum
}

let entropyBitsCount = concatenatedBits.count - checksumBitsCount
let entropyBits = String(concatenatedBits.prefix(entropyBitsCount))
let checksumBits = String(concatenatedBits.suffix(checksumBitsCount))

guard let entropyData = Data(bitsString: entropyBits) else {
throw MnemonicError.invalidCheksum
}

let calculatedChecksumBits = entropyData
.getSha256()
.toBits()
.prefix(entropyLength.cheksumBitsCount)
.joined()

guard calculatedChecksumBits == checksumBits else {
throw MnemonicError.invalidCheksum
}
}

/// Generate a mnemonic.
/// - Parameters:
/// - entropyLength: The entropy length to use. Default is 128 bit.
Expand Down Expand Up @@ -78,72 +139,13 @@ public struct BIP39 {
return words
}

/// Validate a mnemonic.
/// - Parameter mnemonicComponents: Menemonic components to use
func validate(mnemonicComponents: [String]) throws {
// Validate words count
if mnemonicComponents.isEmpty {
throw MnemonicError.wrongWordCount
}

guard let entropyLength = EntropyLength.allCases.first(where: { $0.wordCount == mnemonicComponents.count }) else {
throw MnemonicError.wrongWordCount
}

// Validate wordlist by the first word
let wordlistDictionary = try getWordlist(by: mnemonicComponents[0]).dictionary

// Validate all the words
var invalidWords = Set<String>()

// Generate an indices array inplace
var concatenatedBits = ""

for word in mnemonicComponents {
guard let wordIndex = wordlistDictionary.firstIndex(of: word) else {
invalidWords.insert(word)
continue
}

let indexBits = String(wordIndex, radix: 2).leadingZeroPadding(toLength: 11)
concatenatedBits.append(contentsOf: indexBits)
}

guard invalidWords.isEmpty else {
throw MnemonicError.invalidWords(words: Array(invalidWords))
}

// Validate checksum

let checksumBitsCount = mnemonicComponents.count / 3
guard checksumBitsCount == entropyLength.cheksumBitsCount else {
throw MnemonicError.invalidCheksum
}

let entropyBitsCount = concatenatedBits.count - checksumBitsCount
let entropyBits = String(concatenatedBits.prefix(entropyBitsCount))
let checksumBits = String(concatenatedBits.suffix(checksumBitsCount))

guard let entropyData = Data(bitsString: entropyBits) else {
throw MnemonicError.invalidCheksum
}

let calculatedChecksumBits = entropyData
.getSha256()
.toBits()
.prefix(entropyLength.cheksumBitsCount)
.joined()

guard calculatedChecksumBits == checksumBits else {
throw MnemonicError.invalidCheksum
}
}

/// Parse a mnemonic.
/// - Parameter mnemonicString: The mnemonic to parse
/// - Returns: Menemonic components
func parse(mnemonicString: String) throws -> [String] {
let regex = try NSRegularExpression(pattern: "[a-zA-Z]+")
let regex = try NSRegularExpression(pattern: "\\p{L}+")
let range = NSRange(location: 0, length: mnemonicString.count)
let matches = regex.matches(in: mnemonicString, range: range)
let components = matches.compactMap { result -> String? in
Expand All @@ -159,15 +161,13 @@ public struct BIP39 {
return components
}


/// Validate wordlist by the first word
/// - Parameter mnemonicComponents: Menemonic components to use
/// - Returns: The Wordlist, selected by the first word
func parseWordlist(from mnemonicComponents: [String]) throws -> Wordlist {
return try getWordlist(by: mnemonicComponents[0]).wordlist
}


/// Convert mnemonic componets to a sungle string, splitted by spaces
/// - Parameter mnemonicComponents: Menemonic components to use
/// - Returns: The mnemonic string
Expand Down

0 comments on commit 977888c

Please sign in to comment.