What could cause NullPointerException inside Sun's JavaKeyStore.engineStore() method? - java

We have an application that is creating a KeyStore programmatically. We create the KeyStore in the following manner (sample code, suppressing Exception handling for brevity),
KeyStore ks = KeyStore.getInstance( "JKS" );
ks.load( null, null );
... // Add crypto material here
keystore.store( new FileOutputStream( "keystore.ks" ), "password" );
Method store(OutputStream stream, char[] password) throws the following exception,
java.lang.NullPointerException
at sun.security.provider.JavaKeyStore.engineStore(Unknown Source)
at sun.security.provider.JavaKeyStore$JKS.engineStore(Unknown Source)
at java.security.KeyStore.store(Unknown Source)
The keystore.ks file is created in the file system. But when we try to inspect it with keytool we get,
keytool -list -keystore nms.keystore
keytool error: java.io.EOFException
Funny thing is, the same code works perfectly on every other machine that we have tested it. In the actual code, none of the arguments passed to the store method are null, we have triple-checked that.
Some details about the misbehaved machine,
CentOS 5.8 32 bits
Sun's JRE 1.6.0_43

The best explanation so far for what was happening is that something in the certificates that were being saved to the Keystore was triggering a NPE inside the method
sun.security.provider.JavaKeyStore.engineStore().
The certificates that are being generated are saved in the keystore with their full trust chain. For example, the entry for a certificate A would be of the form,
Cert A alias : Cert A -> Intermediate CA Trust -> Root CA Trust
The error went away after the whole trust chain was re-created. This is consistent with our previous observations because the chain of trust was the only thing different between the systems that were working and the systems that were not.
I've looked at the source of class sun.security.provider.JavaKeyStore at both Grep Code and Java Source Code but I'm unable to tell what could be causing the NPE in that code.
In the end we have a solution but we don't actually know the root cause.

Related

How do I codesign a JavaFX application through the NetBeans API?

I found this in the netbeans IDE:
I was pretty excited because up until this point I've been code signing my JavaFX projects like this:
<fx:signjar keystore = "${comodo.key.store}"
alias = "${comodo.key.alias}"
storetype = "PKCS12"
keypass = "${comodo.key.pass}"
storepass = "${comodo.key.storepass}"
jar = "${JFX.build.dir}/${JFXProject.name}.jar"
destdir = "${JFX.sign.dir}"/>
Which is fine. I mean, it works great and all and there's nothing wrong with it but I would really love to be able to use the Netbeans API code signer interface directly rather than drop the XML into the build file. I filled in the information in the way that seemed correct by taking the values I had in place in the XML and putting them into the interface but it didn't work and I got an error:
Going to create default keystore in "/*Not saying but it was the file name*/"
Generating Key for 3d637e48-f0d8-11e3-825a-20cf305e6ed4
keytool error: java.io.IOException: Invalid keystore format
This shouldn't even need to happen should it? I mean, I've been using this certificate for a while directly in the ant script for a while with no problem, so why is it happening now?
A bit more information: this is a Comodo certificate (if that helps).
What am I doing wrong here?

-tsa or -tsacert timestamp for applet jar self-signed

