105 lines
3.6 KiB
Python
105 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""测试密码哈希解码"""
|
|
|
|
import base64
|
|
import hashlib
|
|
import hmac
|
|
|
|
# 从数据库中的实际密码哈希
|
|
password_hash = "$pbkdf2-sha256$29000$N2aBd1I5Eaz5bYY2CXbu2A$1lEXwDoX9S5slrv0cFHsQ8fAj55m43.1mPbX5f.Ra0U"
|
|
password = "admin123"
|
|
|
|
print(f"密码哈希: {password_hash}")
|
|
print(f"密码: {password}\n")
|
|
|
|
# 解析
|
|
parts = password_hash.split('$')
|
|
if len(parts) == 5:
|
|
iterations = int(parts[2])
|
|
salt_str = parts[3]
|
|
hash_str = parts[4]
|
|
|
|
print(f"迭代次数: {iterations}")
|
|
print(f"Salt 字符串: {salt_str} (长度: {len(salt_str)})")
|
|
print(f"Hash 字符串: {hash_str} (长度: {len(hash_str)})")
|
|
print()
|
|
|
|
# 尝试解码 salt
|
|
print("=== 解码 Salt ===")
|
|
salt_variants = [
|
|
(salt_str, "原始"),
|
|
]
|
|
|
|
salt_bytes = None
|
|
for variant, desc in salt_variants:
|
|
try:
|
|
# 添加填充
|
|
missing = len(variant) % 4
|
|
if missing:
|
|
variant += '=' * (4 - missing)
|
|
decoded = base64.b64decode(variant, validate=False)
|
|
print(f"OK {desc}: 成功,长度 {len(decoded)}")
|
|
salt_bytes = decoded
|
|
break
|
|
except Exception as e:
|
|
print(f"FAIL {desc}: 失败 - {e}")
|
|
|
|
print()
|
|
print("=== 解码 Hash ===")
|
|
# 尝试多种方式解码 hash
|
|
hash_variants = [
|
|
(hash_str, "原始"),
|
|
(hash_str.replace('.', ''), "移除点号"),
|
|
(hash_str.replace('.', '+'), "点号替换为+"),
|
|
(hash_str.replace('.', '/'), "点号替换为/"),
|
|
(hash_str.replace('.', '='), "点号替换为="),
|
|
(hash_str.replace('.', 'A'), "点号替换为A"),
|
|
(hash_str.replace('.', 'B'), "点号替换为B"),
|
|
]
|
|
|
|
stored_hash_bytes = None
|
|
for variant, desc in hash_variants:
|
|
try:
|
|
# 移除填充
|
|
variant_clean = variant.rstrip('=')
|
|
# 添加填充
|
|
missing = len(variant_clean) % 4
|
|
if missing:
|
|
variant_clean += '=' * (4 - missing)
|
|
|
|
decoded = base64.b64decode(variant_clean, validate=False)
|
|
if decoded and len(decoded) > 0:
|
|
print(f"OK {desc}: 成功,长度 {len(decoded)}")
|
|
stored_hash_bytes = decoded
|
|
break
|
|
except Exception as e:
|
|
print(f"FAIL {desc}: 失败 - {e}")
|
|
|
|
print()
|
|
if salt_bytes and stored_hash_bytes:
|
|
print("=== 计算 PBKDF2 ===")
|
|
password_bytes = password.encode('utf-8')
|
|
computed_hash = hashlib.pbkdf2_hmac('sha256', password_bytes, salt_bytes, iterations)
|
|
|
|
print(f"计算的哈希长度: {len(computed_hash)}")
|
|
print(f"存储的哈希长度: {len(stored_hash_bytes)}")
|
|
|
|
match = hmac.compare_digest(computed_hash, stored_hash_bytes)
|
|
print(f"\n匹配结果: {match}")
|
|
|
|
if not match:
|
|
print("\n=== 尝试不同的 hash 长度 ===")
|
|
# 尝试不同的长度
|
|
for i in range(max(0, len(stored_hash_bytes) - 5), len(stored_hash_bytes) + 5):
|
|
if i == len(stored_hash_bytes):
|
|
continue
|
|
test_hash = stored_hash_bytes[:i] if i < len(stored_hash_bytes) else stored_hash_bytes + b'\x00' * (i - len(stored_hash_bytes))
|
|
if len(test_hash) == len(computed_hash):
|
|
test_match = hmac.compare_digest(computed_hash, test_hash)
|
|
if test_match:
|
|
print(f"OK 长度 {i} 匹配成功!")
|
|
break
|
|
else:
|
|
print("无法解码 salt 或 hash")
|
|
|