简体   繁体   English

错误:javax.crypto.BadPaddingException:解密时填充块损坏

[英]Error : javax.crypto.BadPaddingException: pad block corrupted while Decryption

I have done Encryption with , 我已经完成了加密,

public static String encrypt(String plainText) {
    try {
        byte[] keyData = secret_key.getBytes();
        SecretKeySpec secretKey = new SecretKeySpec(keyData, "AES/ECB/PKCS7Padding");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        byte[] cipherText = cipher.doFinal(plainText.getBytes("UTF-8"));
        String encryptedString = Base64.encodeToString(cipherText, Base64.NO_WRAP);

        return encryptedString;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

it's working well. 运行良好。

but part of Decryption gives Error like, 但是Decryption一部分给出了错误,例如

W/System.err: javax.crypto.BadPaddingException: pad block corrupted
W/System.err:     at com.android.org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:701)
W/System.err:     at javax.crypto.Cipher.doFinal(Cipher.java:1111)

decrypt Code like, 像这样decrypt代码

public static String decrypt(String encryptedText) {
    try {
        byte[] keyData = secret_key.getBytes();
        SecretKeySpec secretKey = new SecretKeySpec(keyData, "AES/ECB/PKCS7Padding");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        byte[] cipherText = Base64.decode(encryptedText,Base64.NO_WRAP);
        String decryptedString = new String(cipher.doFinal(cipherText),"UTF-8");

        return decryptedString;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

here what is the problem? 这是什么问题? How can i solve this Issue? 我该如何解决这个问题?

It is likely that your secret_key value contains bytes which are not well represented in the ambiguous encoding you're using. 您的secret_key值可能包含在您使用的模棱两可的编码中不能很好表示的字节。 When you call String#getBytes() without specifying an encoding, you get the system default, which can vary. 在不指定编码的情况下调用String#getBytes() ,将获得系统默认值,该默认值可能会有所不同。

You should use hexadecimal encoding whenever you represent your key as a String . 每当将键表示为String时,都应使用十六进制编码。 This will be consistent across serialization/deserialization on every platform. 这将在每个平台上的序列化/反序列化中保持一致。 There are many standard implementations of this encoding/decoding process available (ie org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEFFEDCBA9876543210"); or org.apache.commons.codec.binary.Hex.decodeHex("0123456789ABCDEFFEDCBA9876543210".toCharArray()); which both return the raw byte[] ). 此编码/解码过程有许多标准实现( org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEFFEDCBA9876543210");org.apache.commons.codec.binary.Hex.decodeHex("0123456789ABCDEFFEDCBA9876543210".toCharArray());都返回原始byte[] )。

Some side notes: 一些注意事项:

  1. You are using ECB mode of operation , which is extremely susceptible to frequency analysis for cryptanalysis and is effectively deprecated aside from toy crypto demonstrations. 您正在使用ECB 操作模式 ,该模式极易受到频率分析进行密码分析的影响,除玩具密码演示外,该方法已被弃用 I suggest you use CBC , CTR , or GCM . 建议您使用CBCCTRGCM
  2. You do not provide an initialization vector (IV), so the same message encrypted with the same key will always yield identical cipher text. 您没有提供初始化向量(IV),因此使用相同密钥加密的相同消息将始终产生相同的密文。 Use a unique and non-predictable IV for every encryption operation by generating 16 bytes from SecureRandom and populating it into an IvParameterSpec . 通过从SecureRandom生成16个字节并将其填充到IvParameterSpec对每个加密操作使用唯一且不可预测的IV。 You can prepend the IV bytes to the cipher text and transport/store it in the clear. 您可以将IV字节放在密文之前,并以明文形式传输/存储。
  3. Your cipher text is not authenticated, allowing for malicious users to both manipulate encrypted data and to attempt decryption via padding oracle/CCA attacks. 您的密文未经身份验证,从而使恶意用户既可以操纵加密的数据,也可以通过填充oracle / CCA攻击来尝试解密。 Use an authenticated encryption with associated data (AEAD) mode like GCM , or use an HMAC/SHA-256 message authentication code (MAC) over the cipher text , and verify it using a constant-time equals method before attempting any decryption. 使用关联数据(AEAD)模式的经过身份验证的加密,例如GCM ,或在密文上使用HMAC/SHA-256消息身份验证码(MAC),并在尝试进行任何解密之前,使用恒定时间等于方法对其进行验证。
  4. You do not need to provide the mode of operation or padding scheme when instantiating a key. 实例化密钥时,无需提供操作模式或填充方案。 SecretKey key = new SecretKeySpec(keyData, "AES"); is sufficient. 足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM