【发布时间】:2014-08-01 19:47:42
【问题描述】:
如果不是很明显,让我先说我不是加密人。
我的任务是在 Python 2.7 中复制 Java 的 PBEWithMD5AndDES(带 DES 加密的 MD5 摘要)的行为。
我确实可以使用 Python 的加密工具包 PyCrypto。
这是我试图复制其行为的 Java 代码:
import java.security.spec.KeySpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.Cipher;
import javax.xml.bind.DatatypeConverter;
public class EncryptInJava
{
public static void main(String[] args)
{
String encryptionPassword = "q1w2e3r4t5y6";
byte[] salt = { -128, 64, -32, 16, -8, 4, -2, 1 };
int iterations = 50;
try
{
KeySpec keySpec = new PBEKeySpec(encryptionPassword.toCharArray(), salt, iterations);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterations);
Cipher encoder = Cipher.getInstance(key.getAlgorithm());
encoder.init(Cipher.ENCRYPT_MODE, key, paramSpec);
String str_to_encrypt = "MyP455w0rd";
byte[] enc = encoder.doFinal(str_to_encrypt.getBytes("UTF8"));
System.out.println("encrypted = " + DatatypeConverter.printBase64Binary(enc));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
对于给定的值,它会输出以下内容:
encrypted = Icy6sAP7adLgRoXNYe9N8A==
这是我将上述内容移植到 Python 的笨拙尝试,encrypt_in_python.py:
from Crypto.Hash import MD5
from Crypto.Cipher import DES
_password = 'q1w2e3r4t5y6'
_salt = '\x80\x40\xe0\x10\xf8\x04\xfe\x01'
_iterations = 50
plaintext_to_encrypt = 'MyP455w0rd'
if "__main__" == __name__:
"""Mimic Java's PBEWithMD5AndDES algorithm to produce a DES key"""
hasher = MD5.new()
hasher.update(_password)
hasher.update(_salt)
result = hasher.digest()
for i in range(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
key = result[:8]
encoder = DES.new(key)
encrypted = encoder.encrypt(plaintext_to_encrypt + ' ' * (8 - (len(plaintext_to_encrypt) % 8)))
print encrypted.encode('base64')
它输出一个完全不同的字符串。
是否可以将 Java 实现移植到具有标准 Python 库的 Python 实现?
显然,Python 实现要求我加密的明文是 8 个字符的倍数,我什至不确定如何填充明文输入以满足该条件。
感谢您的帮助。
【问题讨论】:
-
见rfc 2898,特别是section 6.1。您需要在 CBC 模式下使用 DES,密钥是前 8 个字节,IV 是哈希结果的后 8 个字节。
-
这是一种错误的密码派生方法,不应使用。而是使用随机盐在 HMAC 上迭代大约 100 毫秒(盐需要与哈希一起保存)。使用 password_hash、PBKDF2、Bcrypt 等函数和类似函数。关键是让攻击者花费大量时间通过蛮力寻找密码。请参阅 OWASP(开放式 Web 应用程序安全项目)Password Storage Cheat Sheet。
-
另请参阅 Security Stackexchange 上的 How to securely hash passwords, The Theory。
标签: java python-2.7 encryption md5 des