Java - 为什么我的 AES 程序不是 encrypting/decrypting 双引号?
Java - Why is my AES program not encrypting/decrypting double quotes?
我正在使用 Java 的加密库实现一个简单的 AES-128 加密程序。
不幸的是,这并不是一直都有效。有时会出现明文String中的双引号(")加密后解密,在解密后的字符串中显示为�
据我了解,这个字符是�(�),是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;
}
以下是一些示例案例:
案例一:错误导致
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() 和 new String(byte[]) 的往返过程中。您的“案例 1:导致错误”涉及 non-ASCII 大引号(而您的“案例 2:无问题”使用常规 ASCII 引号),因此显然 String.getBytes() 和 new String(byte[])您的系统不能很好地处理该字符。 (这些方法被记录为使用“平台的默认字符集”,显然您平台的默认字符集不支持该字符。)
要解决此问题,我认为您需要做的就是在两种情况下将字符集从 String.getBytes() 切换为 String.getBytes(Charset) and from new String(byte[]) to new String(byte[], Charset), using StandardCharsets.UTF_8。 (或任何其他合适的字符集,但 UTF-8 是当今最常见的选择。)
所以:
byte[] encrypted = cipher.doFinal(
value.getBytes(StandardCharsets.UTF_8));
和
return new String(original, StandardCharsets.UTF_8);
您粘贴中的引号不是标准的 ASCII ",而是其他内容。
您有 string-based 键和 ivs,并使用 UTF-8 将它们转换为实际的字节数组。这可能是一个错误,你在那里降低了一点随机性,但还不足以让你太担心。
但是,对于实际有效载荷,您不需要这样做 - 而那是您应该这样做的地方。
不是value.getBytes()
,是value.getBytes(StandardCharsets.UTF-8)
,也不是new String(original)
,而是new String(original, StandardCharsets.UTF_8)
。
我正在使用 Java 的加密库实现一个简单的 AES-128 加密程序。
不幸的是,这并不是一直都有效。有时会出现明文String中的双引号(")加密后解密,在解密后的字符串中显示为�
据我了解,这个字符是�(�),是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;
}
以下是一些示例案例:
案例一:错误导致
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() 和 new String(byte[]) 的往返过程中。您的“案例 1:导致错误”涉及 non-ASCII 大引号(而您的“案例 2:无问题”使用常规 ASCII 引号),因此显然 String.getBytes() 和 new String(byte[])您的系统不能很好地处理该字符。 (这些方法被记录为使用“平台的默认字符集”,显然您平台的默认字符集不支持该字符。)
要解决此问题,我认为您需要做的就是在两种情况下将字符集从 String.getBytes() 切换为 String.getBytes(Charset) and from new String(byte[]) to new String(byte[], Charset), using StandardCharsets.UTF_8。 (或任何其他合适的字符集,但 UTF-8 是当今最常见的选择。)
所以:
byte[] encrypted = cipher.doFinal(
value.getBytes(StandardCharsets.UTF_8));
和
return new String(original, StandardCharsets.UTF_8);
您粘贴中的引号不是标准的 ASCII ",而是其他内容。
您有 string-based 键和 ivs,并使用 UTF-8 将它们转换为实际的字节数组。这可能是一个错误,你在那里降低了一点随机性,但还不足以让你太担心。
但是,对于实际有效载荷,您不需要这样做 - 而那是您应该这样做的地方。
不是value.getBytes()
,是value.getBytes(StandardCharsets.UTF-8)
,也不是new String(original)
,而是new String(original, StandardCharsets.UTF_8)
。