解密错误:Pad块损坏

kan*_*ert 7 java encryption android

我有以下代码.

    byte[] input = etInput.getText().toString().getBytes();
    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
        0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };

    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");

    // encryption pass
    cipher.init(Cipher.ENCRYPT_MODE, key);

    byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
    int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
    ctLength += cipher.doFinal(cipherText, ctLength);

    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] plainText = new byte[cipher.getOutputSize(ctLength)];
    int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0);

    String strLength = new String(cipherText,"US-ASCII");
    byte[] byteCiphterText = strLength.getBytes("US-ASCII");
    Log.e("Decrypt", Integer.toString(byteCiphterText.length));

    etOutput.setText(new String(cipherText,"US-ASCII"));

    cipherText  = etOutput.getText().toString().getBytes("US-ASCII");
    Log.e("Decrypt", Integer.toString(cipherText.length));

    ptLength += cipher.doFinal(plainText, ptLength);
    Log.e("Decrypt", new String(plainText));
    Log.e("Decrypt", Integer.toString(ptLength));
Run Code Online (Sandbox Code Playgroud)

它完美地运作.但是一旦我将它转换为课程.它总是在这一行中遇到错误.

 ptLength += cipher.doFinal(plainText, ptLength);

 Error:Pad block corrupted
Run Code Online (Sandbox Code Playgroud)

我检查过并且两个代码完全一样.即使转换字符串中传递给字节的值也与上面的代码没有什么不同.知道代码有什么问题吗?

public String Encrypt(String strPlainText) throws Exception, NoSuchProviderException,
        NoSuchPaddingException {
    byte[] input = strPlainText.getBytes();
    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
            0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };

    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");

    // encryption pass
    cipher.init(Cipher.ENCRYPT_MODE, key);

    byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
    int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
    ctLength += cipher.doFinal(cipherText, ctLength);

    return new String(cipherText, "US-ASCII");
}

public String Decrypt(String strCipherText) throws Exception,
        NoSuchProviderException, NoSuchPaddingException {
    byte[] cipherText = strCipherText.getBytes("US-ASCII");
    int ctLength = cipherText.length;
    byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
            0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };

    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");

    // decryption pass
    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] plainText = new byte[cipher.getOutputSize(ctLength)];
    int ptLength = cipher.update(cipherText, 0, ctLength, plainText, 0);
    ptLength += cipher.doFinal(plainText, ptLength);

    return new String(plainText);
}
Run Code Online (Sandbox Code Playgroud)

mtr*_*aut 5

正如Yann Ramin所说,使用String加密/输出失败。这是二进制数据

  • 可以包含0x00
  • 可以包含在使用的编码中未定义或映射到陌生位置的值

如您的第一个示例中那样,使用普通byte []或进行十六进制编码或base64编码的byte []。

// this is a quick example - dont use sun.misc inproduction
//  - go for some open source implementation
String encryptedString = new sun.misc.BASE64Encoder.encodeBuffer(encryptedBytes);
Run Code Online (Sandbox Code Playgroud)

该字符串可以安全地传输并映射回字节。

编辑

解决长度问题的最安全方法可能是始终使用流式实现(IMHO):

static public byte[] decrypt(Cipher cipher, SecretKey key, byte[]... bytes)
        throws GeneralSecurityException, IOException {
    cipher.init(Cipher.DECRYPT_MODE, key);
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    for (int i = 0; i < bytes.length; i++) {
        bos.write(cipher.update(bytes[i]));
    }
    bos.write(cipher.doFinal());
    return bos.toByteArray();
}
Run Code Online (Sandbox Code Playgroud)


Yan*_*min 1

您已指定 PKCS7 填充。当存储在 String 对象中时,您的填充是否被保留?您的字符串对象与密码输出的字节是否 1:1 匹配?一般来说,字符串不适合传递二进制数据,例如密码输出。