If your jar is not signed you will get some message like this:
com.sun.deploy.net.JARSigningException: Se ha encontrado una entrada sin firma en el recurso: https://desarr.local/jnlp/XXXXXXX-jar-with-dependencies.jar
I built my jar by using Maven, and the final output is a file called XXXX-0.0.1-SNAPSHOT-jar-with-dependencies.jar. This jar contains all third party classes and resources that my application need to work.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.6</version> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <archive> <manifest> <mainClass>xxxxxxxxxx.Main</mainClass> </manifest> <manifestEntries> <Permissions>all-permissions</Permissions> <Codebase>desarr.local</Codebase> <Application-Name>xxxxxxxxx</Application-Name> <Application-Library-Allowable-Codebase>https://desarr.local</Application-Library-Allowable-Codebase> <Entry-Point>xxxxxxxxxx.Main</Entry-Point> <Built-By>Sisifo</Built-By> </manifestEntries> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin>
Note.
- I hid the application name on purpose because it is a real application I am working with.
- I downloaded the application from a Apache server located in "desarr.local", i.e, this is my htdocs basedir.
To sign my jar I created a self-signed certificate acting as a CA, and with it, I signed a second certificate (kind pro eh).
So, I have a PKCS12 certificate called jar-signer signed with my CA:
- The file is "jar_signer(1234).p12"
- The file format is PKCS12
- The password file is "1234"
- The certificate alias is "jar-signer"
- The alias key is "1234"
With this I now could sign my jar:
"c:\Program Files\Java\jdk1.7.0_21\bin\jarsigner.exe" -keystore jar_signer(1234).p12 -storetype PKCS12 -storepass 1234 -keypass 1234 XXXX-SNAPSHOT-jar-with-dependencies.jar jar-signer
Ok, I have a signed jar. I launch my JNLP file again and... Fail. I still get the exact same error.
The jar was signed properly. By using the "-verify" option of jarsigner I got success verification (although with some warnings), but the jar was fine.
"c:\Program Files\Java\jdk1.7.0_21\bin\jarsigner.exe" -verify XXXX-0.0.1-SNAPSHOT-jar-with-dependencies.jar jar verified. Warning: This jar contains entries whose certificate chain is not validated. Re-run with the -verbose and -certs options for more details.
At this point I checked the following issues:
1) My self signed certificates were not suitable.
I passed the jar to our client and they signed it with a "true" certificate,.
Result: Fail.
2) There were problems with the jarsigner tool.
I signed the jar with the jarsigner shipped with JDK 1.6.0_45, 1.7.0_21 and 1.8.0_51.
Result: Fail
3) Set to checked the java option to "keep temporary files on my computer"
In Control Panel > Java > General > Temporary files > Configuration.
Result: Fail
4) Import the sign certificate and the CA as trusted for java.
In Control Panel > Java > Security > Manage Certificates > User
Result: Fail
So I was quite sure that my configuration was fine and that the problem should be in the dam jar.
I opened the jar and I saw that there were a lot of non essential files in it, like licenses, poms, READMEs, etc...
I decided to manually remove all this "crap" and sign again. The result... Success!!!
After a while doing try-error deletes I found that the real problem was related to the file called "\jboss-as-jms-client-bom-7.3.0.Final-redhat-14.pom". Check the previous image and you will note that there is a slash "\" in this name. I think that, for some unknown reason, the java launcher was not able to process properly that file or that this file was not well signed at all.
Well, once I found the root of the problem, the next step was to modify the procedure I was using to create the jar.
The maven-assembly-plugin (check here http://maven.apache.org/plugins/maven-assembly-plugin/) has a config option called "descriptors" to reference an external descriptor file. Based on this file, the plugin know how to build the jar.
There are four predefined descriptors, being jar-with-dependencies just one of them.
I changed the plugin configuration and created a custom descriptor.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.6</version> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <archive> <manifest> <mainClass>xxxxxxxxxx.Main</mainClass> </manifest> <manifestEntries> <Permissions>all-permissions</Permissions> <Codebase>desarr.local</Codebase> <Application-Name>xxxxxxxxxx</Application-Name> <Application-Library-Allowable-Codebase>https://desarr.local</Application-Library-Allowable-Codebase> <Entry-Point>xxxxxxxxxx.Main</Entry-Point> <Built-By>Sisifo</Built-By> </manifestEntries> </archive> <descriptors> <descriptor>src/dev/assembly/distribution.xml</descriptor> </descriptors> </configuration> </execution> </executions> </plugin>
And this is my distribution.xml file:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> <id>jar-with-dependencies</id> <formats> <format>jar</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <outputDirectory>/</outputDirectory> <useProjectArtifact>true</useProjectArtifact> <unpack>true</unpack> <scope>runtime</scope> <unpackOptions> <excludes> <exclude>**/README</exclude> <exclude>**/LICENSE</exclude> <exclude>**/NOTICE</exclude> <exclude>**/ASL2.0</exclude> <exclude>**/INDEX.LIST</exclude> <exclude>**/*.txt</exclude> <exclude>**/*.html</exclude> <exclude>**/.project</exclude> <exclude>**/.classpath</exclude> <exclude>jboss-as-checkstyle/*</exclude> <!-- Eclsuiones relacionadas con maven --> <exclude>META-INF/maven/**</exclude> <exclude>**/pom.xml</exclude> <exclude>**/pom.properties</exclude> <exclude>*.pom</exclude> <exclude>**/*.pom</exclude> <!-- Licencias --> <exclude>META-INF/licenses/*</exclude> <exclude>licenses/*</exclude> <exclude>%regex[jboss-as-jms-client-bom]</exclude> <exclude>\jboss-as-jms-client-bom-7.3.0.Final-redhat-14.pom</exclude> </excludes> </unpackOptions> </dependencySet> </dependencySets>
With this configuration what I was trying to do was to remove all non-essential files and, specifically, the jboss-as-jms-client-bom-7.3.0.Final-redhat-14.pom.
Result: Fail
Even doing so, this file was still there. I tried all kind of expressions, excludes, fieldsets, etc... but no luck.
So, the plan B was to use a ant task to open the jar file, remove the file, and repack it.
For this I used maven-antrun-plugin.
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.7</version> <executions> <execution> <id>elimina-bom</id> <phase>package</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <zip file="${project.build.directory}/${project.build.finalName}-limpio.jar"> <zipfileset src="${project.build.directory}/${project.build.finalName}-jar-with-dependencies.jar"> <exclude name="**/*.pom" /> </zipfileset> </zip> </tasks> </configuration> </execution> </executions> </plugin>
Finally, after long hours of failures, my JNLP app was working...
Hi.
ResponderEliminarThanks for this great tutorial,
I have a question.
How did you create a self-signed certificate acting as a CA??
Please help me. Thanks a lot
Hi
ResponderEliminarWith keyStoreExplorer, when you generate a new key pair, there is an option to "Add Extensions".
There are a lot of extensions types, but I jus marked two:
- Basic Constraints: Subject is a CA
- Key Usage: Certificate signing
This would be your CA.
Once the CA was created, you can use the contextual menu option "Sign New Key Pair" and create a second certificate signed by the first one.
Regards