When I was trying to self-sign in the jar like below.
jarsigner -keystore my keystore myjar.jar myalias
It gives warning like:
No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (2014-05-08) or after any future revocation date.
Please help to resolve the problem.
The Java 7 release provides a (courtesy?) warning about something which has been in place for a decade...
Trusted Timestamping was introducing in Java 5 (2004). The motivation was so that developers would not be forced "to re-sign deployed JAR files annually" when the certificates expired.
→ http://docs.oracle.com/javase/1.5.0/docs/guide/security/time-of-signing.html
A URL-based Time Stamp Authority (TSA) is usually provided by the issuing Certificate Authority (CA) to work with the same certificates the CA issued. For example, the digicert tsa url can be access as follows:
jarsigner -tsa http://timestamp.digicert.com [.. other options]
→ http://www.digicert.com/code-signing/java-code-signing-guide.htm
Time stamping with self-signed certificate may be an elusive goal since (1) a TSA timestamp needs to be an trusted arms-length transaction (which rules out "self timestamping"), and (2) typical TSA URLs are setup to work with the certificates provided by the same CA organization (i.e. the TSA URL does not process a self-signed certificate)
Update:
URLs to try for timestamping self-signed certificates:
Symantec: -tsa http://sha256timestamp.ws.symantec.com/sha256/timestamp (per comment by brad-turek)
For a private network, one could consider an internal Timestamp Authority such as such as Thales (nCipher) Time Stamp Server (or historically OpenTSA)
This warning tells you that your jar's certificate will expire in may. Hence, users will not be able to execute your program after this date.
To improve the situation, the timestamp feature was added. This way, you can tell users: "I used the certificate at this point of time (which is provided and verified by the time stamp agency - tsa), when it was still valid!" As long as you do not change and resign your jar, it will still run, even after the certificate expires, because users see that at the point of creation the certificate was indeed valid.
For reference: http://docs.oracle.com/javase/7/docs/technotes/guides/security/time-of-signing.html
tl;dr: if you ignore the warning, your jar won't run after 14-05-08. Add a timestamp, and it will still run as long as you don't modify anything.
Regards
I was facing the same problem. Without the timestamp the jar would not get signed.
When you add -tsa http://timestamp.digicert.com, it would not give any warning or error but still the jar would not be signed.
But then I added the following part and it worked for me.
-tsacert alias
So, basically my final command was
jarsigner -verbose -tsa http://timestamp.digicert.com -tsacert alias -sigalg SHA256withRSA -digestalg SHA1 -keystore my-release-key.keystore android-release-unsigned.apk alias_name
Remember the alias_name in the command and the one in keystore should be the same.
This error is caused if updates were made with JDK Java/Oracle 1.7 u51. This JDK is NOT identical to the previous one.
You can install a previous version of the JDK BEFORE u51 (for exemple 1.7u45), or install JDK 6.
Then, when you re-compile, you won't see the error.

Caused by: java.security.UnrecoverableKeyException: Cannot recover key

I am supplied with a jks keystore named ABCC_client.store. When I import this keystore to cacerts and try connecting it says No such Algorithm error. PFA the stacktrace
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
at java.security.Provider$Service.newInstance(Provider.java:1245)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:220)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:147)
at javax.net.ssl.SSLContext.getInstance(SSLContext.java:125)
at javax.net.ssl.SSLContext.getDefault(SSLContext.java:68)
at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:102)
at org.apache.axis.components.net.JSSESocketFactory.initFactory(JSSESocketFactory.java:61)
at org.apache.axis.components.net.JSSESocketFactory.create(JSSESocketFactory.java:79)
... 32 more
Caused by: java.security.UnrecoverableKeyException: Cannot recover key
at sun.security.provider.KeyProtector.recover(KeyProtector.java:311)
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:121)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:38)
at java.security.KeyStore.getKey(KeyStore.java:763)
at com.sun.net.ssl.internal.ssl.SunX509KeyManagerImpl.<init>(SunX509KeyManagerImpl.java:113)
at com.sun.net.ssl.internal.ssl.KeyManagerFactoryImpl$SunX509.engineInit(KeyManagerFactoryImpl.java:48)
at javax.net.ssl.KeyManagerFactory.init(KeyManagerFactory.java:239)
at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.getDefaultKeyManager(DefaultSSLContextImpl.java:170)
at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.<init>(DefaultSSLContextImpl.java:40)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at java.security.Provider$Service.newInstance(Provider.java:1221)
... 39 more
But if I use this keystore independently i.e without adding it to cacerts it works.
Some googling led to me to http://joewlarson.com/blog/2009/03/25/java-ssl-use-the-same-password-for-keystore-and-key/ which says that password might me different for the key and the keystore.
If using Tomcat 6 and earlier, make sure the keystore password and the key password are same. If using Tomcat 7 and later, make sure they are the same or that the key password is specified in the server.xml file.
The private key password defined in your app/config is incorrect. First try verifying the the private key password by changing to another one as follows:
keytool -keypasswd -new changeit -keystore cacerts -storepass changeit -alias someapp -keypass password
The above example changes the password from password to changeit. This command will succeed if the private key password was password.
In order to not have the Cannot recover key exception, I had to apply the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files to the installation of Java that was running my application. Version 8 of those files can be found here or the latest version should be listed on this page. The download includes a file that explains how to apply the policy files.
Since JDK 8u151 it isn't necessary to add policy files. Instead the JCE jurisdiction policy files are controlled by a Security property called crypto.policy. Setting that to unlimited with allow unlimited cryptography to be used by the JDK. As the release notes linked to above state, it can be set by Security.setProperty() or via the java.security file. The java.security file could also be appended to by adding -Djava.security.properties=my_security.properties to the command to start the program as detailed here.
Since JDK 8u161 unlimited cryptography is enabled by default.
I had the same error when we imported a key into a keystore that was build using a 64bit OpenSSL Version. When we followed the same procedure to import the key into a keystore that was build using a 32 bit OpenSSL version everything went fine.
Check if password you are using is correct one by running below command
keytool -keypasswd -new temp123 -keystore awsdemo-keystore.jks -storepass temp123 -alias movie-service -keypass changeit
If you are getting below error then your password is wrong
keytool error: java.security.UnrecoverableKeyException: Cannot recover key
Sometimes this seems to be happening for no reason. I too faced the same and tried all methods like Keytool explorer etc.
Ultimately ended requesting Google to reset the key since I had Google play signing enabled. This is a good recommendation to follow.
https://support.google.com/googleplay/android-developer/answer/9842756?hl=en

