知乎專欄 | 多維度架構 | | | 微信號 netkiller-ebook | | | QQ群:128659835 請註明“讀者” |
Post author: Martin Wang
Post link: http://stevenocean.github.io/2018/04/02/about-ethereum-keystore.html
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
以太坊的每個外部賬戶都是由一對密鑰(一個公鑰和一個私鑰)定義的。賬戶以地址為索引,地址由公鑰衍生而來,取公鑰的最後 20個位元組。每對私鑰 /地址都編碼在一個鑰匙檔案裡,也就是我們說的keystore檔案。該檔案是 JSON 文本檔案,可以用任何文本編輯器打開和瀏覽。鑰匙檔案的關鍵部分,賬戶私鑰,通常用你創建帳戶時設置的密碼進行加密。也就是說 keystore 檔案,就是你獨有的、用於簽署交易的以太坊私鑰的加密檔案。如果你丟失了這個檔案,你就丟失了私鑰,意味着你失去了簽署交易的能力,意味着你的資金被永久的鎖定在了你的賬戶裡。
我們先看一下keystore檔案都包含哪些數據:
neo@MacBook-Pro ~/Library/Ethereum/testnet/keystore % cat UTC--2018-04-01T09-30-44.943874000Z--d5eeae04932dbc2e65b948a76a6cdfd44323a5dd { "address":"d5eeae04932dbc2e65b948a76a6cdfd44323a5dd", "crypto":{ "cipher":"aes-128-ctr", "ciphertext":"16715298517abb35cb44e9a32d1f81f21ead63006c57eb0ff434318a6ea3ed3f", "cipherparams":{ "iv":"1ff6fea34e682158e7660ae67960ff76" }, "kdf":"scrypt", "kdfparams":{ "dklen":32, "n":262144, "p":1, "r":8, "salt":"a99af42dac2363db631ef7c57a25705c7efdee73b19c11b27f9a91d41cd32d1c" }, "mac":"dcd248fb996604dfcb69a86604af3992b4a9b8d20cc05e0c7608189dbbe66eda" }, "id":"55edb869-1c86-4c68-924e-8247575a158b", "version":3 }
我們可以看到大部分內容都在 crypto 欄位中,這裡包括:
cipher:對稱 AES 算法的名稱;
cipherparams:上述 cipher 算法需要的參數;
ciphertext:你的以太坊私鑰使用上述 cipher 算法進行加密;
kdf:密鑰生成函數,用於讓你用密碼加密 keystore 檔案;
kdfparams:上述 kdf 算法需要的參數;
Mac:用於驗證密碼的代碼。
就像之前提到的,一個以太坊賬戶就是用於加密簽署交易的一個私鑰-公鑰對。為了確保你的私鑰沒有在檔案中明文存儲(即任何人只要能得到這個檔案就能讀),使用強對稱算法(cipher)對其加密至關重要。
這些對稱算法使用密鑰來加密數據。加密後的數據可以使用相同的方法和同樣的密鑰來解密,因此算法命名為對稱算法。在本文中,我們稱這個對稱密鑰為解密密鑰,因為它將用於對我們的以太坊私鑰進行解密。
加密過程,如下圖:
以下是 cipher,cipherparams 和 ciphertext 對應的概念:
cipher: 是用於加密以太坊私鑰的對稱加密算法。此處cipher用的是 aes-128-ctr 加密模式。
cipherparams: 是 aes-128-ctr 加密算法需要的參數。在這裡,用到的唯一的參數 iv,是aes-128-ctr加密算法需要的初始化向量。
ciphertext: 密文是 aes-128-ctr 函數的加密輸入。
在這裡,你已經有了進行解密以太坊私鑰計算所需要的一切。但是我們首先要取回解密密鑰。
要確保解鎖你的賬戶很容易,你不需要記住你的每一個又長又非用戶友好型的用於解密 ciphertext 密文解密密鑰。相反,以太坊開發者選擇了基于密碼的保護,也就是說你只需要輸入密碼就能拿回解密密鑰。
為了能做到這一點,以太坊用了一個密鑰生成函數,輸入密碼和一系列參數就能計算解密密鑰。
這就是 kdf 和 kdfparams 的用途:
kdf: 是一個密鑰生成函數,根據你的密碼計算(或者取回)解密密鑰。在這裡,kdf 用的是scrypt算法。
kdfparams: 是scrypt函數需要的參數。在這裡,簡單來說,dklen、n、r、p 和 salt 是 kdf 函數的參數。
在這裡,用 kdfparams 參數對 scrypt 函數進行調整,反饋到我們的密碼中,你就會得到解密密鑰也就是密鑰生成函數的輸出。
這就是 keystore 檔案中 mac 值起作用的地方。在密鑰生成函數執行之後,它的輸出(解密密鑰)和 ciphertext 密文就被處理,並且和 mac(就像一種認可的印章)作比較。如果結果和 mac 相同,那麼密碼就是正確的,並且解密就可以開始了。