iOS區(qū)塊鏈錢包之BIP39(二)

HD wallet具有管理多個密鑰和地址的機(jī)制循集,我們可以使用一個隨機(jī)字符串seed通過BIP32或BIP44協(xié)議創(chuàng)建一個HD wallet窄刘,但是一串字符串的記憶成本太高睡扬,而且摘抄下來也會很麻煩煌集。所以BIP39協(xié)議應(yīng)運(yùn)而生封字,他是可以使用12-24單字(可以是英文逞怨、中文者疤、日文等等語言)來幫助用戶更好的保存seed。一般我們使用長度為12個的英文單詞來生成BIP39的內(nèi)容叠赦,這串單詞被稱為mnemonic code驹马,中文名叫助記詞。

BIP-39 生成助記詞流程

助記詞錢包是通過BIP-39中定義的標(biāo)準(zhǔn)化過程自動生成的除秀,錢包從熵源開始糯累,增加校驗(yàn)和,然后將熵映射到字典列表中鳞仙。

1.創(chuàng)建一個128-256位的隨機(jī)序列(熵)

2.提出SHA256哈希的前幾位(熵長/32),就可以創(chuàng)建一個隨機(jī)序列的校驗(yàn)和寇蚊。

3.將校驗(yàn)和添加到隨機(jī)序列的末尾。

4.將序列劃分為包含11位的不同部分棍好。

5.將每個包含11位部分的值與一個預(yù)先定義的2048個單詞的字典做對應(yīng)仗岸。

6.生成的有順序的單詞組就是助記詞允耿。

新建項目

導(dǎo)入CryptoSwift

  1. 新建BIP39.swift文件
import Foundation
import CryptoSwift

public enum BIP39Language {
    case english
    case chinese_simplified
    case chinese_traditional
    case japanese
    case korean
    case french
    case italian
    case spanish
    var words: [String] {
        switch self {
        case .english:
            return englishWords
        case .chinese_simplified:
            return simplifiedchineseWords
        case .chinese_traditional:
            return traditionalchineseWords
        case .japanese:
            return japaneseWords
        case .korean:
            return koreanWords
        case.french:
            return frenchWords
        case .italian:
            return italianWords
        case .spanish:
            return spanishWords
        }
    }
    var separator: String {
        switch self {
        case .japanese:
            return "\u{3000}"
        default:
            return " "
        }
    }
}
public class BIP39 {
    
    /// 返回一組助記詞
    static public func generateMnemonics(bitsOfEntropy: Int, language: BIP39Language = BIP39Language.english) throws -> String? {
        // 1.創(chuàng)建一個128-256位的隨機(jī)序列(熵)
        guard bitsOfEntropy >= 128 && bitsOfEntropy <= 256 && bitsOfEntropy % 32 == 0 else {return nil}
        guard let entropy = Data.randomBytes(length: bitsOfEntropy/8) else {throw AbstractError.noEntropyError}
        
        return BIP39.generateMnemonicsFromEntropy(entropy: entropy, language: language)
        
    }
    
    /// 通過熵生成助記詞
    static public func generateMnemonicsFromEntropy(entropy: Data, language: BIP39Language = BIP39Language.english) -> String?  {
        guard entropy.count >= 16, entropy.count & 4 == 0 else {return nil}
        // 2.提出SHA256哈希的前幾位(熵長/32),就可以創(chuàng)建一個隨機(jī)序列的校驗(yàn)和。
        let checksum = entropy.sha256()
        // 3.將校驗(yàn)和添加到隨機(jī)序列的末尾扒怖。
        let checksumBits = entropy.count*8/32
        var fullEntropy = Data()
        fullEntropy.append(entropy)
        fullEntropy.append(checksum[0 ..< (checksumBits+7)/8 ])
        var wordList = [String]()
        // 4.將序列劃分為包含11位的不同部分
        for i in 0 ..< fullEntropy.count*8/11 {
            guard let bits = fullEntropy.bitsInRange(i*11, 11) else {return nil}
            let index = Int(bits)
            guard language.words.count > index else {return nil}
            // 5.將每個包含11位部分的值與一個預(yù)先定義的2048個單詞的字典做對應(yīng)较锡。
            let word = language.words[index]
            wordList.append(word)
        }
        let separator = language.separator
        // 6.生成的有順序的單詞組就是助記詞。
        return wordList.joined(separator: separator)
    }
    
