使用OpenSSL加密的方式与Java相同

我必须使用bash脚本加密字符串,就像我使用javax.crypto.Cipher加密一样。 在java我使用AES-256,密钥为“0123456789”。 但是当我使用openssl时我不得不将“0123456789”转换为hex,但结果与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")); } } 

d230b216e9d65964abd4092f5c455a21

如果无数的在线hex转换器不起作用,那么您只需将您在Java中使用的密钥打印为hex即可。 这是一个关于这个壮举的流行SO问题。

完成后,您将看到它仍然无效,因为您使用的是不同的算法。

使用Cipher.getInstance("AES"); 它很可能默认为“AES / ECB / 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代码将结果输出为hex,因此您需要在OpenSSL中执行相同操作。 您需要删除OpenSSL命令中的-a选项以防止Base64编码,然后您可以利用其他命令行工具(如Linux上的od将二进制输出数据转换为带有od -tx1hex。

  • 完整命令:

     echo -n lun01 |openssl aes-128-ecb -K 30313233343536373839000000000000 |od -tx1 

不要使用ECB模式! 它在语义上不安全。 您需要至少使用带有随机IV的CBC模式(检查它是随机的,而不仅仅是零字节)。

更好的方法是添加身份validation,例如添加带有加密 – 然后 – MAC方法的HMAC标记,或者只使用像GCM这样的身份validation模式。


如果您使用的是ECB以外的任何其他内容,那么您无法在两个版本中加密相同的内容并期望出现相同的密文。 由于它是随机的,您需要在一个版本中加密并在另一个版本中解密以确保兼容性。