web-dev-qa-db-fra.com

InvalidKeyException: taille de clé illégale - Exception de levée de code Java pour la classe de chiffrement - comment y remédier

J'ai essayé d'obtenir du code Java fonctionnel pour chiffrer les boutons Paypal. Ce n'est pas une tache facile! Même quand je reçois du code, de Paypal, je suis confronté à des erreurs .. euh ..

Voici donc ce que j’ai eu jusqu’à présent, qui, je pense, fonctionnera éventuellement.

J'ai téléchargé le fichier Java.Zip à partir du site Web de Paypal. Il contient deux classes: ClientSide.Java et ButtonEncryption.Java.

Le problème - Je reçois une erreur InvalidKeyException : Illegal key size.

Des questions
1) Comment résoudre ce problème? 2) Quelle ligne de code génère l'erreur?

C:\jakarta-Tomcat\webapps\PlanB\WEB-INF\classes>Java palmb.servlets.Paypal.ButtonEncryption
Java.io.IOException: exception decrypting data - Java.security.InvalidKeyException: Illegal key size
        at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.cryptData(Unknown Source)
        at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.engineLoad(Unknown Source)
        at Java.security.KeyStore.load(Unknown Source)
        at palmb.servlets.Paypal.ClientSide.getButtonEncryptionValue(ClientSide.Java:63)
        at palmb.servlets.Paypal.ButtonEncryption.main(ButtonEncryption.Java:81)


Classe ClientSide

package palmb.servlets.Paypal;

import Java.io.ByteArrayOutputStream;
import Java.io.FileInputStream;
import Java.io.IOException;
import Java.io.PrintWriter;
import Java.security.InvalidAlgorithmParameterException;
import Java.security.KeyStore;
import Java.security.KeyStoreException;
import Java.security.NoSuchAlgorithmException;
import Java.security.NoSuchProviderException;
import Java.security.PrivateKey;
import Java.security.UnrecoverableKeyException;
import Java.security.cert.CertStore;
import Java.security.cert.CertStoreException;
import Java.security.cert.CertificateException;
import Java.security.cert.CertificateFactory;
import Java.security.cert.CollectionCertStoreParameters;
import Java.security.cert.X509Certificate;
import Java.util.ArrayList;
import Java.util.Enumeration;

import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.util.encoders.Base64;

/**
 */
public class ClientSide 
{
    private String  keyPath;
    private String  certPath;
    private String  paypalCertPath;
    private String  keyPass;

    public ClientSide( String keyPath, String certPath, String paypalCertPath, String keyPass )
    {
        this.keyPath = keyPath;
        this.certPath = certPath;
        this.paypalCertPath = paypalCertPath;
        this.keyPass = keyPass;
    }   

    public String getButtonEncryptionValue(String _data, String _privateKeyPath, String _certPath, String _payPalCertPath,
                                            String _keyPass) throws IOException,CertificateException,KeyStoreException,
                                            UnrecoverableKeyException,InvalidAlgorithmParameterException,NoSuchAlgorithmException,
                                            NoSuchProviderException,CertStoreException,CMSException {
        _data = _data.replace(',', '\n');
        CertificateFactory cf = CertificateFactory.getInstance("X509", "BC");

        // Read the Private Key
        KeyStore ks = KeyStore.getInstance("PKCS12", "BC");
        ks.load( new FileInputStream(_privateKeyPath), _keyPass.toCharArray() );

        String keyAlias = null;
        Enumeration aliases = ks.aliases();
        while (aliases.hasMoreElements()) {
            keyAlias = (String) aliases.nextElement();
        }

        PrivateKey privateKey = (PrivateKey) ks.getKey( keyAlias, _keyPass.toCharArray() );

        // Read the Certificate
        X509Certificate certificate = (X509Certificate) cf.generateCertificate( new FileInputStream(_certPath) );

        // Read the Paypal Cert
        X509Certificate payPalCert = (X509Certificate) cf.generateCertificate( new FileInputStream(_payPalCertPath) );

        // Create the Data
        byte[] data = _data.getBytes();

        // Sign the Data with my signing only key pair
        CMSSignedDataGenerator signedGenerator = new CMSSignedDataGenerator();

        signedGenerator.addSigner( privateKey, certificate, CMSSignedDataGenerator.DIGEST_SHA1 );

        ArrayList certList = new ArrayList();
        certList.add(certificate);
        CertStore certStore = CertStore.getInstance( "Collection", new CollectionCertStoreParameters(certList) );
        signedGenerator.addCertificatesAndCRLs(certStore);

        CMSProcessableByteArray cmsByteArray = new CMSProcessableByteArray(data);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        cmsByteArray.write(baos);
        System.out.println( "CMSProcessableByteArray contains [" + baos.toString() + "]" );

        CMSSignedData signedData = signedGenerator.generate(cmsByteArray, true, "BC");

        byte[] signed = signedData.getEncoded();

        CMSEnvelopedDataGenerator envGenerator = new CMSEnvelopedDataGenerator();
        envGenerator.addKeyTransRecipient(payPalCert);
        CMSEnvelopedData envData = envGenerator.generate( new CMSProcessableByteArray(signed),
                CMSEnvelopedDataGenerator.DES_EDE3_CBC, "BC" );

        byte[] pkcs7Bytes = envData.getEncoded();


        return new String( DERtoPEM(pkcs7Bytes, "PKCS7") );

    }

