冷钱包一般常用的地址导入及备份方式有keystore
、private key
、mnemonicv
三种,不同的钱包偏重不同。
Keystore是一个分组密码,它使用加密散列函数来加密或解密您以太坊帐户的私钥。这是在您生成私钥来加密私钥后完成的(也就是说,您必须提供密码和此文件,而不仅仅是私钥)
所以说,光备份了Keystore但忘记了钱包密码也是无用的。
就像之前提到的,一个以太坊账户就是用于加密签署交易的一个私钥—公钥对。
为了确保你的私钥没有在文件中明文存储(即任何人只要能得到这个文件就能读),
使用强对称算法(cipher)对其加密至关重要。
在imtoken创建的钱包生成的keystore文件示例:
{
"version":3,
"id":"d57df606-1b86-447a-a60e-18a539f9d92e",
"address":"dd750189c1d4b984dd09c6cb1872577876cda740"
"crypto":{
//私钥加密
"cipher":”aes-128-ctr”,
"cipherparams":{"iv":"262497534d19d7ea4a3998db620871d1”},
//密文
"ciphertext":"18393e50d7ee3e95ab9c2e96dc1af14a42c4aad07c722292811c650229cb0c06”,
//通过密码解密密钥
"kdf":"scrypt”,
"kdfparams" {
"dklen":32,
"r":8,
"salt":"816c5b4b063aead329b043be0c2e2996e08a48af8bd392c32bc9d68786e6ced4",
"p":1,
"n":262144
},
"mac":"84ab5797ba8a87e8e6edd98360368077387ee1e01671bdaef517caf14b059837”,
},
}
参数详解:
version
- 版本号
address
- 是加密后的公钥,明文显示
id
- 随机
crypto
包含参数:
-
cipher
- 对称 AES 算法的名称;(默认为aes-128-ctr
),128代表位。又名“128位密钥”或“256位密钥”。数字越高,越安全。 -
iv
- aes-128-ctr加密算法需要的初始化向量,大小必须符合密码的要求。如果没有提供,则通过crypto.getRandomBytes生成随机数。
初始化矢量(**IV**)是AES-128-CBC密码中使用的每个备份的16字节唯一字符串。它来源于加密密钥和实际的元数据明文。
- EK是加密后的私钥
- 加密密钥(**EK**)是AES-128-CBC算法和PKCS7填充的16字节加密密钥。它被定义如下:
EK = HMAC-SHA256(key: BackupKey, data: "Encryption Key")[0, 16]
- iv是加密后的EK
-
ciphertext
- 你的以太坊私钥使用上述cipher
算法进行加密,密文是aes-128-ctr
函数的加密输入 -
cipherparams
- 上述 cipher 算法需要的参数
以太坊用了一个密钥生成函数,输入密码和一系列参数就能计算解密密钥。这就是 kdf
和 kdfparams
的用途
-
kdf
- 密钥派生函数。可能是scrypt或pbkdf2。这是你做了多少次努力才能使其更难以暴力。这种增加的计算工作使密码破解变得更加困难,并被称为密钥扩展。(这里默认为scrypt
)
而不是仅仅去:
`password -> hashed password`
它走了:
`password -> (MATH * 262144) -> hashed password.`
-
kdfparams
- 上述 kdf 算法需要的参数;(scrypt算法需要的参数) -
mac
- 用于验证密码的代码,将导出密钥的最后16个字节与完整密文连接起来的SHA3(keccak-256)
验证密码流程:
1. 用户输入密码`password`+`salt`+`n`+`R`+`p`+`dklen`进行`scrypt`加密,得出`derivedkey`
2. `derivedkey`+`iv`+`私钥`进行`aes128`加密得出`ciphertext`,长度为 64 位
3. `derivedkey` +`ciphertext`(加密的私钥)进行`sha3-256`加密得出`Mac`,长度为 64 位
// 通过1+3来判断用户的密码是否输入正确。
简单来说,dklen
、n
、r
、p
和 salt
是 kdf
函数的参数。
dklen:32
,- 派生密钥长度(以字节为单位)。对于某些密码设置,这必须匹配那些块大小。
n:262144
,- 迭代计数。geth的默认值为262144。因为浏览器不喜欢做262,144次事情,所以MEW降低。基本上,这是(MATH * 262144)从上面的数字。
r:8
,- 底层散列的块大小。默认为8。
p:1
- 并行化因素。默认为1.基本上,你必须去0 ... 1 ... 2 ... 262143 ... 262144或262144 ... 262143 ... 2 ... 1 ... 0,你不能并行运行它们。如果您将其更改为2AES,我不知道它是否会改变任何内容。我不认为它的确如第2轮的散列那样是第#轮第1轮的散列,这是第0轮的散列。
salt
- kdf的随机盐。大小必须符合KDF(密钥派生函数)的要求。如果没有提供,则通过crypto.getRandomBytes生成随机数。
/*
如果我只能CPU破解,我可以减少/覆盖我的scrypt设置为1024 * 8 * 1,所以我可以GPU破解它?
不可以。更改 N 将改变迭代计数,这将改变散列。如果您减少数字以使您认为自己是#winning,Hashcat将会大大加速,但即使您的字典中包含明文,它也不会破解散列。
*/
//步骤1:(128 * 8)* 262144 = 1024 * 262144 = 268,435,456字节= 256MB
//步骤2:64(AMD卡)* 64([RX Vega 64具有64个CU]
// (https://www.techpowerup.com/gpudb/2871/radeon-rx-vega-64))= 4,096个并行计算
//步骤3:256MB * 4,096 = 1,048,576 MB RAM = **Vega 64需要1,024 GB RAM**
- 所以,如果我忘记了内置£30,000的我的Eth钱包的密码,那么可能需要几年时间才能破解?!?!
- 对。
//n的值越大,加密级别越高,当然消耗的内存越大。
keystore流程图如下:
Merkle Root是从密文构建的Merkle树的32字节根。为了简单起见,我们使用与比特币块中使用的相同的merkle树。由于这个merkle树容易受到突变(如果最后一个节点是奇数,它可以在不改变根哈希的情况下被复制),客户端将需要重新计算和验证IV值,因为它们也充当明文MAC。该密文被解释为正在使用散列1024字节块列表Hash256。Ciphertext的最终块长度根据比特币Merkle树规范,如果元素(块或哈希)的任何中间列表是奇数,则最后一个元素将被复制。如果整个密文长度是1024个字节或更少,那么它的Hash256是一个merkle根。
参考链接:
https://stealthsploit.com/2018/01/04/ethereum-wallet-cracking-pt-2-gpu-vs-cpu/
https://ethereum.stackexchange.com/questions/37150/ethereum-wallet-v3-format?rq=1