Search code examples
javasslssl-certificatekeystoreencryption-asymmetric

How to put a KeyPair into a KeyStore the right way? (programmatically in Java)


Its best to show my problem and explain it after (I am using KeyStore Explorer to peek into my .pfx files):

enter image description here

Basically, I want the result on the right, but I get the result on the left.

To be more precise: The KeyStore should contain the private key and certs chain (KeyPair), in one entry.

I somehow couldn't get it working in java. This is what I tried to get the result on the left: The problem with the code below is, that its not verifing the certs and adding them as trusted certs.

    /**
     * Creates and returns a new {@link KeyStore} from the provided information.
     * @param keystoreType The {@link KeyStore}s type. Recommended: "pkcs12".
     *                     Check {@link KeyStore#getInstance(String)} for details.
     * @param passwordAsCharArray Password to encrypt this {@link KeyStore} and its keys.
     * @param certificateChain The certificate chain is simply an array of {@link X509Certificate}s.
     * @param privateKey The {@link PrivateKey}.
     * @param publicKey The {@link PublicKey}.
     * @throws KeyStoreException
     */
    public KeyStore buildAndGetKeystore(String keystoreType, char[] passwordAsCharArray,
                                        X509Certificate[] certificateChain, PrivateKey privateKey, PublicKey publicKey)
            throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException, EmptyStringException, EmptyCharArrayException, EmptyCertificateChainException {

        // Check for null parameters
        Objects.requireNonNull(keystoreType);
        Objects.requireNonNull(passwordAsCharArray);
        Objects.requireNonNull(certificateChain);
        Objects.requireNonNull(privateKey);
        Objects.requireNonNull(publicKey);

        // Check for empty parameters
        if (keystoreType.isEmpty()) throw new EmptyStringException("Parameter 'keystoreType' should NOT be empty!");
        if (passwordAsCharArray.length==0) throw new EmptyCharArrayException("Parameter 'passwordAsCharArray' should NOT be empty!");
        if (certificateChain.length==0) throw new EmptyCertificateChainException("Parameter 'certificateChain' should NOT be empty!");

        // Initialise a new keystore
        KeyStore keystore = KeyStore.getInstance(keystoreType);
        keystore.load(null, passwordAsCharArray); // Pass null to tell java this is a new keystore

        // Insert certificates
        for (int i = 0; i < certificateChain.length; i++) {
            keystore.setCertificateEntry(""+i, certificateChain[i]);
        }

        // Write private key (with password protection) to keystore.
        // NOTE: I tried this before and it only writes 
        // the private key to the .pfx file and ignores the domain chain
        //keystore.setKeyEntry("sso-signing-key", privateKey, passwordAsCharArray, certificateChain);

        return keystore;
    }

Some extra details:

The KeyStore on the right was created like this: First generated the certs at sslforfree.com and then converted them to a PKCS12 KeyStore with https://decoder.link/converter


Solution

  • You guys won't believe this, but... The problem was the alias name 'priv-key'. Just removed the hyphen '-' and changed the alias name to 'myKey' like in https://stackoverflow.com/a/67147429/13600212 and voila it works... So many hours lost for such a stupid thing...