OpenSSL的enc实用程序对密码使用非标准(和低质量)密钥派生算法.以下代码显示了enc实用程序如何生成密钥和初始化向量,给定salt和密码.请注意,enc在-salt指定选项时,将"salt"值存储在加密文件中(这对于安全性至关重要).
public InputStream decrypt(InputStream is, byte[] password)
throws GeneralSecurityException, IOException
{
/* Parse the "salt" value from the stream. */
byte[] header = new byte[16];
for (int idx = 0; idx < header.length;) {
int n = is.read(header, idx, header.length - idx);
if (n < 0)
throw new EOFException("File header truncated.");
idx += n;
}
String magic = new String(header, 0, 8, "US-ASCII");
if (!"Salted__".equals(magic))
throw new IOException("Expected salt in header.");
/* Compute the key and IV with OpenSSL's non-standard method. */
SecretKey secret;
IvParameterSpec iv;
byte[] digest = new byte[32];
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(password);
md5.update(header, 8, 8);
md5.digest(digest, 0, 16);
md5.update(digest, 0, 16);
md5.update(password);
md5.update(header, 8, 8);
md5.digest(digest, 16, 16);
iv = new IvParameterSpec(digest, 24, 8);
DESedeKeySpec keySpec = new DESedeKeySpec(digest);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
secret = factory.generateSecret(keySpec);
}
finally {
Arrays.fill(digest, (byte) 0);
}
/* Initialize the cipher. */
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, iv);
return new CipherInputStream(is, cipher);
}
Run Code Online (Sandbox Code Playgroud)
EVP_BytesToKey(3)文档中描述了此密钥和IV生成.该enc命令1用作迭代count(这是一个坏主意,并在我的版本的手册页中标注为错误enc),MD5作为摘要算法 - 一个"破碎"算法.
目前尚不清楚OpenSSL如何将文本密码转换为字节.我猜它使用默认的平台字符编码.因此,如果您遇到String密码(不好,因为它不能"零化"),您可以调用password.getBytes()将其转换为byte[].
如果可以的话,可以使用Java 6 Console或Swing JPasswordField来获取密码.这些返回一个数组,因此您可以在完成后从内存中"删除"密码:Arrays.fill(password, '\0');
| 归档时间: |
|
| 查看次数: |
2886 次 |
| 最近记录: |