Handles and converts PKCS#12 files that are not compatible with Java#765
Handles and converts PKCS#12 files that are not compatible with Java#765kaikramer merged 2 commits intokaikramer:mainfrom
Conversation
| super.load(new ByteArrayInputStream(data), password); | ||
|
|
||
| Set<Certificate> visibleCerts = extractAllCertificates(); | ||
| invisibleCerts = parseP12(data, password).stream() // |
There was a problem hiding this comment.
Invisible comments for the invisible certificates - nice :-)
| return 128; | ||
| } else if (id_aes256_GCM.getId().equals(id)) { | ||
| return 256; | ||
| } else if (id_camellia128_cbc.getId().equals(id)) { |
There was a problem hiding this comment.
Where did you get this list of algorithms from? I was not aware that these are used for PKCS#12 encryption.
There was a problem hiding this comment.
I got it from org.bouncycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi.DefaultSecretKeyProvider. It is used by BC when constructing the PBKDF2KeySpec. I went looking for uses of PBKDF2KeySpec, and that's what I found in the BC provider.
It's not documented, but OpenSSL can construct such P12 files using this command:
openssl pkcs12 -export -inkey my.key -in my.cer -out my.p12 -keypbe CAMELLIA-256-CBC -certpbe CAMELLIA-256-CBC
From DPkcs12Info:
Properties for 'camellia.p12'
File: /Users/camellia.p12
Type: PKCS#12
MAC
Algorithm: Sha-256 (2.16.840.1.101.3.4.2.1)
Salt: 16 bytes
Iterations: 2,048
PKCS#7 Encrypted Data
Algorithm: Pkcs5PBES2 (1.2.840.113549.1.5.13)
Key Derivation Function: Pkcs5PBKDF2 (1.2.840.113549.1.5.12)
Salt: 16 bytes
Iterations: 2,048
Encryption Scheme: 1.2.392.200011.61.1.1.1.4
Certificate Bag
Subject: CN=ML-KEM
Issuer: CN=ML-DSA Authority
Serial Number: 50c61c75fe94be2dab9969c4cb49019b73760f93
Validity: Wed Dec 31 00:11:15 PST 2025 - Fri Dec 31 00:11:15 PST 2027
Bag Attributes
Local ID: f59c9d1207041d2cd2dc6678e94a01ba20f271bf
Certificate Bag
Subject: CN=ML-DSA Authority
Issuer: CN=ML-DSA Authority
Serial Number: 50a8a44f5dd2c8c529246e4de6a5019b737560b7
Validity: Wed Dec 31 00:10:30 PST 2025 - Fri Dec 31 00:10:30 PST 2027
Bag Attributes
PKCS#7 Data
PKCS#8 Shrouded Key Bag
Algorithm: Pkcs5PBES2 (1.2.840.113549.1.5.13)
Key Derivation Function: Pkcs5PBKDF2 (1.2.840.113549.1.5.12)
PBKDF2 Salt: 16 bytes
PBKDF2 Iterations: 2,048
Encryption Scheme: 1.2.392.200011.61.1.1.1.4
Bag Attributes
Local ID: f59c9d1207041d2cd2dc6678e94a01ba20f271bf
But then the Java PKCS12 KeyStore provider chokes on it:
org.kse.crypto.keystore.KeyStoreLoadException: Could not load KeyStore as type 'PKCS12'.
at org.kse.crypto.keystore.KeyStoreUtil.load(KeyStoreUtil.java:176)
at org.kse.crypto.keystore.KeyStoreUtil.load(KeyStoreUtil.java:132)
<snip>
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
java.io.IOException: parseAlgParameters failed: PBE parameter parsing error: expecting the object identifier for AES cipher
at java.base/sun.security.pkcs12.PKCS12KeyStore.parseAlgParameters(PKCS12KeyStore.java:855)
at java.base/sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2113)
at java.base/sun.security.util.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:221)
at java.base/java.security.KeyStore.load(KeyStore.java:1473)
<snip>
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
So it really isn't necessary to add those other ciphers. The Java provider does not support them.
This PR implements #760. I didn't try to refactor the P12 parsing logic. I just copied the portions needed for extracting the certs and friendly names.
This PR also fixes two defects with file reloading:
Dialog prompts for conversion of the key store when KSE identifies that it contains certificates that are not part of any private key cert chain or with the Java trusted cert identifier:

Clicking "No" leaves the key store as it is, and the cert is lost if the user performs any operation that modifies the key store.

Clicking "Yes" converts the key store:

The conversion can be undone:

Let me know if there are any changes that you would like.