Search code examples
javasecurityx509certificatebouncycastle

Cannot generate PKCS#12 keystore to use in Chrome


I'm trying to generate PKCS#12 keystore with Java and BouncyCastle:

// yesterday
Date validityBeginDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
// in 2 years
Date validityEndDate = new Date(System.currentTimeMillis() + 2 * 365 * 24 * 60 * 60 * 1000);

// GENERATE THE PUBLIC/PRIVATE RSA KEY PAIR
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
keyPairGenerator.initialize(1024, new SecureRandom());

KeyPair keyPair = keyPairGenerator.generateKeyPair();

// GENERATE THE X509 CERTIFICATE
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
X500Principal dnName = new X500Principal("CN=" + username);

certGen.setSerialNumber(serial);
certGen.setSubjectDN(dnName);
certGen.setIssuerDN(dnName); // use the same
certGen.setNotBefore(validityBeginDate);
certGen.setNotAfter(validityEndDate);
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");

X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC");

KeyStore clientKeystore = KeyStore.getInstance("PKCS12", "BC");

clientKeystore.load(null, null);

clientKeystore.setKeyEntry("mkey", keyPair.getPrivate(), null, new X509Certificate[] { cert });

clientKeystore.store(new FileOutputStream("admin.pkcs"), "pass".toCharArray());

The keystore is generated just fine, but when I'm trying to load it to Chrome, it shows Unknown error. I've tried to load it with pk12util and got more detailed error message:

pk12util: PKCS12 decode import bags failed: SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY: Unable to import.  Error attempting to import private key.

How can I generate valid PKCS#12 keystore to use it with browsers?


Solution

  • The following worked for me (Win7, Jdk7,bcprov-jdk16 1.46). I can generate a pkcs12 file and import it. The differences with your code are probably in the versions of OS/JRE/BC, the line : Security.addProvider(new BouncyCastleProvider()) and some compilation fixes;

    public static void main( String[] args ) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, IllegalStateException, SignatureException, KeyStoreException, CertificateException, FileNotFoundException, IOException
    {
        Security.addProvider(new BouncyCastleProvider());
        // yesterday
        Date validityBeginDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
        // in 2 years
        Date validityEndDate = new Date(System.currentTimeMillis() + 2 * 365 * 24 * 60 * 60 * 1000);
    
        // GENERATE THE PUBLIC/PRIVATE RSA KEY PAIR
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");
        keyPairGenerator.initialize(1024, new SecureRandom());
    
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
    
        // GENERATE THE X509 CERTIFICATE
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
        X500Principal dnName = new X500Principal("CN=" + "username");
    
        certGen.setSerialNumber(new BigInteger("100"));
        certGen.setSubjectDN(dnName);
        certGen.setIssuerDN(dnName); // use the same
        certGen.setNotBefore(validityBeginDate);
        certGen.setNotAfter(validityEndDate);
        certGen.setPublicKey(keyPair.getPublic());
        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
    
        X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC");
    
        KeyStore clientKeystore = KeyStore.getInstance("PKCS12", "BC");
    
        clientKeystore.load(null, null);
    
        clientKeystore.setKeyEntry("mkey", keyPair.getPrivate(), null, new X509Certificate[] { cert });
    
        clientKeystore.store(new FileOutputStream("admin.pkcs"), "pass".toCharArray());
    }