因此,我正在尝试了解旧的Windows系统如何散列用户密码。根据https://asecuritysite.com/encryption/lmhash,纯文本密码:;
1) 转换为大写和空,最多可填充14个字节;
2) 14字节的密码被分成两个7字节的散列;
3) 7字节值用于创建两个64位DES密钥(每七位添加一个奇偶校验位);
4) 每个密钥使用DES(使用ECB)对字符串"KGS!+#$%"进行加密,该字符串提供两个8字节的密码值
我正在尝试散列密码"PassWord123"(这是这篇technix文章中使用的一个例子)。
应用上面的步骤,我得到了(如果我做错了什么,请随时纠正我):;
1) 密码23000;
2) PASSWOR和D123000;
3) 密码1和D1230001;
4) 9F85D1B92510E5B3和C477143B02BC6ACF(使用此工具和Python脚本来查找这些值);
尽管如此,步骤4应该给我E52CAC67419A9A22和664345140A852F61(使用https://asecuritysite.com/encryption/lmhash以及另一个Python脚本)。
有人知道我做错了什么吗?非常感谢!
有点晚了,但最近我在学习LM哈希时也尝试做同样的事情。
正如注释所指出的,0
的填充为NULL字节,即字面上的x00
字符
然后第二个可能的问题是,站点错误地说"KGS!+#$%"
是加密的字符串,而实际上是"KGS!@#$%"
字符串(注意@
而不是+
)。
密钥被分成7个字符的块,但大多数DES函数需要8个字节作为密钥。因此,您需要使用奇偶校验位扩展散列,这是一个稍微复杂的过程,但在passlib等库中已经完成了。在7个字符的块上运行他们的des.expand_des_key
函数将为您提供DES加密的8字节密钥。
把这些放在一起,我们可以在Python:中这样半手动地进行计算
from Crypto.Cipher import DES # pycryptodome
from passlib.utils import des # passlib
def lm(plaintext: bytes):
plaintext = plaintext.upper()
plaintext = plaintext.ljust(14, b"x00")
key1, key2 = des.expand_des_key(plaintext[:7]), des.expand_des_key(plaintext[7:])
print(key1, key2)
hash1 = DES.new(key1, DES.MODE_ECB).encrypt(b"KGS!@#$%")
hash2 = DES.new(key2, DES.MODE_ECB).encrypt(b"KGS!@#$%")
return hash1 + hash2
if __name__ == "__main__":
print(lm(b"PassWord123").hex())
# e52cac67419a9a22664345140a852f61
这正确地计算了E52CAC67419A9A22
和664345140A852F61
部分,并且表明中间8字节密钥几乎是不可识别的(b'P Tj4xba<xa4'
和b'Dx18LF0x00x00x00'
)。