openssl des3在java中解密

有没有办法解密使用openssl -des3 enc命令加密的文件。 究竟openssl如何使用密码和盐来制作密钥?

OpenSSL的enc实用程序对密码使用非标准(和低质量)密钥派生算法。 以下代码显示了enc实用程序如何生成密钥和初始化向量,给定salt和密码。 请注意,当指定-salt选项时, enc会将“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); } 

EVP_BytesToKey(3)文档中描述了此密钥和IV生成。 enc命令使用1作为迭代count (这是一个坏主意,并且在我的enc版本的手册页中被标记为bug),并且MD5作为摘要算法 - “破坏”算法。

目前尚不清楚OpenSSL如何将文本密码转换为字节。 我猜它使用默认的平台字符编码。 因此,如果您遇到String密码(不好,因为它不能“归零”),您只需调用password.getBytes()将其转换为byte[]

如果可以的话,可以使用Java 6的Console或Swing的JPasswordField来获取密码。 这些返回一个数组,因此您可以在完成后从内存中“删除”密码: Arrays.fill(password, '\0');

谢谢你,埃里克森,你的post。 它帮助我极大地尝试重新创建openssl的密码和IV例程。

我最终得到了一些略有不同的东西,可能是因为我需要解密blowfish加密的数据而不是DES。 见下文。

此外,我发现openssl在遇到字节00,0a或0d时将停止读取密码。 一般来说,我认为openssl只读取字节11和127之间的密码字符。因此,对于下面的示例,我的代码在此之前截断密码,如果它包含00,0a或0d。

  /* Compute the key and IV with OpenSSL's non-standard method. */ final byte[] digest = new byte[32]; final MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(password, 0); // append the salt md5.update(salt); // run the digest and output 16 bytes to the first 16 bytes to the digest array. Digest is reset md5.digest(digest, 0, 16); // write the first 16 bytes from the digest array back to the buffer md5.update(digest, 0, 16); // append the password md5.update(password, 0); // append the salt md5.update(salt); // run the digest and output 16 bytes to the last 16 bytes of the digest array md5.digest(digest, 16, 16); key = Arrays.copyOfRange(digest, 0, 16); iv = Arrays.copyOfRange(digest, 16, 24); 

上面的代码可以使用org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator替换为3行。 它成为了

 final OpenSSLPBEParametersGenerator generator = new OpenSSLPBEParametersGenerator(); generator.init(password, salt); final ParametersWithIV ivParam = (ParametersWithIV)generator.generateDerivedParameters(16, 8); final KeyParameter keyParameter = (KeyParameter)ivParam.getParameters();