openssl enc 默认使用(适度)非标准的基于密码的加密算法,以及自定义但简单的数据格式。
- 如果你真的不需要PBE,只有一些 openssl 加密,the question linked by @Artjom 有一个很好的答案:在 openssl 中使用“原始”密钥和IV,然后使用相同的密钥和IV在爪哇。并让它们都默认为“PKCS5”(实际上是 PKCS#7)填充。请注意,
openssl enc 采用十六进制的 -K 和 -iv,而 Java 加密将它们作为字节;根据需要进行转换。因为/如果你对密文进行base64-ed,首先de-base64;这是在 java8 中提供的,并且有许多可用于早期 java 版本的库。
否则需要解压文件格式。 de-base64后,丢弃前8个字节,取后8个字节为salt,其余字节为密文。
如果您需要特定算法 AES128-CBC 或 192 或 256 的 PBE 并且您可以使用第三方加密库 http://www.BouncyCastle.org ,它为这三种算法实现了 openssl PBE。将SecretKeyFactory 实例化为PBEWITHMD5AND128BITAES-CBC-OPENSSL -- 或 192 或 256,但前提是安装了 Unlimited Strength Policy(更新:或 Oracle 版本 >= 8u161 或 OpenJDK) -- 并给它一个 PBEKeySpec,键为 chars、salt ,计数为 1,并在同一算法的 Cipher 中使用结果。
否则您必须自己进行 PBE。幸运的是(?)这很简单。把下面的方法放在方便的地方:
public static /*or as appropriate */ void opensslBytesToKey (
byte[] pass, byte[] salt /*or null*/, // inputs
int iter, String hashname, // PBKDF1-ish
byte[] key, byte[] iv /*or null*/ // outputs
) throws NoSuchAlgorithmException
{
MessageDigest md = MessageDigest.getInstance (hashname);
byte[] temp = null, out = new byte[key.length+(iv!=null?iv.length:0)];
int outidx = 0;
while(outidx < out.length){
if(temp!=null) md.update(temp);
md.update(pass);
if(salt!=null) md.update(salt);
temp = md.digest();
for(int i=1; i<iter; i++) temp = md.digest (temp);
int use = Math.min (out.length-outidx, temp.length);
System.arraycopy (temp,0, out,outidx, use);
outidx += use;
}
System.arraycopy (out,0, key,0, key.length);
if(iv!=null) System.arraycopy (out,key.length, iv,0, iv.length);
}
并使用密码作为字节、盐、迭代计数 1、“MD5”和输出数组来调用它,这些数组的大小适合您的 AES 密钥(16、24 或 32 字节)和 AES IV(始终16 字节)。在SecretKeySpec 和IvParameterSpec 中分别使用这些,Cipher 用于(更正)AES/CBC/PKCS5Padding。
除此之外:您不能像这样加密字符串,只能加密 bytes(或更准确地说是 octets)。几乎所有系统上的 C 程序(包括 openssl)都将字符串/字符 in ASCII 隐式转换为字节和从字节转换,但使用 ASCII 集之外的任何字符可能会产生不一致和不可用的结果。 Java 将字符串 / 字符视为 Unicode(或更准确地说是 UTF-16),并将它们显式地转换为字节或从字节转换;这种转换对于 ASCII 是可靠的(并且与 C 一致),但对于非 ASCII 字符可能会有所不同。
更新:OpenSSL 1.1.0 (2016-08) 将 enc PBE 的默认哈希值从 MD5 更改为 SHA256。根据用于加密的 OpenSSL 版本,或者是否使用了(以前未记录的)-md 选项,更改我的选项 3 中的调用。更多详情见(我的)https://crypto.stackexchange.com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption/#35614