简体   繁体   中英

Exception in thread “main” javax.crypto.BadPaddingException: Decryption error in Java

We working on RSA encryption/Decryption in Java.

We are able to perform encryption but getting error for decryption

Below is code snippet we are using

public class RSA_Read_Write_Key {
    
    static String plainText = "This RSA Crypto Java Code";
    
    public static void main(String[] args) throws Exception {
        byte[] cipherTextArray = encrypt(plainText, "D:\\TCE\\public.key");
        String encryptedText = Base64.getEncoder().encodeToString(cipherTextArray);
        System.out.println("Encrypted Text : " + encryptedText);
        String decryptedText = decrypt(cipherTextArray, "D:\\TCE\\private.key");
        System.out.println("DeCrypted Text : " + decryptedText);    
    }

    public static Key readKeyFromFile(String keyFileName) throws IOException {
        Key key = null;
        InputStream inputStream = new FileInputStream(keyFileName);
        ObjectInputStream objectInputStream = new ObjectInputStream(new BufferedInputStream(inputStream));
        try {
            BigInteger modulus = (BigInteger) objectInputStream.readObject();
            BigInteger exponent = (BigInteger) objectInputStream.readObject();
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            if (keyFileName.startsWith("public"))
                key = keyFactory.generatePublic(new RSAPublicKeySpec(modulus, exponent));
            else
                key = keyFactory.generatePrivate(new RSAPrivateKeySpec(modulus, exponent));        
        } 
        catch (Exception e) {
            e.printStackTrace();
        } finally {
            objectInputStream.close();        
        }
        return key;    
    }
    
    public static byte[] encrypt(String plainText, String fileName) throws Exception {
        Key publicKey = readKeyFromFile("D:\\TCE\\public.key");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] cipherText = cipher.doFinal(plainText.getBytes());
        return cipherText;   
    }

    public static String decrypt(byte[] cipherTextArray, String fileName) throws Exception {
        Key privateKey = readKeyFromFile("D:\\TCE\\private.key");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte [] plain = new byte[100];
        byte[] decryptedTextArray = cipher.doFinal(cipherTextArray);
        return new String(decryptedTextArray);    
    } 
}

When we run the code we getting below Error. Can someone help to resolve this?

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:363)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at RSAcrypto.RsaToy.decrypt(RsaToy.java:108)
at RSAcrypto.RsaToy.main(RsaToy.java:34)

I' ve found the following problems:

  • In readKeyFromFile() it is checked whether the passed file path starts with public . If so, the public key is generated. This only works if the path consists only of the file name, which is generally not the case, eg in the current code the path D:\\\\TCE\\\\public.key is used. To solve this problem it would be better to apply new File(keyFileName).getName().startsWith("public") instead of keyFileName.startsWith("public") .

  • The file path fileName passed in encrypt() and decrypt() should be forwarded to readKeyFromFile() . Instead the hard coded path D:\\\\TCE\\\\public.key is passed. This may have been changed for test purposes only.

With these changes, the code works on my machine as long as keys are used in an appropriate format. This is not one of the typical formats like PKCS#8, PKCS#1 or X.508, but the (as BigInteger ) serialized modulus and exponent (public or private depending on the key type), so that both can be read with ObjectInputStream . One way to store a key in this format is to serialize the modulus and exponent (as BigInteger ) with ObjectOutputStream .

Please also note that in some places encoding (eg plainText.getBytes() ) and decoding (eg new String(decryptedTextArray) ) is done without specifying a character set, so that the (environment dependent) default character set is used (which can cause problems if encryption and decryption are performed in different environments).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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