    public static byte[] DERtoPEM(byte[] bytes, String headfoot) 
    {
        ByteArrayOutputStream pemStream = new ByteArrayOutputStream();
        PrintWriter writer = new PrintWriter(pemStream);

        byte[] stringBytes = Base64.encode(bytes);

        System.out.println("Converting " + stringBytes.length + " bytes");

        String encoded = new String(stringBytes);

        if (headfoot != null) {
            writer.print("-----BEGIN " + headfoot + "-----\n");
        }

        // write 64 chars per line till done
        int i = 0;
        while ((i + 1) * 64 < encoded.length()) {
            writer.print(encoded.substring(i * 64, (i + 1) * 64));
            writer.print("\n");
            i++;
        }
        if (encoded.length() % 64 != 0) {
            writer.print(encoded.substring(i * 64)); // write remainder
            writer.print("\n");
        }
        if (headfoot != null) {
            writer.print("-----END " + headfoot + "-----\n");
        }
        writer.flush();
        return pemStream.toByteArray();
    }

}


Classe ButtonEncryption

package palmb.servlets.Paypal;

//import com.Paypal.crypto.sample.*;

import palmb.servlets.Paypal.ClientSide;

import Java.io.*;
import Java.security.InvalidAlgorithmParameterException;
import Java.security.KeyStoreException;
import Java.security.NoSuchAlgorithmException;
import Java.security.NoSuchProviderException;
import Java.security.Security;
import Java.security.UnrecoverableKeyException;
import Java.security.cert.CertStoreException;
import Java.security.cert.CertificateException;
import org.bouncycastle.cms.CMSException;

/**
 */
public class ButtonEncryption {


    //path to public cert
    private static String certPath = "C:/jakarta-Tomcat/webapps/PlanB/Certs/public-cert.pem";

    //path to private key in PKCS12 format
    private static String keyPath = "C:/jakarta-Tomcat/webapps/PlanB/Certs/my_pkcs12.p12";

    //path to Paypal's public cert
    private static String paypalCertPath = "C:/jakarta-Tomcat/webapps/PlanB/Certs/Paypal_cert_pem.txt";

    //private key password
    private static String keyPass = "password"; //will be replaced with actual password when compiled and executed

    //the button command, properties/parameters
    private static String cmdText = "cmd=_xclick\[email protected]\nitem_name=vase\nitemprice=25.00";  //cmd=_xclick,[email protected],amount=1.00,currency_code=USD

    //output file for form code
    private static String output = "test.html";


