Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uninitialzed keystore with Java 8 171/172 and higher #120

Closed
dschadow opened this issue May 6, 2018 · 9 comments
Closed

Uninitialzed keystore with Java 8 171/172 and higher #120

dschadow opened this issue May 6, 2018 · 9 comments
Assignees
Labels
Milestone

Comments

@dschadow
Copy link
Member

dschadow commented May 6, 2018

With Java 8 update 171/172 and possibly Java 9/10 the JCT keystore isn't initialized/ working any more. The reason might be the switch from JKS to PKCS12 as keystore format.

@dschadow dschadow added the Bug label May 6, 2018
@dschadow dschadow added this to the Final 1.0.0 milestone May 6, 2018
@dschadow
Copy link
Member Author

dschadow commented May 6, 2018

@grthor
Copy link
Member

grthor commented May 25, 2018

I have investigated this problem, but have come to no solution.

With the Java Update 8u171 a new security property has been intorduced http://www.oracle.com/technetwork/java/javase/8u171-relnotes-4308888.html#JDK-8189997 . The input stream is filtered when deserializing a secret key from the keystore. The input must match one of the following types: java.lang.Enum, java.security.KeyRep, java.security.KeyRep$Type, javax.crypto.spec.SecretKeySpec.
It looks like this new feature is causing the problem.

In the Release Notes to 8u171 Oracle states:

Customers storing a SecretKey that does not serialize to the above types must modify the filter to make the key extractable.

First of all, I do not know how the keys are serialized in the JCT, but I tried to change the filter to allow everything and get it working again.

  • The filter is specified in C: \ Program Files \ Java \ jdk1.8.0_151 \ jre \ lib \ security \ java.security, so i compared it with an older version (8u151) to detect changes. After that, I have set the changes that affect the deserialization of the JCEKS to the old version. -> No success.
  • Then I tried to change the filter according to this manual https://access.redhat.com/blogs/766093/posts/3135411.

Description of the error

As soon as the keystore is to be loaded, the following errors are displayed in the stack trace:
Mai 25, 2018 4:42:38 PM java.io.ObjectInputStream filterCheck
INFO: ObjectInputFilter REJECTED: null, array length: -1, nRefs: 1, depth: 1, bytes: 70, ex: n/a
!SESSION 2018-05-25 16:42:29.923 -----------------------------------------------
... 

The first Exception:

!ENTRY org.jcryptool.crypto.keystore 4 0 2018-05-25 16:42:38.802
!MESSAGE Invalid secret key format
!STACK 0
java.io.IOException: Invalid secret key format
	at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:856)
	at java.security.KeyStore.load(KeyStore.java:1445)
	at org.jcryptool.crypto.keystore.backend.KeyStoreManager.loadKeystore(KeyStoreManager.java:180)
...

The second Exception:

org.eclipse.core.runtime.CoreException: File already exists on disk: C:\Users\Thorben\Documents\.jcryptool\flexiprovider\jctKeystore.ksf.

The second exception is just a "following error" and will probably disappear as soon as the first exception has been fixed. It is thrown in loadKeystore() in JceKeyStore.java:856, if the keystore failed to load successfully, it tries to create a new keystore.

Similar errors on the web

https://stackoverflow.com/questions/50393533/java-io-ioexception-invalid-secret-key-format-when-opening-jceks-key-store-wi

@grthor
Copy link
Member

grthor commented Jun 26, 2018

Here are some new insights from @simlei and my research:

The jdk.serialFilter or the jceks.key.serialFilter can be set with -Djdk.jdk.serialFilter = pattern or -Djdk.jceks.key.serialFilter = pattern. The pattern is described at the very end of your /java/jre/lib/security/java.security file. If you set the filter in this way, an info message will be displayed in the console stating that the filter has been set. This info looks like an error message.

Jun 19, 2018 8:05:40 PM sun.misc.ObjectInputFilter$Config lambda$static$0
INFO: Creating serialization filter from *

