title: InvalidKeyException : Illegal Key Size - Java code throwing exception for encryption class - how to fix?
body: <p>I've been trying to get some working Java code to use for encrypting Paypal buttons. This is no easy task! Even when I get some code, from Paypal, I'm faced with errors..ugh..</p>
  
  <p>So here is what I have so far, that I think will work eventually.</p>
  
  <p>I downloaded the Java.zip file from Paypal's website. Within it are two classes - ClientSide.java and ButtonEncryption.java</p>
  
  <p><strong>The Problem -</strong> I'm getting an <code>InvalidKeyException : Illegal key size</code> error.</p>
  
  <p><strong>Questions</strong><br/>
  1) How do I resolve this issue? 2) What line of code is throwing the error?</p>
  
  <pre><code>C:\jakarta-tomcat\webapps\PlanB\WEB-INF\classes&gt;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)
  </code></pre>
  
  <p><br/></p>
  
  <h1>ClientSide class</h1>
  
  <pre><code>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 &lt; 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();
      }
  
  }
  </code></pre>
  
  <p><br/></p>
  
  <h1>ButtonEncryption class</h1>
  
  <pre><code>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\nbusiness=buyer@hotmail.com\nitem_name=vase\nitemprice=25.00";  //cmd=_xclick,business=sample@paypal.com,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 &amp;&amp; result != "")
              {
                  try {        
                      OutputStream fout= new FileOutputStream( output );
                      OutputStream bout= new BufferedOutputStream(fout);
                      OutputStreamWriter out = new OutputStreamWriter(bout, "US-ASCII");
  
                      out.write( "&lt;form action=\"https://www." );
                      out.write( stage );
                      out.write( "paypal.com/cgi-bin/webscr\" method=\"post\"&gt;" );  
                      out.write( "&lt;input type=\"hidden\" name=\"cmd\" value=\"_s-xclick\"&gt;" );  ;
                      out.write( "&lt;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!\"&gt;" );
                      out.write( "&lt;input type=\"hidden\" name=\"encrypted\" value=\"" );
                      out.write( result );
                      out.write( "\"&gt;" );
                      out.write( "&lt;/form&gt;");
  
                      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();
          }
      }
  }
  </code></pre>
  
  <p><br/></p>
  
  <h1>Edited : info about keys/certificates</h1>
  
  <p>I generated the Private Key and Public Certificate with OpenSSL via the following commands.
  <br/>
  <strong>Private Key</strong><br/>
  openssl genrsa -out private-key.pem 1024
  <br/>
  <strong>Public Certificate</strong>
  <br/>openssl req -new -key private-key.pem -x509 -days 1095 -out public-cert.pem
  <br/>
  <strong>Created PKCS12 File</strong><br/>
  openssl pkcs12 -export -in public-cert.pem -inkey private-key.pem -out my_pkcs12.p12</p>
  
  <p><br/>
  Additionally, I had to download the Paypal Public Certificate from the Paypal website.</p>
  
  <p><br/></p>
  
  <h1>Edited - adding compilation warnings - BouncyCastle</h1>
  
  <pre><code>C:\jakarta-tomcat\webapps\PlanB\WEB-INF\classes&gt;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
  </code></pre>
  
  <p><br/></p>
  
  <h1>JCE policy file installation steps</h1>
  
  <p>These are the steps I took to installing the JCE Unlimited Strength Policy files:<br/>
  1) Went to <a href="https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jce_policy-6-oth-JPR@CDS-CDS_Developer" rel="noreferrer">Java JCE Download</a> Page on Oracle.<br/>
  2) Extracted files from zip.<br/>
  3) Placed local_policy.jar and US_export_policy.jar files in C:\Java\jdk1.6.0_22\jre\lib\security folder. <br/>
  Note: C:\Java\jdk1.6.0_22 is set as %JAVA_HOME% 
  <br/>
  4) Updated system classpath to include location of jars.
  <br/>
  Note: There are other files, that came with the JDK 1.6 within the security folder, including : java.policy, java.security, javaws.policy, trusted.libraries - but those probably have nothing to do with the JCE files, right?
  <br/></p>
  
  <hr/>
  
  <h1>Edit 6/23/2011 - results after further configuration</h1>
  
  <p>I went to Bouncy Castle page at <a href="http://www.bouncycastle.org/specifications.html#install" rel="noreferrer">http://www.bouncycastle.org/specifications.html#install</a><br/>
  Scroll down to <strong>5.0 Bouncy Castle Provider</strong> then read info under <strong>5.1 Example</strong>. It makes mention of adding a parameter for the Bouncy Castle Provider to the <code>java.security</code> file. My file is under C:\Java\jdk1.6.0_22\jre\lib\security.<br/><br/>
  I added the following line to my file - <code>security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider</code> <br/></p>
  
  <p>In addition, I discovered that I hadn't added the Bouncy Castle jars to the classpath, so I went ahead and did so.
  <br/></p>
  
  <p>Now after making these changes, recompiling and attempting to execute <code>ClientSide.java</code> I'm given the same exception : but maybe the focus should be on the part of the exception where it says this about bouncycastle provider -</p>
  
  <pre><code>at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.cryptData(Unknown Source)
  at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.engineLoad(Unknown Source)
  </code></pre>
  
  <p><strong>@PeteyB - I'm certain that I installed the policy files correctly. Based on what I've stated here, is there anything else you can suggest I try? Can you look at the Bouncy Castle site @ <a href="http://www.bouncycastle.org/specifications.html#install" rel="noreferrer">http://www.bouncycastle.org/specifications.html#install</a> and see if there is something I'm missing?</strong></p>