简体   繁体   English

javax.crypto.BadPaddingException:填充块有时损坏

[英]javax.crypto.BadPaddingException: pad block corrupted sometimes

I have the following code for encrypt我有以下加密代码

public static String encrypt(String value, char[] secret) {
        try {
            final byte[] bytes = value != null ? value.getBytes(StandardCharsets.UTF_8) : new byte[0];
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey key = keyFactory.generateSecret(new PBEKeySpec(secret));
            Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
            pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(IsoGame.$().crossPlatformManager.getCrossPlatformUtilsInstance().getDeviceUniqueIdentifier().getBytes(StandardCharsets.UTF_8), 20));
            return new String(Base64.encodeBase64(pbeCipher.doFinal(bytes)), StandardCharsets.UTF_8);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;

    }

and the following code for decrypt.以及以下用于解密的代码。

public static String decrypt(String value, char[] secret) {
        try {
            final byte[] bytes = value != null ? Base64.decodeBase64(value.getBytes(StandardCharsets.UTF_8)) : new byte[0];
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey key = keyFactory.generateSecret(new PBEKeySpec(secret));
            Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
            pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(IsoGame.$().crossPlatformManager.getCrossPlatformUtilsInstance().getDeviceUniqueIdentifier().getBytes(StandardCharsets.UTF_8), 20));
            return new String(pbeCipher.doFinal(bytes), StandardCharsets.UTF_8);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;

    }

However, sometimes the exception is being thrown at但是,有时会抛出异常

pbeCipher.doFinal(bytes)

in decrypt method.在解密方法中。

The exception is javax.crypto.BadPaddingException: pad block corrupted异常是javax.crypto.BadPaddingException: pad block corrupted

It's strange, as I'm getting this exception sometimes with the same values.这很奇怪,因为我有时会收到具有相同值的异常。

Any ideas?有任何想法吗? Thanks.谢谢。

The most likely reason would simply be the wrong password to be supplied. 最可能的原因只是提供错误的密码。 If the wrong password is supplied then the wrong key is derived. 如果提供了错误的密码,则会导出错误的密钥。 Then the ciphertext will be decrypted to garbage plaintext. 然后密文将被解密为垃圾明文。 This will only be noticed if the padding exception gets thrown: unpadding random bytes is likely to fail. 只有在抛出填充异常时才会注意到这一点:取消填充随机字节可能会失败。

You could eg first validate that the derived key is correct by performing a HMAC over known data using the derived key. 例如,您可以通过使用派生密钥对已知数据执行HMAC来首先验证派生密钥是否正确。 In addition, it would be a good idea to use some kind of authenticated encryption, so that if the key or data is wrong or corrupted that decryption does indeed fail. 此外,使用某种经过身份验证的加密是个好主意,这样如果密钥或数据错误或损坏,解密确实会失败。 If you're unlucky then - at this time - the data will decrypt, unpadding will succeed and you end up with garbage plaintext. 如果你运气不好,那么 - 此时 - 数据将被解密,unpadding将成功,你最终得到垃圾明文。

Of course, you'd better upgrade to PBKDF2 for key derivation, and upgrade AES to eg AES-GCM instead of DES. 当然,您最好升级到PBKDF2以进行密钥派生,并将AES升级到例如AES-GCM而不是DES。 Currently your encryption is entirely insecure, even if you use a strong password. 目前,即使您使用强密码,您的加密也是完全不安全的。

Your problem is 你的问题是

IsoGame.$().crossPlatformManager.getCrossPlatformUtilsInstance().getDeviceUniqueIdentifier().getBytes(StandardCharsets.UTF_8)

I have ran the following code multiple times and no exception occurred and the decrypted data was equal to "Hello there!": 我多次运行以下代码并且没有发生异常,解密数据等于“Hello there!”:

