Tuesday, October 15, 2019

Identifying and handling Java keystore store types in different Java versions

Recently I encountered a different behaviour of Java keytool in newer versions of Java (I tested 10.0.2 and 11.0.4) compared to older versions (I tested 7.0_131 and 8.0_144) in regards to identifying store types.

Generate keystore with various store types

keytool is able to handle three different store types.
Basically I am running these commands (regardless which Java version is in place). Store types are not case sensitive.
keytool -genkey -alias foo -keystore a.keystore -storetype JKS
keytool -genkey -alias foo -keystore b.keystore -storetype JCEKS
keytool -genkey -alias foo -keystore c.keystore -storetype PKCS12

In detail:
I supply a password and simply hit Enter to all the questions being asked except the last one (answer y). I also don't provide a different key password.
Note that the default store type has also changed between Java versions (JKS in Java 8, PKCS12 in Java 10) so running the above commands without -storetype .. will generate keystores of different type resp. to your Java version in use. It is best to always indicate a store type in order to avoid any disambiguity.

keytool -genkey -alias foo -keystore a.keystore -storetype jks
Enter keystore password:
Re-enter new password:
What is your first and last name?
...
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
  [no]:  y

Enter key password for 
        (RETURN if same as keystore password):

Checking the keystore type via keytool -list

Since keytool -list ... also indicates the store type (before listing the aliases) I am running
keytool -list -keystore a.keystore
keytool -list -keystore b.keystore
keytool -list -keystore c.keystore

Result for Java 7 and 8

keytool -list -keystore a.keystore
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

foo, Oct 15, 2019, PrivateKeyEntry,
Certificate fingerprint (SHA1): 69:B0:E2:F8:D4:C3:77:70:A2:20:AC:BE:51:B1:6A:FF:71:85:AF:4F
keytool -list -keystore b.keystore
keytool error: java.io.IOException: Invalid keystore format

keytool -list -keystore c.keystore
keytool error: java.io.IOException: Invalid keystore format

i.e. keytool does not recognize the store type in Java 7 and 8
If you want to see the list of aliases you need to know the store type in advance and indicate it on the command line.

keytool -list -keystore b.keystore -storetype JCEKS
Enter keystore password:

Keystore type: JCEKS
Keystore provider: SunJCE

Your keystore contains 1 entry

foo, Oct 15, 2019, PrivateKeyEntry,
Certificate fingerprint (SHA1): 87:08:88:32:20:F2:61:11:C3:82:E0:DF:26:76:7B:8A:CD:2C:2C:B8
keytool -list -keystore c.keystore -storetype PKCS12
Enter keystore password:

Keystore type: PKCS12
Keystore provider: SunJSSE

Your keystore contains 1 entry

foo, Oct 15, 2019, PrivateKeyEntry,
Certificate fingerprint (SHA1): E8:C4:B1:F2:E2:C9:7F:9F:D0:10:77:3D:F5:07:30:77:3C:E3:74:8D

Result for Java 10 and 11

The newer Java versions are able to list any store type.
keytool -list -keystore a.keystore
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

foo, Oct 15, 2019, PrivateKeyEntry,
Certificate fingerprint (SHA-256): 25:EB:EE:65:AC:AD:F5:44:58:90:82:E3:BE:9D:A2:AD:D0:EC:91:50:CB:72:75:C9:03:12:0F:58:4F:A5:FA:44

Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore x.keystore -destkeystore x.keystore -deststoretype pkcs12".
keytool -list -keystore b.keystore
Enter keystore password:

Keystore type: JCEKS
Keystore provider: SunJCE

Your keystore contains 1 entry

foo, Oct 15, 2019, PrivateKeyEntry,
Certificate fingerprint (SHA-256): B2:61:07:4D:D5:12:58:D7:F8:49:BB:1A:7E:69:FC:F2:C4:3E:3A:9B:F3:B0:E0:F0:F5:3E:9F:46:C4:8B:A7:86

Warning:
The JCEKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore y.keystore -destkeystore y.keystore -deststoretype pkcs12".
keytool -list -keystore c.keystore
Enter keystore password:
Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 1 entry

foo, Oct 15, 2019, PrivateKeyEntry,
Certificate fingerprint (SHA-256): B4:E3:38:34:21:27:AC:0F:43:09:46:BC:FE:41:DF:1E:F5:5F:3A:75:75:52:D3:7C:42:A4:F7:57:B5:FC:34:9E

Note that the fingerprints are different and the store types JKS and JCEKS generate a warning.
The keystore provider for PKCS12 is SunJSSE in Java 7 and SUN in Java 10.


On UNIX systems you can use the file command to get an indication of the resp. store type.
file *.keystore

a.keystore: Java KeyStore
b.keystore: Java JCE KeyStore
c.keystore: data
i.e. the file "magic" can identify the old JKS and JCEKS keystores but the newest recommended PKCS12 is only shown as data.

Thursday, September 19, 2019

Assignment operator in python vs. copy

Lately I stumbled across the following issue when assigning a variable to another (which was a list) and a change to the original reflected in the second.
(This is in python 3.7. I am not using the python prompt >>> in the examples below.)

x = ['a']
y = x
x.append('b')
print(x)
   ['a', 'b']
print(y)
   ['a', 'b']

An example with int shows this

x = 5
y = x
x = x + 7
print(x)
  12
print(y)
  5

What might seem surprising at first glance totally makes sense:
an assignment '=' is not a copy operation.

The assignment

x = something
rather gives the name tag x to the object something.
y = x
gives the name tag y to the same object which is tagged x.
There is no copy aka. creation of a new object happening here.

The conclusion is:
if the object tagged x is a changeable object any change will be seen in y too.
So if the object is a list, tuple, set, dict etc. a change to the object (like the append operation) is both visible when either accessing x or y.

If the object is an integer or a string then it cannot be changed. Operations like addition create a new object.
x = x + 7 does not change the former object 5 but creates a new object 12.
y is still pointing to the old object and thus shows the old value.

If the intention of the original code was to create a copy of a list then a true copy operation should be used instead.

y = x[:]