我必须使用 bash 脚本加密字符串,就像使用 javax.crypto.Cipher 加密一样。在java中,我使用AES-256和密钥“0123456789”。但是当我使用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"));
}
}
d230b216e9d65964abd4092f5c455a21
如果无数的在线十六进制转换器不适合您,那么您可以简单地将您在 Java 中使用的密钥打印为十六进制。Here https://stackoverflow.com/q/9655181是一个关于此的热门问题feat.
完成此操作后,您会发现它仍然不起作用,因为您使用了不同的算法。
当你使用Cipher.getInstance("AES");
它很可能默认为“AES/ECB/PKCS5Padding”,这与“aes-256-cbc”不同,因为 ECB 和 CBC 是两个完全不同的运作模式 https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation。为了防止这种歧义,请始终完全限定您的密码,例如:Cipher.getInstance("AES/CBC/PKCS5Padding");
.
那么您在 Java 中生成的密钥只有 16 个字节长,因此 OpenSSL 中的匹配密码将是“aes-128-ecb”。
正如 dave_thompson_085 在 a 中所说comment https://stackoverflow.com/questions/32018672/encrypt-using-openssl-in-the-same-way-java-does#comment51946640_32018672:
-
echo
添加 Java 代码未添加的换行符。您需要以这种方式创建明文:echo -n "lun01"
。或者看this https://stackoverflow.com/questions/7105433/windows-batch-echo-without-new-line如果您使用的是 Windows。
-
您的 Java 代码将结果输出为十六进制,因此您需要在 OpenSSL 中执行相同的操作。您需要删除-a
OpenSSL 命令中的选项来阻止 Base64 编码,然后您可以利用其他命令行工具,例如od
在linux上将二进制输出数据转换为十六进制od -tx1
.
-
完整命令:
echo -n lun01 |openssl aes-128-ecb -K 30313233343536373839000000000000 |od -tx1
安全建议
不要使用 ECB 模式!它在语义上不安全。您需要至少使用带有随机 IV 的 CBC 模式(检查它是随机的而不仅仅是零字节)。
更好的方法是添加身份验证,例如使用先加密后 MAC 的方法添加 HMAC 标签,或者简单地使用 GCM 等身份验证模式。
附加信息
如果您使用的是 ECB 以外的任何内容,那么您无法在两个版本中加密相同的内容并期望出现相同的密文。由于它是随机的,您需要在一个版本中加密并在另一个版本中解密以确保兼容性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)