文件结构
分解分析
Index
首先 Index 是利用了 MsgPack 压缩的,利用 Python 脚本解密
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
with open('Index', 'rb') as f: index = umsgpack.unpack(f)
masterPasswordSalt = index['s'] encryptedDescriptorData = index['d'] encryptedDescriptorDataNonce = index['dn'] version = index['v']
print(len(masterPasswordSalt), masterPasswordSalt.hex()) print(len(encryptedDescriptorData), encryptedDescriptorData.hex()) print(len(encryptedDescriptorDataNonce), encryptedDescriptorDataNonce.hex()) print(version)
|
拿到的 index
是一个有四个键的字典,这四个键含义分别为
s
masterPasswordSalt 主密码的盐,固定为 16 Bytes
d
encryptedDescriptorData
dn
encryptedDescriptorDataNonce 加密 descriptorData 使用的随机数,固定为 24 Bytes
v
version 当前数据库版本(目前固定为 1)
下一步就是根据用户的主密码 masterPassword 和盐 masterPasswordSalt 生成用于加密的 masterKey 了,这用到了 Argon2id 算法,利用 Python 实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
from pysodium import crypto_pwhash from pysodium import crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_MODERATE, crypto_pwhash_ALG_DEFAULT
masterKey = crypto_pwhash( 32, masterPassword, masterPasswordSalt, crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_MODERATE, crypto_pwhash_ALG_DEFAULT )
print(len(masterKey), masterKey.hex())
|
生成 masterKey 后利用之前的 encryptedDescriptorData 校验 masterKey 是否正确
1 2 3 4 5 6
| from pysodium import crypto_secretbox_open
descriptorData = crypto_secretbox_open(encryptedDescriptorData, encryptedDescriptorDataNonce, masterKey) unzippedDescriptorData = umsgpack.loads(descriptorData)
realMasterKey = unzippedDescriptorData['masterKey']
|
参考信息
How Elpass Encrypt Your Data
surge-networks/Elpass-Core
jedisct1/swift-sodium
Password hashing
stef/pysodium