有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javajavax。加密。IllegalBlockSizeException:解密加密的AES字符串时最后一个块未完成

我正在尝试解密从后端服务器收到的字符串"~9?8?m???=?T?G",该服务器使用OpenSSL使用AES-256-CBC对字符串进行加密。下面是代码块:

public static String decryptText(String textToDecrypt) {
    try {

        byte[] base64TextToDecrypt = Base64.encodeBase64(textToDecrypt.getBytes("UTF-8"));

        byte[] guid = "fjakdsjkld;asfj".getBytes("UTF-8");

        byte[] iv = new byte[16];
        System.arraycopy(guid, 0, iv, 0, guid.length);
        IvParameterSpec ips = new IvParameterSpec(iv);

        byte[] secret = DECRYPTION_SECRET_HASH.getBytes("UTF-8");
        SecretKeySpec secretKey = new SecretKeySpec(secret, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // decryption pass
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ips);
        byte[] converted = cipher.doFinal(base64TextToDecrypt);
        System.out.println(new String(converted));

    } catch (Exception e) {
        e.printStackTrace();
        Log.e(TAG, "Decipher error for " + textToDecrypt, e);
    }
    return "";
}

不幸的是,当我到达

byte[] converted = cipher.doFinal(base64TextToDecrypt);

语句引发以下异常:

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption

有什么想法吗


共 (3) 个答案

  1. # 1 楼答案

    您应该在方法的开头对字符串进行解码,而不是对特定于平台的字符串表示进行编码

    byte[] base64TextToDecrypt = Base64.decodeBase64(textToDecrypt);
    

    或者更准确地说:

    byte[] bytesToDecrypt = Base64(base64TextToDecrypt);
    

    如果你的变量命名正确

    一般来说,每次(感觉必须)使用String.getBytes(): byte[]方法或String(byte[])构造函数时,都可能是做错了什么。你应该首先考虑你想做什么,如果你需要使用它,就指定一个

    在您的例子中,converted变量中的输出可能是字符编码的。所以你可以使用以下片段:

    String plainText = new String(converted, StandardCharsets.UTF_8);
    System.out.println(plainText);
    

    而不是你现在拥有的

  2. # 2 楼答案

    在加密和解密字符串时,请记住以下几点:

    加密:

    1. 使用toByteArray(Charsets.UTF-8)将字符串转换为字节数组,并始终使用UTF-8指定字符集

    2. 使用密码加密上述字节数组。doFinal(byteArray)

    3. 现在这还不够,需要使用base64对加密的byteArray进行base64编码。编码(encryptedByteArray,Base64.DEFAULT)

    4. 请记住,这再次返回byteArray,如果要转换为字符串,请使用toString(Charsets.UTF-8),最重要的是再次将字符集指定为UTF-8,然后根据需要处理或存储在DB中

    解密:

    一,。获取加密字符串,解密时的第一步是使用base64对加密字符串进行解码。解码(encryptedString.toByteArray(charset.UTF-8),Base64。(默认)

    1. 现在用密码解密解码后的字节数组。dofinal(解码字节数组)

    2. 使用toString(Charsets.UTF-8)将解密后的字节数组转换为字符串。注意:始终指定字符集。这将返回原始字符串

    我知道我没有共享任何代码,但相信我,在加密和解密字符串时,流是重要的部分

  3. # 3 楼答案

    多亏了@owlstead,我找到了解决方案。是我犯了Base64编码一个已经Base64编码的字符串的错误。下面是代码块

    public static String decryptText(String textToDecrypt) {
        try {
            byte[] decodedValue = Base64.decodeBase64(textToDecrypt.getBytes());
    
            byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            IvParameterSpec ips = new IvParameterSpec(iv);
    
            byte[] input = textToDecrypt.getBytes();
    
            Cipher cipher = Cipher.getInstance(ENCRYPTION_METHOD);
    
            // decryption pass
            cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY, ips);
            byte[] plainText = cipher.doFinal(decodedValue);
    
            return new String(plainText);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Decipher error for " + textToDecrypt, e);
        }
    
        return "";
    }
    

    相应的加密是这样的

    public static String encryptText(String textToEncrypt) {
        try {
            byte[] guid = "1234567890123456".getBytes("UTF-8");
    
            byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            IvParameterSpec ips = new IvParameterSpec(iv);
    
            // The secret key from the server needs to be converted to byte array for encryption.
            byte[] secret = ENCRYPTION_SECRET_HASH.getBytes("UTF-8");
    
            // we generate a AES SecretKeySpec object which contains the secret key.
            // SecretKeySpec secretKey = new SecretKeySpec(secret, "AES");
            Cipher cipher = Cipher.getInstance(ENCRYPTION_METHOD);
            cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY, ips);
    
            byte[] cipherText = cipher.doFinal(textToEncrypt.getBytes());
            byte[] base64encodedSecretData = Base64.encodeBase64(cipherText);
            String secretString = new String(base64encodedSecretData);
            return secretString;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Encryption error for " + textToEncrypt, e);
        }
        return "";
    }