Illegal Key Size
About a week ago, I wrote an article on how to encrypt with PHP and decrypt with Java. The funny thing is I got an error when I deployed the Java code into the live server! 😐
As a reminder, this is the code I am talking about:
SecretKeySpec skeySpec = new SecretKeySpec("SECRET KEY".getBytes(), "AES"); IvParameterSpec initalVector = new IvParameterSpec("iv_example".getBytes()); Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, initalVector);
This code was working perfectly fine on my local machine but here is the exception I got when I ran it on a Linux server:
java.security.InvalidKeyException: Illegal key size at javax.crypto.Cipher.a(DashoA12275) at javax.crypto.Cipher.a(DashoA12275) at javax.crypto.Cipher.a(DashoA12275) at javax.crypto.Cipher.init(DashoA12275) at javax.crypto.Cipher.init(DashoA12275) ...
Looking on internet for an explanation, I found the following answer on Charitha Kankanamge’s blog (which I slightly updated):
“java.security.InvalidKeyException: Illegal key size” error is a common issue which occurs when you try to invoke a secured web service in an environment where the provision for java unlimited security jurisdiction is not done.
This can be avoided by installing Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files.
1. Go to http://www.oracle.com/technetwork/java/javase/downloads/index.html
2. Go to the Additional Resources section and click on the download button next to “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files X”
3. Download jce_policy-X.zip and extract it into a directory
4. You will find local_policy.jar and US_export_policy.jar files there in the extracted directory. Copy these two files to $JAVA_HOME/jre/lib/security directory (These files might already be there, replace them in this case)
5. Restart the web server and invoke your secured service again. You will not encounter the “invalidkeyException” any more
Please click on the link below to see the original article:
http://charithaka.blogspot.com/2008/08/how-to-avoid-javasecurityinvalidkeyexce.html
Encrypt with PHP – Decrypt with Java
For security reason, I wanted to encrypt the data transferred between PHP web services and a Java application. But the problem was to encrypt the data with PHP in a way that it is possible to decrypt it using Java.
It obviously exists a lot of ways of doing this. But here is the way I choose:
- Use a secret key and an initialisation vector for the encryption and decryption
- Use the mcrypt PHP module for the encryption
- Use the javax.crypto Java package for the decryption
Please find below the PHP code for the encryption:
function encrypt($message, $initialVector, $secretKey) { return base64_encode( mcrypt_encrypt( MCRYPT_RIJNDAEL_128, md5($secretKey), $message, MCRYPT_MODE_CFB, $initialVector ) ); }
And please see below the Java code for the decryption:
public static String md5(String input) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] messageDigest = md.digest(input.getBytes()); BigInteger number = new BigInteger(1, messageDigest); return number.toString(16); } public String decrypt(String encryptedData, String initialVectorString, String secretKey) { String decryptedData = null; try { SecretKeySpec skeySpec = new SecretKeySpec(md5(secretKey).getBytes(), "AES"); IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes()); Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector); byte[] encryptedByteArray = (new org.apache.commons.codec.binary.Base64()).decode(encryptedData.getBytes()); byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray); decryptedData = new String(decryptedByteArray, "UTF8"); } catch (Exception e) { LOGGER.debug("Problem decrypting the data", e); } return decryptedData; }
EDIT: The line number.toString(16)
of the md5 method needs to be replaced by String.format("%032x", number)
. See this article for more details.
Upgrade to RichFaces 3.3.3.Final
From time to time, it is good to upgrade the application libraries to the latest stable version. Especially the frontend libraries as the browsers are constantly involving and new ones are coming on the market.
This is why I wanted to upgrade the RichFaces library on one of my web application which was still using the version 3.3.0.GA with JSF/MyFaces 1.2.5.
The RichFaces dependency was looking like the following in my pom.xml
file:
<dependency> <groupId>org.richfaces.ui</groupId> <artifactId>richfaces-ui</artifactId> <version>3.3.0.GA</version> <scope>compile</scope> </dependency>
The upgrade should be straightforward.
But when changing to the version 3.3.3.Final, I got the following error:
2010-10-13 15:56:14.959::WARN: Error starting handlers java.lang.NoClassDefFoundError: org/ajax4jsf/component/SequenceDataAdaptor at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoader.defineClass(ClassLoader.java:616) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoader.defineClass(ClassLoader.java:616) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoader.defineClass(ClassLoader.java:616) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at org.apache.myfaces.shared_impl.util.ClassUtils.classForName(ClassUtils.java:132) at org.apache.myfaces.shared_impl.util.ClassUtils.simpleClassForName(ClassUtils.java:158) at org.apache.myfaces.application.ApplicationImpl.addComponent(ApplicationImpl.java:564) at org.apache.myfaces.config.FacesConfigurator.configureApplication(FacesConfigurator.java:650) at org.apache.myfaces.config.FacesConfigurator.configure(FacesConfigurator.java:277) at org.apache.myfaces.webapp.AbstractFacesInitializer.buildConfiguration(AbstractFacesInitializer.java:131) at org.apache.myfaces.webapp.Jsp21FacesInitializer.initContainerIntegration(Jsp21FacesInitializer.java:64) at org.apache.myfaces.webapp.AbstractFacesInitializer.initFaces(AbstractFacesInitializer.java:83) at org.apache.myfaces.webapp.StartupServletContextListener.contextInitialized(StartupServletContextListener.java:72) at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:540) at org.mortbay.jetty.servlet.Context.startContext(Context.java:135) at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220) at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:510) at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448) at org.mortbay.jetty.plugin.Jetty6PluginWebAppContext.doStart(Jetty6PluginWebAppContext.java:110) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152) at org.mortbay.jetty.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:156) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117) at org.mortbay.jetty.Server.doStart(Server.java:222) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40) at org.mortbay.jetty.plugin.Jetty6PluginServer.start(Jetty6PluginServer.java:132) at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:357) at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:293) at org.mortbay.jetty.plugin.AbstractJettyRunMojo.execute(AbstractJettyRunMojo.java:203) at org.mortbay.jetty.plugin.Jetty6RunMojo.execute(Jetty6RunMojo.java:182) at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:451) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:558) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:512) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:482) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:330) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:291) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:142) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:336) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:129) at org.apache.maven.cli.MavenCli.main(MavenCli.java:287) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315) at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375) Caused by: java.lang.ClassNotFoundException: org.ajax4jsf.component.SequenceDataAdaptor at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at org.codehaus.classworlds.RealmClassLoader.loadClassDirect(RealmClassLoader.java:195) at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:255) at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:274) at org.codehaus.classworlds.RealmClassLoader.loadClass(RealmClassLoader.java:214) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:375) at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337) ... 82 more
What happened here? I simply changed the version number and it now does NOT work! 🙁
Looking at the exception, it seems that it cannot find the class org.ajax4jsf.component.SequenceDataAdaptor
which is part of the richfaces-impl
library. Why not?
Well, in fact, it is quite simple! It appears that from the version 3.3.3 of RichFaces, you now have to specifically add the richfaces-impl
dependency to your pom.xml
file such as:
<dependency> <groupId>org.richfaces.ui</groupId> <artifactId>richfaces-ui</artifactId> <version>3.3.3.Final</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.richfaces.framework</groupId> <artifactId>richfaces-impl</artifactId> <version>3.3.3.Final</version> <scope>compile</scope> </dependency>
Why do we have to manually add this dependency? This is because the new version of RichFaces allows you to use JSF 2.0 instead of JSF 1.2. To do that, simply add the library richfaces-impl-jsf2
instead of richfaces-impl
in your pom.xml
file.
Please click on the following link for the JBoss manual about this configuration:
http://community.jboss.org/wiki/HowtoaddRichFaces33xtomavenbasedproject
The selfRendered attribute
This is an interesting problem related to the RichFaces rich:suggestionbox
tag.
Let’s take the following code:
<rich:suggestionbox for="q" minChars="1" suggestionAction="#{myBean.mySuggestionAction}" var="result" limitToList="true"> <h:column> <h:outputText value="#{result}" /> </h:column> </rich:suggestionbox>
If you use the code above as it is, the whole page is going to be processed each time the suggestionAction is called. And because the minChars
attribute is set to 1, the action is going to be called each time the user enters a character! 😮
For obvious reason, such as performance issue, this is not ideal.
To avoid this behaviour, you simply need to set the attribute selfRendered
to true as shown below:
<rich:suggestionbox for="q" minChars="1" suggestionAction="#{myBean.mySuggestionAction}" var="result" limitToList="true" selfRendered="true"> <h:column> <h:outputText value="#{result}" /> </h:column> </rich:suggestionbox>
Here is the description of the selfRendered
attribute from RichFaces documentation:
If “true”, forces active Ajax region render response directly from stored components tree, bypasses page processing. Can be used for increase performance. Also, must be set to ‘true’ inside iteration components, such as dataTable.
Don’t hesitate to add this attribute to increase the performance of your website. 😉
loadBundle’s behaviour with JSTL tags
Let’s start with a bit of knowledge.
f:loadBundle
is a JSF tag which loads a resource bundle and saves it as a variable in the request scope. The RichFaces a4j:loadBundle
tag is a substitution for the f:loadBundle
tag and allows to use reference to bundle messages during the Ajax re-rendering.
When I discovered the RichFaces tag, I immediately replaced all the f:loadBundle
tags by a4j:loadBundle
. Was I right? I thought at first, but then I got a problem. 🙁
The problem was appearing when I started mixing RichFaces and JSF tags.
For example, let’s take the following resource bundle:
active=true
And the following code:
<a4j:loadBundle basename="Messages" var="msg" /> Active is #{msg.active} -- <c:if test="#{msg.active}"> Hello World! </c:if>
This displays ‘Active is true --
‘.
What is wrong there? The active message is true but the c:if
condition failed! 😯
Let’s now try the following:
<a4j:loadBundle basename="Messages" var="msg" /> Active is #{msg.active} -- <c:if test="#{empty msg.active}"> Hello World! </c:if>
This displays ‘Active is true -- Hello World!
‘.
What does that mean? It seems that JSTL doesn’t get the value of the active
message but gets an empty string instead!
In conclusion, if the resource bundle is loading using the RichFaces tag, the messages will be not visible by the JSTL tags.
To fix this problem, you will have to also load the resource bundle using the JSF tag:
<a4j:loadBundle basename="Messages" var="msg" /> <f:loadBundle basename="Messages" var="msg" /> Active is #{msg.active} -- <c:if test="#{msg.active}"> Hello World! </c:if>
As expected, this displays ‘Active is true -- Hello World!
‘. 🙂