文章目錄
- 摘要
- 動機
- 基本原理
- 詳述
字首
建議詳述
加密步驟
解密步驟 - 向後相容性
- 測試用例
- 實現
摘要
提出了一種以58字元 Base58Check編碼的可列印字串的形式對密碼保密型私鑰記錄進行加密和編碼的方法。加密私鑰記錄旨在用於紙質錢包。每一個記錄字串都包含除了密碼之外重構私鑰所需的所有資訊,並且該方法使用加鹽和scrypt來抵抗暴力攻擊。
動機
密碼和密碼保護型金鑰是個人間傳送資產的新實踐。想要傳送資產的人可以通過郵政郵件郵寄一個受密碼保護的紙錢包並通過電話或者email給接收者密碼,以保證傳遞的安全不受其他通道的攔截。紙錢包的使用者可以攜帶資金的加密私鑰並在家中留存一份拷貝以預防意外的遺失和偷竊。把資產存在銀行賬戶或者保險箱中的紙錢包的使用者可以把密碼留在家裡或者與可信的夥伴分享已預防銀行中的某人乘機訪問紙錢包並花費其中的資產。預見和不可預見的關於密碼保護型私鑰的用例還有很多。
另一方面,標準的密碼保護型私鑰格式使得其能夠共享來自不同錢包客戶端的私鑰。
基本原理
用例:作為一個NEO紙錢包使用者,我喜歡新增加密的功能,如此我的NEO紙錢包可以拆解成兩個因子:我有的和我知道的。
用例:作為一個NEO使用者想要用一個私鑰向個人或者公司付款,我不必擔心任何通訊渠道會攔截我的key和導致資產的被盜。我想要提供一個密碼保護型金鑰,伴隨一個可以通過其他渠道傳輸的密碼。
詳述
本提議運用到了以下函式和定義:
·AES256加密、AES256解密,是眾所周知的AES分組編碼不考慮初始向量和塊連線的簡單格式。這些函式每一個都需要一個256位的key和16位元組的輸入和確定的16位元組的輸出。
·SHA256,一種眾所周知的任意位元組長度輸入和固定產出32位元組長度hash的雜湊演算法。
·scrypt,一個著名的金鑰推導演算法。它需要以下引數(string) password, (string) salt, (int) n, (int) r, (int) p, (int) length,並固定產生一個長度等於length長度的位元組陣列。
Base58Check,一個在NEO系統中廣泛使用的用58的字元byte[]編碼的方法。
字首
建議將Base58Check編碼過後的字串以6字開頭。數字6旨在從使用者的角度表示一種需要其他東西才能生效的私鑰–總的定義可以理解為將來包括特別是在多籤交易中的金鑰,並且被選遵從現有字首5,多見於WIF格式表示一種非加密私鑰。
建議第二個字元應該給出提示所需什麼因子,對於加密金鑰需要一個密碼,建議使用大寫字母P。
為保持加密金鑰的大小,在AES加密中不使用初始向量(IVS)。相反,使用scrypt從密碼以及NEO地址的32位hash作為鹽匯出用於類似初始向量用途的合適值。
建議詳述
物件識別符號字首:0x0142。這是在Base58Check編碼記錄開頭的常量位元組,它們的存在導致結果字串具有可預見的字首。
使用者如何判斷:58個字元總是以“6P”開頭
有效載荷位元組數(不包括字首):37
·1位元組(FLAG位元組):始終為0xE0
·4位元組:Sha256(Sha256(expected_neo_address))[0…3]),用於拼寫檢查和加鹽。
16位元組:AES加密金鑰材料記錄(加密半數1)
16位元組:AES加密金鑰材料記錄(加密半數2)
在BASE58CHECK編碼(字首6Py)中的範圍:
最小值:6PYJXKPVNKXUZAFD2B5ZSZAFJYNP4EZQQECJS39 449 QUUXLNXJLX6LG(基於01 42 E0加三十六個00)
最大值:6PyxG5TnGyLyxDrZiqxBuxxdotBNTBI3D61MQBXPPZQZEJTVQQHSCNK(基於01 42 E0加三十六個FF)
加密步驟
1、計算NEO地址(ASCII),
並獲取SHA256(SHA256())的前四個位元組.我們將其叫做地址雜湊。
2.使用Scrypt從密碼匯出一個金鑰。
·引數:密碼是以UTF-8格式的密碼。鹽採用之前得到的地址hash,n=16384,r=8,p=8,length=64
·把結果的64位元組分成2半,稱他們為匯出半數1和匯出半數2.
3.做AES256加密(block = privkey[0…15] xor derivedhalf1[0…15], key = derivedhalf2),把16位元組的結果叫做加密半數1.
4.做AES256加密(block = privkey[16…31] xor derivedhalf1[16…31], key = derivedhalf2),把16位元組的結果叫做加密半數2.
加密私鑰是以下Base58Check編碼下的串聯,總共39位元組,沒有Base58 checksum:
·0x01 0x42 + flagbyte + addresshash + encryptedhalf1 + encryptedhalf2
解密步驟
1.從使用者那獲取加密私鑰和密碼。
2.把密碼和地址hash帶入Scrypt函式得到半匯出數1和半匯出數2.
3.用AES256Decrypt解密半匯出數1和半匯出數2,併合並兩部分並將結果和半匯出數1做異或得到明文形式私鑰。
4.把明文私鑰轉化成NEO地址。
5.求NEO地址hash,並驗證加密私鑰記錄中的地址hash是否與之匹配。如果不是,則報告密碼錯誤。
向後相容性
向後相容性是最小的,由於它是一種新標準幾乎擴充套件了WIF格式。假設私鑰資料的入口可以接受現存格式的私鑰(比如16進位制數或者WIF格式);本草案使用的金鑰格式不能被錯誤地用於任何現有的格式,並保留自動檢測能力。
測試用例
Test 1:
• Passphrase: TestingOneTwoThree
• Encrypted: 6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL
• Unencrypted (WIF): L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP
• Unencrypted (hex): CBF4B9F70470856BB4F40F80B87EDB90865997FFEE6DF315AB166D713AF433A5
Test 2:
• Passphrase: Satoshi
• Encrypted: 6PYN6mjwYfjPUuYT3Exajvx25UddFVLpCw4bMsmtLdnKwZ9t1Mi3CfKe8S
• Unencrypted (WIF): KwYgW8gcxj1JWJXhPSu4Fqwzfhp5Yfi42mdYmMa4XqK7NJxXUSK7
• Unencrypted (hex): 09C2686880095B1A4C249EE3AC4EEA8A014F11E6F986D0B5025AC1F39AFBD9AE
實現
• neo-project/neo: https://github.com/neo-projec…
• CityOfZion/neon-js: https://github.com/CityOfZion…