我必须使用bash脚本加密字符串,就像我使用javax.crypto.Cipher加密一样。在java中,我使用密钥为"0123456789"的AES-256。但是当我使用openssl时,我不得不将"0123456789"转换为十六进制,但结果与java 不同
echo "lun01" | openssl aes-256-cbc -e -a -K 7573746f726530313233343536373839 -iv 7573746f726530313233343536373839
dpMyN7L5HI8VZEs1biQJ7g==
Java:
public class CryptUtil {
public static final String DEFAULT_KEY = "0123456789";
private static CryptUtil instance;
private String chiperKey;
private CryptUtil(String chiperKey) {
this.chiperKey = chiperKey;
}
public static CryptUtil getInstance() {
if (null == instance) {
instance = new CryptUtil(DEFAULT_KEY);
}
return instance;
}
public static CryptUtil getInstance(String cipherkey) {
instance = new CryptUtil(cipherkey);
return instance;
}
public String aesEncrypt(String plainText) {
byte[] keyBytes = Arrays.copyOf(this.chiperKey.getBytes("ASCII"), 16);
SecretKey key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cleartext = plainText.getBytes("UTF-8");
byte[] ciphertextBytes = cipher.doFinal(cleartext);
final char[] encodeHex = Hex.encodeHex(ciphertextBytes);
return new String(encodeHex);
return null;
}
public static void main(String[] args) {
CryptUtil cryptUtil = CryptUtil.getInstance();
System.out.println(cryptUtil.aesEncrypt("lun01"));
}
}
d230b216e9d65964bd4092f5c455a21
如果无数的在线十六进制转换器不适合您,那么您可以简单地将Java中使用的密钥打印为十六进制。这是一个关于壮举的SO常见问题。
完成后,你会发现它仍然不起作用,因为你使用的是不同的算法。
当你使用CCD_ 1时,它很可能默认为"0";AES/EBC/PKCS5Padding";这与";aes-256-cbc";,因为ECB和CBC是两种完全不同的运作模式。为了防止这种歧义,请始终完全限定您的密码,例如:Cipher.getInstance("AES/CBC/PKCS5Padding");
。
那么您在Java中生成的密钥只有16字节长,因此OpenSSL中的匹配密码将是";aes-128-ecb";。
正如dave_thompson_085在评论中所说:
-
echo
添加了一个换行符,Java代码没有添加该换行符。您需要以这种方式创建明文:echo -n "lun01"
。如果你在Windows上,也可以看到这个。 -
您的Java代码将结果输出为十六进制,因此您需要在OpenSSL中执行同样的操作。您需要删除OpenSSL命令中的
-a
选项以防止Base64编码,然后您可以使用其他命令行工具,如linux上的od
,使用od -tx1
将二进制输出数据转换为十六进制。 -
完整命令:
echo -n lun01 |openssl aes-128-ecb -K 30313233343536373839000000000000 |od -tx1
安全建议
不要使用ECB模式!它在语义上不安全。您至少需要将CBC模式与随机IV一起使用(检查它是否是随机的,而不仅仅是零字节(。
更好的方法是添加身份验证,例如使用先加密后MAC的方法添加HMAC标签,或者简单地使用像GCM这样的身份验证模式。
其他信息
如果你使用的是ECB以外的任何东西,那么你就不能在两个版本中加密相同的东西,并期望出现相同的密文。由于它是随机的,您需要在一个版本中加密,在另一个版本进行解密,以确保兼容性。