Here’s a nice Link describing the Filter https://docs.oracle.com/javase/10/core/serialization-filtering1.htm#JSCOR-GUID-3ECB288D-E5BD-4412-892F-E9BB11D4C98A. Unfortunately it referes to Java 9.

The error message:

Jun 19, 2018 8:05:40 PM java.io.ObjectInputStream filterCheck
INFO: ObjectInputFilter REJECTED: null, array length: -1, nRefs: 1, depth: 1, bytes: 70, ex: n/a

It is structured as follows:
Info: ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}

  • 0: The filter status: Possible statuses are UNDECIDED, REJECTED and ALLOWED.
  • 1: The class: The object class being deserialized. the class; may be null
  • 2: Array length: the array length requested; use -1 if not creating an array
  • 3: References to other classes: Total number of references to any type of object, class, enum, proxy, etc.
  • 4: recursion depth
  • 5: the number of bytes read from the input stream
  • 6: Runtime exception: n/a is the default value.

The byteinputstream when it is rejected is

[c, o, m, ., s, u, n, ., c, r, y, p, t, o, ., p, r, o, v, i, d, e, r, ., S, e, a, l, e, d, O, b, j, e, c, t, F, o, r, K, e, y, P, r, o, t, e, c, t, o, r, ...

Actually, this class should be allowed because the filter was previously set to * (allow all).

At the end of private void filterCheck(Class<?> clazz, int arrayLength) throws InvalidClassException { an InvalidClassException is thrown, which is then generalized to an IOException before being output to the console.

@grthor
Copy link
Member

grthor commented Nov 24, 2018

Workaround

If you are using an actual Weekly Build and Windows you have a folder ".jcryptool" in the document library. If you delete this foder once it works with Java 8u170 and higher.

The background is that the keystore is saved in the .jcryptool folder. Version 0.9 (last stable version) comes with a key that does not conform to the security policies introduced in Java 8u170. The Weekly Builds no longer provide this key. However, the weekly builds do not overwrite the keystore, so the broken key still exists and continues to cause an exception when loading the keystore. If the folder is deleted, the keystore will be recreated without the broken key and it works.

@grthor grthor pinned this issue Feb 1, 2019
@dschadow dschadow unpinned this issue Feb 16, 2019
@simlei
Copy link
Member

simlei commented Oct 13, 2019

The keystore has developed further issues with Java 11, see #149

@simlei simlei self-assigned this Oct 13, 2019
@simlei
Copy link
Member

simlei commented Oct 26, 2019

It seems that things have changed once Java 11 with OpenJDK/JRE was introduced and the JAXB issue was resolved. For me, the keystore seems to work now. I have however not have found too much time looking into it and also don't quite remember at which exact point we experienced this issue: Loading the keystore / adding and removing keys? That seems to work now on my machine. Or was it when invoking a certain algorithm?

Test with the version from my fork at: https://github.com/simlei/core/releases/tag/v1.0-J11-CH-1

This is the original keystore file that was removed due to the original issue: it goes into ~/Documents/.jcryptool/flexiprovider/

https://github.com/jcryptool/core/blob/2ea363bf97ab77757b8d9bbb1b985c1a3ce23a5b/org.jcryptool.crypto.keystore/keystore/jctKeystore.ksf

@grthor
Copy link
Member

grthor commented Oct 28, 2019

I tested the keystore in the version from your fork (https://github.com/simlei/core/releases/tag/v1.0-J11-CH-1). For me, the keystore shows the same error as in previous versions.

This are the last lines from the exception:

!ENTRY org.jcryptool.crypto.keystore 4 0 2019-10-28 21:57:31.814
!MESSAGE Rejected by the jceks.key.serialFilter or jdk.serialFilter property
!STACK 0
java.security.UnrecoverableKeyException: Rejected by the jceks.key.serialFilter or jdk.serialFilter property
	at java.base/com.sun.crypto.provider.KeyProtector.unseal(Unknown Source)
	at java.base/com.sun.crypto.provider.JceKeyStore.engineGetKey(Unknown Source)
	at java.base/java.security.KeyStoreSpi.engineGetEntry(Unknown Source)
	at java.base/java.security.KeyStore.getEntry(Unknown Source)
	at org.jcryptool.crypto.keystore.backend.KeyStoreManager.getSecretKey(KeyStoreManager.java:371)
	at org.jcryptool.crypto.keystore.backend.KeyStoreManager.getKey(KeyStoreManager.java:275)

Reproduction

I did the following steps to produce the error:

  1. Download and unzip the version from your fork.
  2. Delete the .jcryptool folder to get evade problems caused by previous JCT versions.
  3. Started the downloaded product.

Current state: JCT runs with Java 11.0.5 and everything seems fine.

  1. Opened the keystore and pressed "new secret key" in the top right corner (the key icon).
  2. Used "Alice Whitehaed" as contact name and as algorithm "AES, Rijndael". The keylength is the standard key length.
  3. Typed password 1234 two times and pressed "Finish".
    Current State: The key is created. It is listed below "secret keys".
  4. Do a right click on the key and select "Properties" (Eigenschaften).
  5. Now you get an error messageimage

Current State: the exception listed above as code snipped is printed to the error log.

  1. Hit "ok" in the error message. Now you will get the Dialog that you requested. I don't now if any key properties are missing.
    image

This is how i produced the error.

I hope you can reproduce it.

Testing the old keystore file

Now i tested the old keystore (https://github.com/jcryptool/core/blob/e5215aaff40862c7f199a80b409063dab735d7de/org.jcryptool.crypto.keystore/keystore/jctKeystore.ksf).
10. Downloaded the kestore and copied it to .jcryptool/flexiprovider.
11. Started the product and opened the keystore.

Current State: No new exceptions in the error log. The old keystore seems to work. In my memory the old keystore does not open at all, so thats an improvement already :) Interestingly there is an "AES, Rijandael" key already stored.

  1. Do a right click on the key and select "properties" like in step 7.
  2. The same error as in step 8 comes up.
  3. Clicked on "ok" and got the same dialog like in step 9.

Summary: So the behaviour of the keystore, when trying to show the properties of a key that does not conform the jceks.serialFilter or jdk.serialFilter, is the same with the old and and new keystore file. An improvement is, that the old keystore can be opened :)

Testing the "properties" Dialog

In the next steps i tested wether the "Properties" dialog works. Therefore i choosed the ElGamal key, because it fits to the serialFilters.

  1. I selected the ElGamal key that is saved in the keystore and expanded the entry. Now you could see the "Private key" and "Public key".
  2. I done a right click on "Private Key" and selected "Properties". Now i get a dialog window like in step 9 and 13 but with more key properties.
    image

Current State: No new exceptions are shown in the error log after showing the properties of the ElGamal secret key.

Summary: The properties Dialog seems to work correct.

Conclusio

The keystore works with the old keystore file. I would suggest to replace the new one with the old one, because the old one contains more keys. Unfortunately you can not display all properties of a key that does not conform to jceks.serialFilter or jdk.SerialFilter. The problem does not seem to be fixed on all platforms

Hope this will help you @simlei . If you have other scenarios that i should test, just write it in the comments or send me a mail.

Best regards, Thorben

simlei pushed a commit to simlei/core that referenced this issue Oct 29, 2019
Signed-off-by: Simon Leischnig <simon-jena@gmail.com>
@simlei
Copy link
Member

simlei commented Oct 29, 2019

This should do it (see commit above)
Please test: https://github.com/simlei/core/releases/tag/v1.0-J11-CH-KS-1

Could only be released together with the branch from my core/ fork. This is unfortunately still blocked by OSX not starting up with the Java 11 JRE... :(

@grthor
Copy link
Member

grthor commented Oct 29, 2019

Hi @simlei , great news 🎉 Your new product (https://github.com/simlei/core/releases/tag/v1.0-J11-CH-KS-1) works for me.
I tested the keystore in the same way as i tested your last product. Heres my way shortened to two steps:

  1. Created an AES key
  2. Tried to see the properties of the key.

The product works for the old and new keystore file. :)

Best regars, Thorben

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants