在創建了自己的本地區塊鏈后,我們會得到一個文件夾keystore,該文件夾是用來存儲你在這個區塊鏈中創建的賬戶的備份鑰匙文件,比如在這里我有一個賬戶的備份鑰匙文件為:UTC--2018-07-12T06-48-30.819494813Z--91b678137f09c8b4f294a14e88c09276522618cf(json文件)
{"address":"91b678137f09c8b4f294a14e88c09276522618cf",
"crypto":{
"cipher":"aes-128-ctr",
"ciphertext":"ebd32eef42c403fbe6509a8b5ae5b2d7d4eb15ee1a046ae23c3383ad672f0fcd",
"cipherparams":{
"iv":"0406c84c7a744beb6774214f912327dd"
},
"kdf":"scrypt",
"kdfparams":{
"dklen":32,
"n":262144,
"p":1,
"r":8,
"salt":"260bebdb9cb810a63d1060f69ebd35a479c77d5fd11a16fb496367359cb99f2a"
},
"mac":"5bb1d0ea80da66265f044f075f5fcf7c736500c75fa1a0d5d52e25f9bceea7a2"
},
"id":"fa03979a-f607-4de9-b32a-4952cc93ca6f",
"version":3
}
cipher:加密算法,對稱加密,AES算法,用於加密以太坊私鑰; cipherparams:cipher算法需要的參數,參數iv,是aes-128-ctr加密算法需要的初始化向量; ciphertext:私鑰加密后的密文,你的以太坊私鑰使用上述 cipher 算法進行加密,這樣你的私鑰不會是明文存儲,aes-128-ctr函數的解密輸入密文;
//所以將ciphertext的密文解密密鑰、ciphertext加密后的私鑰、cipherparams算法所需的參數 這三者輸入到對稱算法aes-128-ctr中后,就能夠得到私鑰了
//然后從上面所需的三個輸入中我們就知道我們現在還不知道ciphertext的密文解密密鑰是什么,那么下面就是用於生成這個解密的
kdf:秘鑰生成函數,用於使用你自己設置的密碼加密keystore文件,所以你要用自己的密碼解密keystore文件后才能得到私鑰 //用 kdfparams 參數對 scrypt 函數進行調整 kdfparams:kdf算法所需要的參數;
//kdf和kdfparams的作用就是生成ciphertext的密文解密密鑰,因為我們很難記得這個長串的密鑰,所以在這里我們只需要通過這個密鑰生成函數scrypt、其參數kdfparams以及自己設置的密碼password
//這三者我們就能夠得到ciphertext的密文解密密鑰,然后將其輸入到上面的aes-128-ctr加密算法用於解密ciphertext,我們就能夠得到自己的私鑰了
//mac的作用是用做一開始輸入密碼password的時候來判斷輸入的這個密碼是不是正確的,正確的才開始上面解密ciphertext的過程
//就是我們先通過輸入的密碼、密鑰生成函數scrypt及其參數kdfparams三者得到密文解密密鑰
//然后使用其左起第二個字節開始的16個字節以及ciphertext連接在一起,並進行哈希散列(用SHA3-256的方法)
//然后將得到的值hash與mac的值做比對,相同才說明輸入的密碼為該賬戶設置的密碼,mac也是根據上面的步驟得到的
mac:驗證密碼的編碼;
Remarks about toV3
The options
is an optional object hash, where all the serialization parameters can be fine tuned:
- uuid - UUID. One is randomly generated.隨機生成
- salt - Random salt for the
kdf
. Size must match the requirements of the KDF (key derivation function). Random number generated viacrypto.getRandomBytes
if nothing is supplied.kdf的隨機salt。大小必須符合KDF(key派生函數)的要求。通過密碼生成的隨機數。如果沒有提供任何內容,則為getRandomBytes。 - iv - Initialization vector for the
cipher
. Size must match the requirements of the cipher. Random number generated viacrypto.getRandomBytes
if nothing is supplied.密碼的初始化向量。大小必須符合密碼的要求。通過密碼生成的隨機數。如果沒有提供任何內容,則為getRandomBytes。 - kdf - The key derivation function, see below.key的推導函數
- dklen - Derived key length. For certain
cipher
settings, this must match the block sizes of those.派生key的長度,對於某些密碼設置,這必須與這些設置的塊大小匹配 - cipher - The cipher to use. Names must match those of supported by
OpenSSL
, e.g.aes-128-ctr
oraes-128-cbc
.使用密碼。名稱必須與OpenSSL支持的名稱匹配,例如aes-128-ctr或aes-128-cbc。
Depending on the kdf
selected, the following options are available too.
For pbkdf2
:
c
- Number of iterations. Defaults to 262144.迭代次數prf
- The only supported (and default) value ishmac-sha256
. So no point changing it.唯一支持的(也是默認的)值是hmac_sha256。所以沒有必要改變它。
For scrypt
:
n
- Iteration count. Defaults to 262144.迭代次數r
- Block size for the underlying hash. Defaults to 8.底層哈希的塊大小。默認為8。p
- Parallelization factor. Defaults to 1.並行化的因素。默認為1。
The following settings are favoured by the Go Ethereum implementation and we default to the same:
下面的設置是Go Ethereum實現支持的,我們默認的設置也是如此
kdf
:scrypt
dklen
:32
n
:262144
r
:8
p
:1
cipher
:aes-128-ctr
所以我們總結上面的過程,我們就知道該鑰匙文件的使用過程為:
首先,你輸入了密碼password,這個密碼將作為 kdf 密鑰生成函數的輸入,來計算密文解密密鑰。
然后,將密文解密密鑰和 ciphertext 密文連接並進行處理,和 mac 比較來確保密碼是正確的。
最后,通過 cipher 對稱函數用密文解密密鑰對 ciphertext 密文解密,得到私鑰
鑰匙文件的文件名格式為UTC。賬號列出時是按字母順序排列,但是由於時間戳格式,實際上它是按創建順序排列。
所以,在整個過程中你的密碼是惟一的輸入,你的以太坊私鑰是惟一的輸出。所需的其他信息都可以在你的以太坊賬戶創建時生成的keystore文件中獲得。
所以一定要確保你的密碼足夠強,這樣能保證即使有人得到了你的keystore文件,它也無法獲得你的私鑰。
想了解scrypt可看:
https://tools.ietf.org/html/rfc7914
https://zhuanlan.zhihu.com/p/32484253
私鑰、公鑰、地址之間的關系:
每個賬戶都由一對密鑰來定義,包括公鑰和私鑰。我們通過自己設置的密碼以及鑰匙備份文件UTC--...能夠得到自己賬戶的私鑰,私鑰通過一系列運算后能夠得到公鑰
比如比特幣系統使用了橢圓曲線簽名算法,通過私鑰可以計算出公鑰:
Hash(Hash(ECC(私鑰))) -> 公鑰
要想反向從公鑰得到私鑰是十分困難的
在以太坊中取公鑰的最后20個字節作為地址
所以,一定要將鑰匙備份文件備份保存,並且要牢記你自己的密碼,如果你丟失了鑰匙備份文件或者忘記了密碼,那么你的幣將丟失,密碼是無法找回的。