最近梳理了下,发现加密钱包的种类真是越来越多,我记得最早只有比特币钱包,只能 pc 上使用,后来随着币的种类越来越多,用于多币种统一管理的钱包越来越多,后来好多交易所也推出了自己的钱包,主打一个百花齐放,现在我看主流常见的手机端加密钱包的数量都有几十个。
这么多钱包,使用起来倒是越来越方便了,可是也带来了一些问题,因为加密钱包的去中心化特性,导致其核心信息都在本地存储,如助记词、私钥、keystor、密码等。
但凡一个粗心导致信息错误或者丢失,就可能意味着钱包资产脱离自己的控制了。助记词的问题还好说,缺失那么一两个都还能通过跑程序来恢复,但是这个密码忘记了,我从没想过会是个问题,因为我们可以通过助记词来导入钱包呀,直到最近遇到个朋友:
他用的是 tokenPocket
钱包,然后助记词没备份,密码也忘记了,问我的时候,我第一感觉是没办法了,没有助记词肯定不行呀,不过他说钱包没卸载还能正常打开看到余额呢,只是操作的时候,需要密码,而自己疏忽把密码也忘记了。
正文
经过一段时间的研究,我发现这种情况下,钱包恢复并不是不可能,因为当前手机钱包没卸载,意味着钱包数据问题都还在本地存储卡上,只要找到它的加密文件,进行解密即可,助记词、私钥、密码等信息都可以恢复。 不过,因为钱包种类太多,每家情况不太一样,比如说加密算法肯定是各家都有一些差异,所以解密方法也不通用。
以 TP 钱包为例,通过抓包能获取到它的加密密码(安卓可以,ios 不行),但是不知道具体的加密算法, sha256、md5等常见的加密算法肯定有用到,但是进行了处理和组合,增加了salt、iv等信息,使每次生成的加密密码不同。
我在app上测试了下,当改密码后又改回来旧的密码,密钥也变回来啦!这个观察很有趣!如果改回相同的密码后密钥也恢复了,那说明这个系统的设计和我之前理解的不太一样。这意味着:盐值(salt) 可能是通过某种确定性的方式从密码生成的,而不是随机生成或者系统中存在一个主密钥或种子,用来确定性地生成加密参数让我们看看代码中的关键部分:
function a(e, t) {
var r = i.utf8ToBuffer(e); // e 是码
var o = i.base64ToBuffer(t); // t 是 salt
return global.crypto.subtle.importKey(
"raw",
r,
{ name: "PBKDF2" },
false,
["deriveBits", "deriveKey"]
).then(function(e) {
return global.crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: o,
iterations: 10000,
hash: "SHA-256"
},
e,
{
name: "AES-GCM",
length: 256
},
false,
["encrypt", "decrypt"]
);
});
}
经过一段时间的研究,终于有所进展,可以说,像这种加密钱包的密码忘记,通过解密程序和密码字典,进行暴力破解,是可以实现的。
解码需要的时间,会根据密码长度和解密设备的性能而不同,tokenPocket
一般允许至少 8位长度的密码,以8位为例子,一般 5 小时左右可以破解,如果有复杂符号如(. ~!@#$%^&)等,时间会更久一点。
总结
通过本文的分析,可以得出结论,加密钱包的密码忘记了,在特定情况下,恢复是有可能的。
---