    public static void main(String[] args) 
    {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 


        String stage = "sandbox";

        try 
        {
            ClientSide client_side = new ClientSide( keyPath, certPath, paypalCertPath, keyPass );

            String result = client_side.getButtonEncryptionValue( cmdText, keyPath, certPath, paypalCertPath, keyPass );

            File outputFile = new File( output );
            if ( outputFile.exists() )
                outputFile.delete();

            if ( result != null && result != "")
            {
                try {        
                    OutputStream fout= new FileOutputStream( output );
                    OutputStream bout= new BufferedOutputStream(fout);
                    OutputStreamWriter out = new OutputStreamWriter(bout, "US-ASCII");

                    out.write( "<form action=\"https://www." );
                    out.write( stage );
                    out.write( "Paypal.com/cgi-bin/webscr\" method=\"post\">" );  
                    out.write( "<input type=\"hidden\" name=\"cmd\" value=\"_s-xclick\">" );  ;
                    out.write( "<input type=\"image\" src=\"https://www." );
                    out.write( stage );
                    out.write( "Paypal.com/en_US/i/btn/x-click-but23.gif\" border=\"0\" name=\"submit\" " );
                    out.write( "alt=\"Make payments with Paypal - it's fast, free and secure!\">" );
                    out.write( "<input type=\"hidden\" name=\"encrypted\" value=\"" );
                    out.write( result );
                    out.write( "\">" );
                    out.write( "</form>");

                    out.flush();  // Don't forget to flush!
                    out.close();
                  }
                  catch (UnsupportedEncodingException e) {
                    System.out.println(
                     "This VM does not support the ASCII character set."
                    );
                  }
                  catch (IOException e) {
                    System.out.println(e.getMessage());        
                  }
            }
        } 
        catch (NoSuchAlgorithmException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (NoSuchProviderException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (IOException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (CMSException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (CertificateException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (KeyStoreException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (UnrecoverableKeyException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (InvalidAlgorithmParameterException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (CertStoreException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}


Édité: informations sur les clés/certificats

J'ai généré la clé privée et le certificat public avec OpenSSL via les commandes suivantes .
Clé privée
openssl genrsa -out clé privée.pem 1024
Certificat public
openssl req -new -key clé-privée.pem -x509 -days 1095 -out public-cert.pem
Fichier PKCS12 créé
openssl pkcs12 -export -in public-cert.pem -inkey clé-privée.pem -out mon_pkcs12.p12


De plus, je devais télécharger le certificat public Paypal depuis le site Web de Paypal.


Edited - ajout de mises en garde de compilation - BouncyCastle

C:\jakarta-Tomcat\webapps\PlanB\WEB-INF\classes>javac .\palmb\servlets\Paypal\ClientSide.Java -Xlint
.\palmb\servlets\Paypal\ClientSide.Java:85: warning: [deprecation] addSigner(Java.security.PrivateKey,Java.security.cert.X509Certificate,Java.lang.String) in org.bouncycastle.cms.CMSSignedDataGenerator has been deprecated
                signedGenerator.addSigner( privateKey, certificate, CMSSignedDat
aGenerator.DIGEST_SHA1 );
                               ^
.\palmb\servlets\Paypal\ClientSide.Java:88: warning: [unchecked] unchecked call
to add(E) as a member of the raw type Java.util.ArrayList
                certList.add(certificate);
                            ^
.\palmb\servlets\Paypal\ClientSide.Java:90: warning: [deprecation] addCertificatesAndCRLs(Java.security.cert.CertStore) in org.bouncycastle.cms.CMSSignedGenerat
or has been deprecated
                signedGenerator.addCertificatesAndCRLs(certStore);
                               ^
.\palmb\servlets\Paypal\ClientSide.Java:97: warning: [deprecation] generate(org.
bouncycastle.cms.CMSProcessable,boolean,Java.lang.String) in org.bouncycastle.cm
s.CMSSignedDataGenerator has been deprecated
                CMSSignedData signedData = signedGenerator.generate(cmsByteArray, true, "BC");
                                                          ^
.\palmb\servlets\Paypal\ClientSide.Java:102: warning: [deprecation] addKeyTransR
ecipient(Java.security.cert.X509Certificate) in org.bouncycastle.cms.CMSEnvelope
dGenerator has been deprecated
                envGenerator.addKeyTransRecipient(payPalCert);
                            ^
.\palmb\servlets\Paypal\ClientSide.Java:103: warning: [deprecation] generate(org.bouncycastle.cms.CMSProcessable,Java.lang.String,Java.lang.String) in org.bouncycastle.cms.CMSEnvelopedDataGenerator has been deprecated
                CMSEnvelopedData envData = envGenerator.generate( new CMSProcess
ableByteArray(signed),
                                                       ^
6 warnings


Étapes d'installation du fichier de règles JCE

Voici les étapes que j'ai suivies pour installer les fichiers de stratégie JCE Unlimited Strength:
1) Nous sommes allés à Téléchargement de JCE Java Page sur Oracle.
2) Fichiers extraits de Zip.
3) Placé les fichiers local_policy.jar et US_export_policy.jar dans le dossier C:\Java\jdk1.6.0_22\jre\lib\security. 
Remarque: C:\Java\jdk1.6.0_22 est défini sur% Java_HOME%
4) Chemin de classe système mis à jour pour inclure l’emplacement des bocaux .
Remarque: le dossier de sécurité contient d’autres fichiers fournis avec JDK 1.6, notamment: Java.policy, Java.security, javaws.policy, Trusted.libraries - mais ils n’ont probablement rien à voir avec les fichiers JCE. , droite?


Edit 23/06/2011 - résultats après une configuration supplémentaire

Je suis allé à la page du château de Bouncy à l'adresse _ { http://www.bouncycastle.org/specifications.html#install } _
Faites défiler la liste jusqu’à 5.0 Bouncy Castle Provider puis lisez les informations sous 5.1 Exemple. Il mentionne l'ajout d'un paramètre pour le fournisseur du château gonflable au fichier Java.security. Mon fichier est sous C:\Java\jdk1.6.0_22\jre\lib\security.

J'ai ajouté la ligne suivante à mon fichier - security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider 

De plus, j'ai découvert que je n'avais pas ajouté les jarres Bouncy Castle au parcours de la classe, alors je suis allé de l'avant et je l'ai fait .

Maintenant, après avoir apporté ces modifications, recompilé et tenté d’exécuter ClientSide.Java, on me donne la même exception: mais peut-être que l’accent devrait être mis sur la partie de l’exception où il est dit ceci sur le fournisseur de Bouncycastle -

at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.cryptData(Unknown Source)
at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.engineLoad(Unknown Source)

@PeteyB - Je suis certain d'avoir correctement installé les fichiers de règles. D'après ce que j'ai dit ici, pouvez-vous suggérer autre chose d'essayer? Pouvez-vous consulter le site du château gonflable @ _ { http://www.bouncycastle.org/specifications.html#install et voir s’il manque quelque chose?

36
katura

Le problème doit donc venir de votre installation JCE Unlimited Strength. 

Assurez-vous d’écraser les local_policy.jar et US_export_policy.jar à la fois dans le jdk1.6.0_25\jre\lib\security\ de votre JDK et dans le dossier lib\security\ de votre JRE.

Dans mon cas, je placerais les nouveaux .jars dans:

C:\Program Files\Java\jdk1.6.0_25\jre\lib\security

et

C:\Program Files\Java\jre6\lib\security


Si vous exécutez Java 8 et que vous rencontrez ce problème. Les étapes ci-dessous devraient aider!

Accédez à votre installation JRE (par exemple - jre1.8.0_181\lib\security\policy\unlimited), copiez local_policy.jar et remplacez-la par «local_policy.jar» dans votre répertoire d'installation JDK (par exemple, jdk1.8.0_141\jre\lib\security). 

73
Petey B

Si vous recevez toujours l'InvalidKeyException lors de l'exécution de mon programme de chiffrement AES avec des clés de 256 bits, mais pas avec des clés de 128 bits, c'est parce que vous n'avez pas installé correctement les nouveaux fichiers JAR de règles et qu'il n'a rien à voir avec BouncyCastle (qui est également restreint par ces fichiers de politique). Essayez de désinstaller, puis de réinstaller Java, puis de remplacer les anciens fichiers jar par les nouveaux. Sinon, je suis à court d'idées et je souhaite la meilleure des chances.

Vous pouvez voir les fichiers de règles eux-mêmes si vous ouvrez les fichiers lib/security/local_policy.jar et US_export_policy.jar dans winzip et regardez les fichiers * .policy dans le bloc-notes et assurez-vous qu'ils ressemblent à ceci:

default_local.policy:

    // Country-specific policy file for countries with no limits on crypto strength.
grant {
    // There is no restriction to any algorithms.
    permission javax.crypto.CryptoAllPermission; 
};

default_US_export.policy:

// Manufacturing policy file.
grant {
    // There is no restriction to any algorithms.
    permission javax.crypto.CryptoAllPermission; 
};
6
Petey B

Ajoutez le code ci-dessous dans votre code client:

static {
    Security.insertProviderAt(new BouncyCastleProvider(),1);
 }

avec cela, il n'est pas nécessaire d'ajouter une entrée dans le fichier Java.security.

4
Anil Verma

L'erreur semble être générée lorsque vous essayez de charger le fichier de clés à partir de "C: /jakarta-Tomcat/webapps/PlanB/Certs/my_pkcs12.p12" ici:

ks.load( new FileInputStream(_privateKeyPath), _keyPass.toCharArray() ); 

Avez-vous essayé de remplacer "/" par "\\" dans votre chemin de fichier? Si cela ne vous aide pas, cela a probablement un rapport avec les fichiers de stratégie juridictionnelle à puissance illimitée de Java. Vous pouvez vérifier cela en écrivant un petit programme qui effectue le cryptage AES. Essayez de chiffrer avec une clé de 128 bits, puis si cela fonctionne, essayez avec une clé de 256 bits et voyez si elle échoue. 

Code qui encyrpte AES:

import Java.io.UnsupportedEncodingException;
import Java.security.InvalidAlgorithmParameterException;
import Java.security.InvalidKeyException;
import Java.security.NoSuchAlgorithmException;
import Java.security.NoSuchProviderException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Test 
{
    final String ALGORITHM = "AES";                       //symmetric algorithm for data encryption
    final String PADDING_MODE = "/CBC/PKCS5Padding";      //Padding for symmetric algorithm
    final String CHAR_ENCODING = "UTF-8";                 //character encoding
    //final String CRYPTO_PROVIDER = "SunMSCAPI";             //provider for the crypto

    int AES_KEY_SIZE = 256;  //symmetric key size (128, 192, 256) if using 256 you must have the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files  installed

    private String doCrypto(String plainText) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException
    {
        byte[] dataToEncrypt = plainText.getBytes(CHAR_ENCODING);

        //get the symmetric key generator
        KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
        keyGen.init(AES_KEY_SIZE); //set the key size

        //generate the key
        SecretKey skey = keyGen.generateKey();

        //convert to binary
        byte[] rawAesKey = skey.getEncoded();

        //initialize the secret key with the appropriate algorithm
        SecretKeySpec skeySpec = new SecretKeySpec(rawAesKey, ALGORITHM);

        //get an instance of the symmetric cipher
        Cipher aesCipher = Cipher.getInstance(ALGORITHM + PADDING_MODE);

        //set it to encrypt mode, with the generated key
        aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        //get the initialization vector being used (to be returned)
        byte[] aesIV = aesCipher.getIV();

        //encrypt the data
        byte[] encryptedData = aesCipher.doFinal(dataToEncrypt);    

        //initialize the secret key with the appropriate algorithm
        SecretKeySpec skeySpecDec = new SecretKeySpec(rawAesKey, ALGORITHM);

        //get an instance of the symmetric cipher
        Cipher aesCipherDec = Cipher.getInstance(ALGORITHM +PADDING_MODE);

        //set it to decrypt mode with the AES key, and IV
        aesCipherDec.init(Cipher.DECRYPT_MODE, skeySpecDec, new IvParameterSpec(aesIV));

        //decrypt and return the data
        byte[] decryptedData = aesCipherDec.doFinal(encryptedData);

        return new String(decryptedData, CHAR_ENCODING);
    }

    public static void main(String[] args)
    {
        String text = "Lets encrypt me";

        Test test = new Test();

        try {
            System.out.println(test.doCrypto(text));
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Ce code fonctionne-t-il pour toi?

Vous pouvez également essayer de spécifier votre fournisseur de château gonflable dans cette ligne:

Cipher.getInstance(ALGORITHM +PADDING_MODE, "YOUR PROVIDER");

Et voyez si cela pourrait être une erreur associée à un château gonflable.

1
Petey B

J'ai fait face au même problème. J'ai essayé d'ajouter les US_export_policy.jar et local_policy.jar dans le dossier de sécurité Java, mais le problème persistait. Puis ajouté le ci-dessous dans Java_opts à l'intérieur de Tomcat setenv.shfile et cela a fonctionné.

-Djdk.tls.ephemeralDHKeySize=2048

Veuillez vérifier ce lien link pour plus d'informations

0
Divya S