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..
So here is what I have so far, that I think will work eventually.
I downloaded the Java.zip file from Paypal's website. Within it are two classes - ClientSide.java and ButtonEncryption.java
The Problem - I'm getting an InvalidKeyException : Illegal key size
error.
Questions
1) How do I resolve this issue? 2) What line of code is throwing the error?
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)
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(); } }
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 && 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(); } } }
I generated the Private Key and Public Certificate with OpenSSL via the following commands.
Private Key
openssl genrsa -out private-key.pem 1024
Public Certificate
openssl req -new -key private-key.pem -x509 -days 1095 -out public-cert.pem
Created PKCS12 File
openssl pkcs12 -export -in public-cert.pem -inkey private-key.pem -out my_pkcs12.p12
Additionally, I had to download the Paypal Public Certificate from the Paypal website.
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
These are the steps I took to installing the JCE Unlimited Strength Policy files:
1) Went to Java JCE Download Page on Oracle.
2) Extracted files from zip.
3) Placed local_policy.jar and US_export_policy.jar files in C:\Java\jdk1.6.0_22\jre\lib\security folder.
Note: C:\Java\jdk1.6.0_22 is set as %JAVA_HOME%
4) Updated system classpath to include location of jars.
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?
I went to Bouncy Castle page at http://www.bouncycastle.org/specifications.html#install
Scroll down to 5.0 Bouncy Castle Provider then read info under 5.1 Example. It makes mention of adding a parameter for the Bouncy Castle Provider to the java.security
file. My file is under C:\Java\jdk1.6.0_22\jre\lib\security.
I added the following line to my file - security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
In addition, I discovered that I hadn't added the Bouncy Castle jars to the classpath, so I went ahead and did so.
Now after making these changes, recompiling and attempting to execute ClientSide.java
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 -
at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.cryptData(Unknown Source) at org.bouncycastle.jce.provider.JDKPKCS12KeyStore.engineLoad(Unknown Source)
@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 @ http://www.bouncycastle.org/specifications.html#install and see if there is something I'm missing?
How to remove the key size restriction? You can remove the maximum key restriction by replacing the existing JCE jars with unlimited strength policy jars. Then simply restart you java application and the Exception should be gone.
KeyException which in turn is a subclass of java. security. GeneralSecurityException . As the name suggests, InvalidKeyException emerges when there is something wrong with the encryption key you are trying to use in one of your encryption algorithms.
To enable JCE Unlimited, use the crypto. policy Security property introduced in JDK 8u151. DataStax recommends enabling Java Cryptography Extension (JCE) Unlimited to ensure support for all encryption algorithms, especially AES-256 for Kerberos and SSL when using Oracle Java.
So the problem must be with your JCE Unlimited Strength installation.
Be sure you overwrite the local_policy.jar
and US_export_policy.jar
in both your JDK's jdk1.6.0_25\jre\lib\security\
and in your JRE's lib\security\
folder.
In my case I would place the new .jars in:
C:\Program Files\Java\jdk1.6.0_25\jre\lib\security
and
C:\Program Files\Java\jre6\lib\security
If you are running Java 8 and you encounter this issue. Below steps should help!
Go to your JRE installation (e.g - jre1.8.0_181\lib\security\policy\unlimited) copy local_policy.jar and replace it with 'local_policy.jar' in your JDK installation directory (e.g - jdk1.8.0_141\jre\lib\security).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With