Loading JKS file written by OpenJDK Java 21 results in ASN.1 error
I'm not sure whether this issue stems from pyjks or pyasn1. I might post it in both projects.
If I use jks.KeyStore.load on a JKS file containing a certificate/key bunde that was imported using keytool from OpenJDK Java 21 (java-21-openjdk-21.0.3.0.9-1.fc40.x86_64), then an ASN.1 error occurs:
>>> import jks
>>> jks.KeyStore.load('javakeystore21.jks', '[PASSWORD]')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/username/.local/lib/python3.12/site-packages/jks/util.py", line 90, in load
ret = cls.loads(input_bytes,
^^^^^^^^^^^^^^^^^^^^^^
File "/home/username/.local/lib/python3.12/site-packages/jks/jks.py", line 525, in loads
entry.decrypt(store_password)
File "/home/username/.local/lib/python3.12/site-packages/jks/jks.py", line 197, in decrypt
algo_params = encrypted_info['encryptionAlgorithm']['parameters'].asOctets()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/username/.local/lib/python3.12/site-packages/pyasn1/type/univ.py", line 915, in asOctets
return bytes(self._value)
^^^^^^^^^^^^^^^^^^
File "/home/username/.local/lib/python3.12/site-packages/pyasn1/type/base.py", line 213, in plug
raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % name)
pyasn1.error.PyAsn1Error: Attempted "__index__" operation on ASN.1 schema object
If I instead import the same SSL bundle using keytool from OpenJDK Java 17 (java-17-openjdk-17.0.11.0.9-1.fc40.x86_64), then loading it works fine:
>>> import jks
>>> jks.KeyStore.load('javakeystore17.jks', '[PASSWORD]')
<jks.jks.KeyStore object at 0x7f04826bd6a0>
This happens with pyjks 20.0.0 and pyasn1 0.6.0 on Python 3.12.
The keytool import command that I run looks like this:
keytool -importkeystore -srckeystore bundle.p12 -srcstoretype pkcs12 -srcalias mybundle -destkeystore javakeystore.jks -destalias mybundle
I have a feeling that OpenJDK 21's keytool command does not give encrypted private keys any encryption algorithm parameters when they're placed into JKS files. When I compare javakeystore21.jks and javakeystore17.jks using keytool -list -v, they're exactly the same. But the two files are slightly different sizes. And if I use the strings command on the two of them, it looks like the encrypted private key under mybundle is quite different.
Thanks for reaching out with the excellent report, Paul. Unfortunately, the maintainers of this package (myself included) haven't touched a JKS in a long while. If you make any progress, we're happy to review a PR with a test/fix. Thanks again!
I've came across this issue today. Have you found any workaround?
Edit: To add more info if anyone will be interested in fixing it. The same thing will happen in the following scenario.
- Take a PEM format certificate and private key, use pyjks to create a jks KeyStore and save it as a file.
- Open it in Java (21) using keytool or KeyStore Explorer and let's say modify the password, then save it.
- KeyStore is no longer be supported by pyjks and decrypting the PrivateKeyEntry object will raise the mentioned exception.
Do you really have JKS content? The "Java Key Store" object (in Java) can deal with JKS or PKCS#12 content. The default from keytool is now to generate PKCS#12 material. JKS content is deprecated since (I think) Java 9.
To read PKCS#12 you can use the 'cryptogrpahy' package.