Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-为什么我的AES程序不加密/解密双引号?_Java_Encoding_Utf 8_Cryptography_Aes - Fatal编程技术网

Java-为什么我的AES程序不加密/解密双引号?

Java-为什么我的AES程序不加密/解密双引号?,java,encoding,utf-8,cryptography,aes,Java,Encoding,Utf 8,Cryptography,Aes,我正在使用Java的加密库实现一个简单的AES-128加密程序 不幸的是,这并不是一直都很有效。有时,明文字符串中的双引号(“)在加密然后解密时显示为� 在解密的字符串中 据我所知,这个字符是࿽(�),它是UTF-8解码器遇到错误时使用的替换字符 因此,我的问题是,为什么会发生这种错误,为什么只是偶尔发生,以及如何解决它 这是我的加密和解密代码块: public static String encrypt(String value) { try {

我正在使用Java的加密库实现一个简单的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. 

我相信加密内容在这里不相关;相反,问题一定是在String.getBytes()和new String(byte[])的往返过程中。您的“案例1:错误导致”包含非ASCII卷曲引号(而您的“案例2:无问题”使用常规ASCII引号),因此显然是String.getBytes()和new String(byte[])在您的系统上,无法很好地处理该字符(这些方法被记录为使用“平台的默认字符集”,显然您的平台的默认字符集不支持该字符)

要解决这个问题,我认为您需要做的就是从String.getBytes()切换到新字符串(byte[]),并从新字符串(byte[])切换到,在这两种情况下都用作字符集(或任何其他合适的字符集,但UTF-8是当今最常见的选择)

因此:

byte[]encrypted=cipher.doFinal(
value.getBytes(StandardCharsets.UTF_8));

返回新字符串(原始,StandardCharsets.UTF_8);

粘贴中的引号不是标准ASCII”,而是其他内容

您有基于字符串的键和IV,并使用UTF-8将它们转换为实际的字节数组。这可能是一个错误,你减少了一点随机性,但这还不足以让你太担心

然而,对于实际的有效载荷,您不需要这样做,而这正是您应该做的


它不是
value.getBytes()
,而是
value.getBytes(StandardCharsets.UTF-8)
,也不是
new String(original)
,而是
new String(original,StandardCharsets.UTF_8)

我确信加密的东西在这里不相关;相反,问题一定是在
value.getBytes()
新字符串(原始)
的往返过程中。“案例1:错误导致”和“案例2:无问题”之间的区别在于案例1涉及非ASCII卷曲引号。作为更好地理解这个问题的第一步,我建议循环使用
value.tocharray()
并将字符打印为整数(最好是十六进制),然后对
value.getBytes()
执行同样的操作。你完全正确!这两个双引号是不同的。案例1中的UNICODE值为8220,而案例2中的UNICODE值为ASCII 34。我从另一个来源复制了卷曲引用,这就是问题的原因。现在我想我的问题是,我能做些什么来解释这一点呢?有没有办法自动将非ASCII双引号更改为ASCII双引号,并对其他此类字符执行相同操作?