【发布时间】:2020-10-08 04:51:15
【问题描述】:
我正在使用 Java 的 Crypto 库实现一个简单的 AES-128 加密程序。
不幸的是,这并不总是很好。有时会发生明文字符串中的双引号(“)在加密然后解密时,在解密的字符串中显示为�。
据我了解,这个字符是�(�),是UTF-8解码器遇到错误时使用的替换字符。
因此,我的问题是为什么会发生此错误,为什么只是有时以及如何解决?
这是我的加密和解密代码块:
public static String encrypt(String value)
{
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String encrypted)
{
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
以下是一些示例案例:
案例 1:导致错误
Enter Plaintext: had no pictures or conversations in it, “and what is the use of a book,” thought Alice “without pictures or conversations?”
Encrypted String: UgapiW5aYIKkoKkyeHvvFlgf8mCIq1AopmCtYGiJ23eNILNn1OXtM4enEvB5Kt1imNmynyHCCjLbbjB7TV0sq2F3Iz+YUehOw50gje6IMj8fpaEracq1NvZQXSH5T8fyBtAUH3weU5FE5vr3dYmwTSGUxNR2gaRV6MV7vmcEuIz7A5MLnKjsb2+1Sya+l/k2
Enter Ciphertext: UgapiW5aYIKkoKkyeHvvFlgf8mCIq1AopmCtYGiJ23eNILNn1OXtM4enEvB5Kt1imNmynyHCCjLbbjB7TV0sq2F3Iz+YUehOw50gje6IMj8fpaEracq1NvZQXSH5T8fyBtAUH3weU5FE5vr3dYmwTSGUxNR2gaRV6MV7vmcEuIz7A5MLnKjsb2+1Sya+l/k2
After decryption: had no pictures or conversations in it, �and what is the use of a book,� thought Alice �without pictures or conversations?�
案例 2:没有问题
Enter Plaintext: Hello there, "Camera-man". He's sitting now.
Encrypted String: jb2QJ5nLQCjGKw6l2q9GnX6jgTJVGWn6LiVRfE5oRT7WT7vYNejKPHIhgorbfaob
Enter Ciphertext: jb2QJ5nLQCjGKw6l2q9GnX6jgTJVGWn6LiVRfE5oRT7WT7vYNejKPHIhgorbfaob
After decryption: Hello there, "Camera-man". He's sitting now.
【问题讨论】:
-
我相信加密的东西在这里不相关;相反,问题一定出在
value.getBytes()和new String(original)的往返过程中。您的“案例 1:导致错误”和“案例 2:没有问题”之间的区别在于案例 1 涉及非 ASCII 大引号。作为更好地理解问题的第一步,我建议循环value.toCharArray()并将字符打印为整数(最好是十六进制),然后对value.getBytes()执行相同的操作。 -
你完全正确!两个双引号是不同的。案例 1 中的 UNICODE 值为 8220,而案例 2 中的那个是 ASCII 34。我从不同的来源复制了大引号,这就是导致问题的原因。现在我想我的问题是,我能做些什么来解决这个问题?有没有办法自动将非 ASCII 双引号更改为 ASCII 双引号并对其他此类字符执行相同操作?
标签: java encoding utf-8 cryptography aes