Подтвердить что ты не робот

InvalidKeyException: Недопустимый размер ключа - исключение исключения кода Java для класса шифрования - как исправить?

Я пытаюсь получить некоторый рабочий код Java для шифрования кнопок Paypal. Это непростая задача! Даже когда я получаю код, от Paypal, я столкнулся с ошибками......

Итак, вот что у меня есть до сих пор, я думаю, что в конечном итоге это сработает.

Я загрузил файл Java.zip с веб-сайта Paypal. В нем находятся два класса - ClientSide.java и ButtonEncryption.java

Проблема - Я получаю ошибку InvalidKeyException : Illegal key size.

Вопросы
1) Как решить эту проблему? 2) Какая строка кода выдает ошибку?

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)


Класс 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();
    }

}


Класс 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 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 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();
        }
    }
}


Отредактировано: информация о ключах/сертификатах

Я сгенерировал закрытый ключ и открытый сертификат с OpenSSL с помощью следующих команд.
Закрытый ключ
openssl genrsa -out private-key.pem 1024
Открытый сертификат
openssl req -new -key private-key.pem -x509 -days 1095 -out public-cert.pem
Созданный файл PKCS12
openssl pkcs12 -export -in public-cert.pem -inkey private-key.pem -out my_pkcs12.p12


Кроме того, мне пришлось загрузить общедоступный сертификат Paypal с веб-сайта Paypal.


Отредактировано - добавление предупреждений компиляции - 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


Шаги установки файла политики JCE

Это шаги, которые я предпринял для установки файлов политики безопасности без ограничений:
1) Пошел в Java JCE Скачать Страница по Oracle.
2) Извлеченные файлы из zip.
3) Размещены файлы local_policy.jar и US_export_policy.jar в папке C:\Java\jdk1.6.0_22\jre\lib\security.
Примечание: C:\Java\jdk1.6.0_22 устанавливается как% JAVA_HOME%
4) Обновлен путь к системному классу, чтобы включить расположение банок.
Примечание. Существуют другие файлы, которые поставляются вместе с JDK 1.6 в папке безопасности, включая: java.policy, java.security, javaws.policy, trusted.libraries - но они, вероятно, не имеют никакого отношения к файлам JCE, не так ли?


Изменить 6/23/2011 - результаты после дальнейшей настройки

Я отправился на страницу Загадки Загадки в http://www.bouncycastle.org/specifications.html#install
Прокрутите вниз до 5.0 Bouncy Castle Provider, затем прочитайте информацию в 5.1 Пример. Он упоминает о добавлении параметра для Bouncy Castle Provider в файл java.security. Мой файл находится в папке C:\Java\jdk1.6.0_22\jre\lib\security.

Я добавил в файл следующую строку: security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider

Кроме того, я обнаружил, что я не добавил банки Bouncy Castle в путь класса, поэтому я пошел вперед и сделал это.

Теперь, после внесения этих изменений, перекомпиляции и попытки выполнить ClientSide.java, мне предоставляется то же исключение: но, возможно, фокус должен быть со стороны исключения, где он говорит об этом провайдеру bouncycastle -

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

@PeteyB - я уверен, что правильно установил файлы политики. Основываясь на том, что я сказал здесь, есть ли что-нибудь еще, что вы можете предложить мне попробовать? Можете ли вы посмотреть сайт Bouncy Castle @http://www.bouncycastle.org/specifications.html#install и посмотреть, нет ли чего-то, что мне не хватает?

4b9b3361

Ответ 1

Таким образом, проблема должна быть связана с установкой JCE Unlimited Strength.

Обязательно перезапишите local_policy.jar и US_export_policy.jar как в JDK jdk1.6.0_25\jre\lib\security\, так и в вашей JRE lib\security\.

В моем случае я бы разместил новые .jars в:

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

и

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

Ответ 2

Если вы все еще получаете InvalidKeyException при запуске моей программы шифрования AES с 256-битными ключами, но не с 128-битными ключами, это связано с тем, что вы не установили новые JAR файлы политики правильно и не имеете никакого отношения к BouncyCastle ( который также сдерживается этими файлами политики). Попробуйте удалить, а затем снова установить java, а затем заменить старую банку новыми неограниченными прочными. Помимо этого, у меня нет идей, удачи.

Вы можете сами просмотреть файлы политики, если вы открываете файлы lib/security/local_policy.jar и US_export_policy.jar в winzip и смотрите в файлы с кодировкой *.policy в блокноте и убедитесь, что они выглядят следующим образом:

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; 
};

Ответ 3

Добавьте код кода в код клиента:

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

с этим нет необходимости добавлять какую-либо запись в файл java.security.

Ответ 4

Ошибка, кажется, бросается, когда вы пытаетесь загрузить их хранилище ключей из "C:/jakarta-tomcat/webapps/PlanB/Certs/my_pkcs12.p12" здесь:

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

Вы пытались заменить "/" на "\\" в вашем пути к файлу? Если это не поможет, возможно, это связано с файлами политики юрисдикции Java Unlimited Strength. Вы можете проверить это, написав небольшую программу, которая шифрует AES. Попробуйте шифровать с помощью 128-битного ключа, а затем, если это работает, попробуйте с помощью 256-битного ключа и посмотрите, не сработает ли он.

Код, который выполняет AES-encyrption:

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();
        }
    }
}

Этот код работает для вас?

Вы также можете попытаться указать своего активного провайдера замка в этой строке:

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

И посмотрим, может ли это быть ошибка, связанная с надувным замком.

Ответ 5

Я столкнулся с той же проблемой. Сначала пробовал добавлять US_export_policy.jar и local_policy.jar в папку безопасности java, но проблема не устранена. Затем добавлено ниже в java_opts внутри файла tomcat setenv.sh, и оно сработало.

-Djdk.tls.ephemeralDHKeySize=2048

Пожалуйста, проверьте эту ссылку для получения дополнительной информации