    /// 通過助記詞返回一個熵
    static public func mnemonicsToEntropy(_ mnemonics: String, language: BIP39Language = BIP39Language.english) -> Data? {
        let wordList = mnemonics.components(separatedBy: " ")
        guard wordList.count >= 12 && wordList.count % 4 == 0 else {return nil}
        var bitString = ""
        for word in wordList {
            let idx = language.words.index(of: word)
            if (idx == nil) {
                return nil
            }
            let idxAsInt = language.words.startIndex.distance(to: idx!)
            let stringForm = String(UInt16(idxAsInt), radix: 2).leftPadding(toLength: 11, withPad: "0")
            bitString.append(stringForm)
        }
        let stringCount = bitString.count
        if stringCount % 33 != 0 {
            return nil
        }
        let entropyBits = bitString[0 ..< (bitString.count - bitString.count/33)]
        let checksumBits = bitString[(bitString.count - bitString.count/33) ..< bitString.count]
        guard let entropy = entropyBits.interpretAsBinaryData() else {
            return nil
        }
        let checksum = String(entropy.sha256().bitsInRange(0, checksumBits.count)!, radix: 2).leftPadding(toLength: checksumBits.count, withPad: "0")
        if checksum != checksumBits {
            return nil
        }
        return entropy
    }
    
    /// 通過助記詞返回一個seed(種子)
    static public func seedFromMmemonics(_ mnemonics: String, password: String = "", language: BIP39Language = BIP39Language.english) -> Data? {
        let valid = BIP39.mnemonicsToEntropy(mnemonics, language: language) != nil
        if (!valid) {
            print("Potentially invalid mnemonics")
        }
        guard let mnemData = mnemonics.decomposedStringWithCompatibilityMapping.data(using: .utf8) else {return nil}
        let salt = "mnemonic" + password
        guard let saltData = salt.decomposedStringWithCompatibilityMapping.data(using: .utf8) else {return nil}
        guard let seedArray = try? PKCS5.PBKDF2(password: mnemData.bytes, salt: saltData.bytes, iterations: 2048, keyLength: 64, variant: HMAC.Variant.sha512).calculate() else {return nil}
        let seed = Data(bytes:seedArray)
        return seed
    }
}
  1. 統(tǒng)一錯誤處理類AbstractError.swift
import Foundation

public enum AbstractError: Error {
    case noEntropyError
    case keyDerivationError
    case aesError
    case invalidAccountError
    case invalidPasswordError
    case encryptionError(String)
}

項目結(jié)構(gòu)


image.png

demo使用:

// 生成助記詞
let mnemonic = try! BIP39.generateMnemonics(bitsOfEntropy: 128)!

// 種子
let seed = BIP39.seedFromMmemonics(mnemonic)

print("助記詞:\(mnemonic)")

print("種子seed:\(seed?.toHexString() ?? "")")

示例結(jié)果


助記詞:soldier stay tackle return tackle lens praise leader traffic sword anxiety intact
種子seed:bc428e06a1bc08b3bf52ce6b1fd1a295518888b1de10eea3231043bed07e4ccd108e5a192bfd073d3db81dba8311ed2b109fbda3d6daa63d27000e395a46f887

驗(yàn)證地址:
https://iancoleman.io/bip39/
demo下載地址:
暫未上傳

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盗痒,一起剝皮案震驚了整個濱河市蚂蕴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俯邓,老刑警劉巖骡楼,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異稽鞭,居然都是意外死亡鸟整,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門朦蕴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篮条,“玉大人,你說我怎么就攤上這事吩抓∩婕耄” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵疹娶,是天一觀的道長伴栓。 經(jīng)常有香客問我,道長蚓胸,這世上最難降的妖魔是什么挣饥? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮沛膳,結(jié)果婚禮上扔枫,老公的妹妹穿的比我還像新娘。我一直安慰自己锹安,他們只是感情好短荐,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叹哭,像睡著了一般忍宋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上风罩,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天糠排,我揣著相機(jī)與錄音,去河邊找鬼超升。 笑死入宦,一個胖子當(dāng)著我的面吹牛哺徊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播乾闰,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼落追,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涯肩?” 一聲冷哼從身側(cè)響起轿钠,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎病苗,沒想到半個月后疗垛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铅乡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年继谚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阵幸。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖芽世,靈堂內(nèi)的尸體忽然破棺而出挚赊,到底是詐尸還是另有隱情,我是刑警寧澤济瓢,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布荠割,位于F島的核電站,受9級特大地震影響旺矾,放射性物質(zhì)發(fā)生泄漏蔑鹦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一箕宙、第九天 我趴在偏房一處隱蔽的房頂上張望嚎朽。 院中可真熱鬧,春花似錦柬帕、人聲如沸哟忍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锅很。三九已至,卻和暖如春凤跑,著一層夾襖步出監(jiān)牢的瞬間爆安,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工仔引, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扔仓,地道東北人褐奥。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像当辐,于是被迫代替她去往敵國和親抖僵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容