public static void main(String[] args)
    {
        new CryptographyError();
    }

    private CryptographyError()
    {
        char[] secret = "MySecret".toCharArray();
        String mesasge = "Hello there!";
        EncryptedData encryptedData = encrypt(mesasge, secret);
        System.out.println("ENCRYPTED " + encryptedData.encryptedString);
        String decrypted = decrypt(encryptedData, secret);
        System.out.println("DECRYPTED " + decrypted);
    }

    private static final SecureRandom RANDOM = new SecureRandom();

    public static EncryptedData encrypt(String value, char[] secret) {
        try {
            final byte[] bytes = value != null ? value.getBytes(StandardCharsets.UTF_8) : new byte[0];
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey key = keyFactory.generateSecret(new PBEKeySpec(secret));
            Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
            byte[] salt = new byte[8];
            RANDOM.nextBytes(salt);
            pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(salt, 20));
            return new EncryptedData(salt, new String(Base64.getEncoder().encode(pbeCipher.doFinal(bytes)), StandardCharsets.UTF_8));

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(value);
        }
        return null;

    }

    public static String decrypt(EncryptedData encryptedData, char[] secret) {
        try {
            String value = encryptedData.encryptedString;
            byte[] salt = encryptedData.salt;
            final byte[] bytes = value != null ? Base64.getDecoder().decode(value.getBytes(StandardCharsets.UTF_8)) : new byte[0];
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey key = keyFactory.generateSecret(new PBEKeySpec(secret));
            Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
            pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(salt, 20));
            return new String(pbeCipher.doFinal(bytes), StandardCharsets.UTF_8);

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

    }

    private static class EncryptedData
    {
        private final byte[] salt;
        private final String encryptedString;

        private EncryptedData(byte[] salt, String encryptedString)
        {
            this.salt = salt;
            this.encryptedString = encryptedString;
        }
    }

The only main difference between my code and your code is 我的代码和代码之间唯一的主要区别是

IsoGame.$().crossPlatformManager.getCrossPlatformUtilsInstance().getDeviceUniqueIdentifier().getBytes(StandardCharsets.UTF_8)

which means that must not return the same value on encryption and decryption. 这意味着加密和解密时不得返回相同的值。 Also if you want to test this you can just change the salt between them and notice the exception is thrown again. 此外,如果你想测试它,你可以只改变它们之间的盐,并注意再次抛出异常。

Also Maarten Bodewes gave you some good notes about how to improve your code. Maarten Bodewes还为您提供了一些关于如何改进代码的好注意事项。

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

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

相关问题 javax.crypto.BadPaddingException:pad块损坏 - javax.crypto.BadPaddingException: pad block corrupted Android javax.crypto.BadPaddingException:填充块已损坏 - Android javax.crypto.BadPaddingException: pad block corrupted 文件解密失败:javax.crypto.BadPaddingException:填充块已损坏 - Decryption of file fails: javax.crypto.BadPaddingException: pad block corrupted javax.crypto.BadPaddingException:填充块损坏的异常 - javax.crypto.BadPaddingException: pad block corrupted exception 错误:javax.crypto.BadPaddingException:解密时填充块损坏 - Error : javax.crypto.BadPaddingException: pad block corrupted while Decryption Java Blowfish CBC 解密 javax.crypto.BadPaddingException:填充块已损坏 - Java Blowfish CBC Decryption javax.crypto.BadPaddingException: pad block corrupted 函数解密引发javax.crypto.BadPaddingException:android中的类SimpleCrypto中的填充块已损坏 - function decrypt throws javax.crypto.BadPaddingException: pad block corrupted in class SimpleCrypto in android 解密图像时,给出javax.crypto.BadPaddingException:填充块损坏的Android - When Decrypting Image, gives javax.crypto.BadPaddingException: pad block corrupted Android AES128解密:javax.crypto.badpaddingexception pad块损坏 - AES128 Decryption :javax.crypto.badpaddingexception pad block corrupted javax.crypto.BadPaddingException:未知的块类型 - javax.crypto.BadPaddingException: unknown block type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM