如何解决Java-为什么我的AES程序不加密/解密双引号?
我正在使用Java的Crypto库实现一个简单的AES-128加密程序。
不幸的是,这并非一直都很好。有时会发生这样的情况,即在加密然后解密后,将纯文本字符串中的双引号(“)表示为``。
从我发现的结果来看,这个字符是&#xfffd(&#65533),这是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,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.
解决方法
我相信加密货币在这里无关紧要;相反,问题必须出在String.getBytes()和新String(byte [])的往返中。您的“情况1:导致错误”涉及非ASCII的双引号(而“情况2:没有问题”则使用常规的ASCII引号),因此系统上的String.getBytes()和新String(byte [])显然没有不能很好地处理这个角色。 (这些方法记录为使用“平台的默认字符集”,显然您平台的默认字符集是不支持该字符的字符集。)
要解决此问题,我想您需要做的就是使用String.getBytes(Charset)从String.getBytes()切换到new String(byte[],Charset)并从新的String(byte [])切换到StandardCharsets.UTF_8作为两种情况下的字符集。 (或任何其他合适的字符集,但UTF-8是当今最常见的选择。)
所以:
byte[] encrypted = cipher.doFinal(
value.getBytes(StandardCharsets.UTF_8));
和
return new String(original,StandardCharsets.UTF_8);
,
粘贴中的引号不是标准的ASCII“,而是其他。
您具有基于字符串的键和iv,并使用UTF-8将其转换为实际的字节数组。这可能是一个错误,您在此处降低了随机性,但不足以太担心。
但是,对于实际的有效负载,您无需执行此操作-那是您应该拥有的。
不是value.getBytes()
,不是value.getBytes(StandardCharsets.UTF-8)
,不是new String(original)
,而是new String(original,StandardCharsets.UTF_8)
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。