Error with signing jar files using jarsigner with a real certificate

I have a problem with signing my jar files with jarsigner. I used this tutorial to sign my jar files, but with the last step(signing the jar), I got this error:
jarsigner error: java.lang.RuntimeException: keystore load: Invalid keystore format
and I didn't use step #10, I used instead step #5 from this site since, I'm using a real certificate not a fake one ...
Note:
I'm having my certificate in .spc & .pvk format...
But, since I'm using jarsigner, I have to convert them to .p12 format. So, I convert them first to .pfx using pvkimprt.exe then to .p12. I used the method that I specified in the link that I mentioned it before.
Also, I tried to create a fake certificate to make sure that the problem is not from the pvkimprt.exe tool or from the certificate. It gave me the same error.
The certificate is just fine. So, where is the problem came from?
The error you are facing indicates that jarsigner does not understand the format of the keystore containing the key.
If you converted your key & certificate into a PKCS#12 file you have to specify the type of used keystore to jarsigner with the -storetype PKCS12 command line option and the P12 password with -storepass mystorepassword
(actually most of the time .pfx and .p12 are used for the same file format therefore I am not sure that the firefox import/export step in the tutorial is mandated)
Not really an answer, just a comment - I found that the upper case was crucial - "pkcs12" didn't work but "PKCS12" did, using Jcs's answer.
This is what I did and that worked:
<ant:signjar alias="le-f0b73c88-1f82-4497-8c3f-e10d399b4c9c" storetype="pkcs12"
storepass="fount-current"
keystore="/vobs/oam_base/loadbuild_tools/common/src/conf/kunal.pfx">
Store pass should be the lower case, this is the working order or arguments, some time wrong order with throw the runtime padding exception.
[signjar] jarsigner error: java.lang.RuntimeException: keystore load:

How to test the code signing of a JAR file on a client machine?

We have signed a JAR file using a certificate generated by MS Active Directory Certificate Services. However, when accessing it via Java Web Start we are getting the prompt that the digital signature cannot be verified even though we've installed the root CA into the certificate store on the client machine.
Now trying to look at the root CA on the client machine, using "keytool -list", I'm seeing an exception (invalid URI:file://\my_msadcs_server\path\to\CRL.crl). So now I'm not sure exactly what is going wrong.
Anyone have a suggestion or sample Java code on how I can test the downloaded JAR file's signature on the client machine in an attempt to figure out exactly why JWS is complaining? It could be that the root CA certificate has a problem (and I will chase down that avenue when my AD admin gets in) but I'd like to rule out other possibilities first. Currently the only thing I have to go on is the exception from "keytool -list", but keytool had no issues importing the root CA certificate in the first place.
Thanks in advance!,
mG.
I use jarsigner with the -verify, -verbose and -certs options. You may have to specify your -keystore, too.
I think the invalid URI message is a clue. Java file URI takes the following form: file://host/path

Categories

Resources