简体   繁体   中英

Basic Program for encrypt/Decrypt : javax.crypto.BadPaddingException: Decryption error

I have written a very basic program for Encrypt/Decrypt and trying to encrypt just single string right now. Encryption is working fine but in Decryption it is throwing an error

javax.crypto.BadPaddingException: Decryption error.

It is throwing an error on below line

byte[] decodedData = (rsa.doFinal(decodedValue));

I tried multiple ways and went through lots of threads but not able to find the solution. Can any one please help me with this issue?

The class is simple with 4 methods only, first is test method, next is keystore load method, and rest of two methods are encrypt and decrypt.

package XXXX;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;


public class EncryptDecryptUtil {
    private String publicKeyStoreFileName = "C:\\Program Files\\Java\\jdk1.8.0_51\\jre\\lib\\security\\cacerts";
    private String pubKeyStorePwd = "XXX";
    private String pubKeyAlias="XXXX";
    private static final String JKS = "JKS";
    private static final int CONST_16 = 16;    

    public String TestMethod(final String clearText) throws InvalidKeyException, NoSuchAlgorithmException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, KeyStoreException,
            CertificateException, IOException, UnrecoverableKeyException {    
        byte[] ecryptedAESKey = generateEncryptedData("TEST");
        System.out.println("Encrypted Key = " + ecryptedAESKey);
        System.out.println("Decrypted Key = " + generateDecryptedData(ecryptedAESKey));
        return generateDecryptedData(ecryptedAESKey);
    }

    private KeyStore loadKeyStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
            IOException {
        KeyStore keystore = KeyStore.getInstance(JKS);
        FileInputStream tmp = new FileInputStream(publicKeyStoreFileName);
        keystore.load(tmp, pubKeyStorePwd.toCharArray());
        tmp.close();
        return keystore;
    } 

    private byte[] generateEncryptedData(final String data) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {
            Base64 base64 = new Base64();
            X509Certificate cert;
            KeyStore keystore = loadKeyStore();
            cert = (java.security.cert.X509Certificate) keystore.getCertificate(pubKeyAlias);
            Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            rsa.init(Cipher.ENCRYPT_MODE, cert);

            byte[] ecrypteddata = (base64.encode(rsa.doFinal(data.getBytes(StandardCharsets.UTF_8))));
            return ecrypteddata;
    }

    public String generateDecryptedData(final byte[] encryptedData) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {
            Base64 base64 = new Base64();
            X509Certificate cert;
            KeyStore keystore = loadKeyStore();
            cert = (java.security.cert.X509Certificate) keystore.getCertificate(pubKeyAlias);
            Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            rsa.init(Cipher.DECRYPT_MODE, cert);
            byte[] decodedValue = base64.decode(encryptedData);
            byte[] decodedData = (rsa.doFinal(decodedValue));
            return new String(decodedData);
    }    
}

The Java API makes a difference between certificates and (RSA) private keys. A private key, although associated with a certificate, is not part of a certificate. Java (fortunately) differs with Microsoft's .NET API in this respect, the .NET API is full of such bad design choices.

When you're trying:

rsa.init(Cipher.DECRYPT_MODE, cert);

you should expect an error. The problem is however that this construct is sometimes used to raw "decrypt" RSA based signatures with a public key. So although you should always decrypt with a private key, decrypting with a public key is not explicitly disallowed (for the Sun providers).

So instead try and use KeyStore#getKey or (more modern but more convoluted) KeyStore#getEntry to retrieve the private key. That is: if you do indeed have a private key in the keystore and the password to retrieve it.

Below is the final working code:

import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Created by Suchit Pandya on 9/16/2016.
 */
public class EncryptLogic2 {

    private String publicKeyStoreFileName = "C:\\Program Files\\Java\\jdk1.8.0_51\\jre\\lib\\security\\cacerts";
    private String pubKeyStorePwd = "password";
    private String pubKeyAlias="certName";
    private static final String JKS = "JKS";
    private static final String SHA1PRNG = "SHA1PRNG";
    private static final String RSA = "RSA/ECB/PKCS1Padding";
    private static final int CONST_16 = 16;
    private static byte[] asKey;


    public String TestMethod(final String clearText) throws InvalidKeyException, NoSuchAlgorithmException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, KeyStoreException,
            CertificateException, IOException, UnrecoverableKeyException {

        String ecryptedData = generateEncryptedData(clearText);
        String decryptedData = generateDecryptedData(ecryptedData);
        System.out.println("*********** Decrypted Data = " + decryptedData);
        return decryptedData;
    }

    private KeyStore loadKeyStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
            IOException {
        KeyStore keystore = KeyStore.getInstance(JKS);
        FileInputStream tmp = new FileInputStream(publicKeyStoreFileName);
        keystore.load(tmp, pubKeyStorePwd.toCharArray());
        tmp.close();
        return keystore;
    }

    private String generateEncryptedData(final String data) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {
        Base64 base64 = new Base64();
        X509Certificate cert;
        KeyStore keystore = loadKeyStore();
        cert = (java.security.cert.X509Certificate) keystore.getCertificate(pubKeyAlias);
        Cipher rsa = Cipher.getInstance(RSA);
        Key key = cert.getPublicKey();
        rsa.init(Cipher.ENCRYPT_MODE, key);

        byte[] ecrypteddata = rsa.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.encodeBase64String(ecrypteddata);
    }

    public String generateDecryptedData(final String encryptedData) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
            KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {
        Base64 base64 = new Base64();
        X509Certificate cert;
        KeyStore keystore = loadKeyStore();
        Cipher rsa = Cipher.getInstance(RSA);
        Key key = keystore.getKey(pubKeyAlias, pubKeyStorePwd.toCharArray());
        rsa.init(Cipher.DECRYPT_MODE, key);
        byte[] decodedValue = base64.decode(encryptedData);
        byte[] decodedData = (rsa.doFinal(decodedValue));
        return new String(decodedData, StandardCharsets.UTF_8);
    }
}

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