0

I'm unable to add a certificate with a 2048 bit key to a Bouncy Castle KeyStore. I've updated my version of JCE, both the JRE and JDK security folders, with UnlimitedJCEPolicyJDK7.zip. The code below indicates the error location. I'm using bcprov-jdk15on-149 but have tried bcprov-jdk15on-157 with the same results. There are a number of posts regarding symmetric encryption problems but fewer on PKE. I'm running Windows 10 Pro, JRE 7, JDK 1.7.0_51. I'd appreciate any suggestions.

        char[] testPass = "changeit".toCharArray();
        String testAlias = "express";

        // -----------------------------------------------------------------
        // Open source TrustStore and extract certificate and key
        FileInputStream jksFis  = new FileInputStream("G:\\testSrc.jks");
        KeyStore jksKS = KeyStore.getInstance(KeyStore.getDefaultType());
        jksKS.load(jksFis, testPass);
        PrivateKey jksPK = (PrivateKey) jksKS.getKey(testAlias,testPass);
        RSAKey rsaKey = (RSAKey)jksPK;
        int rsaKeyLen = rsaKey.getModulus().bitLength();
        System.out.printf("Key length is %d\n",rsaKeyLen); // 2048
        X509Certificate[] jksCerts = new X509Certificate[1];
        jksCerts[0] = (X509Certificate) jksKS.getCertificate(testAlias);

        // -----------------------------------------------------------------
        // Create new default type keystore and add certificate and key.
        KeyStore jksDest = KeyStore.getInstance(KeyStore.getDefaultType());
        jksDest.load(null,null);
        jksDest.setKeyEntry(testAlias, jksPK, testPass, jksCerts);
        FileOutputStream jfos = new FileOutputStream("G:\\testDest.jks");
        jksDest.store(jfos, testPass);
        jfos.close();

        // -----------------------------------------------------------------
        // Create Bouncy Castle KeyStore and add certificate and key
        Security.addProvider(new BouncyCastleProvider());
        KeyStore bksKS = KeyStore.getInstance("PKCS12","BC");
        bksKS.load(null,null);
        bksKS.setKeyEntry(testAlias, jksPK, testPass, jksCerts);
        FileOutputStream bksFos = new FileOutputStream("G:\\testDest.bks");
        // -----------------------------------------------------------------
        // Next line gives this error:
        // java.io.IOException: exception encrypting data - 
        // java.security.InvalidKeyException: Illegal key size
        bksKS.store(bksFos, testPass);  // This is the error line.
        // Error on previous line.
Will
  • 93
  • 3
  • 12
  • 1
    The RSA key length is not the problem here, there is no restriction for RSA key lengths in Java 7. But symmetric keys are used for the encryption of the keystore and those are different for JKS and PKCS12. Just to be sure: Add a check in your code for unlimited strength policy, sth. like this: https://stackoverflow.com/a/11541337/2672392 – Omikron Jun 18 '17 at 21:27
  • Thanks so much, Omikron. I followed your link and posted the resulting changes to the code in my answer to my question below. – Will Jun 19 '17 at 05:22

1 Answers1

0

The procedure for installing the JCE update seems pretty straightforward so one of my assumptions about the version I'm using may be mistaken. As Omikron pointed out in his helpful comment it shouldn't have mattered anyway. He did get me going in the right direction which led to the solution. I'm posting the revised code below. I'm not sure why the default keystore type worked in the first place and bouncy castle didn't. Maybe someone familiar with bouncycastle will share their thoughts. In the meantime I'm going to see if this works on Android too.

public static void main(String[] args) {
    try{
        // -----------------------------------------------------------------
        // Anonymous recommendation I found here:
        // http://suhothayan.blogspot.com/2012/05/how-to-install-java-cryptography.html
        // This fixed my problem.
        try { 
            Field field = Class.forName("javax.crypto.JceSecurity").
                                getDeclaredField("isRestricted");
            field.setAccessible(true);
            field.set(null, java.lang.Boolean.FALSE); 
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        // -----------------------------------------------------------------        
        // Check recommended by Omikron, who was correct: I assume I didn't 
        // install the JCE properly because it prints 128 for the max 
        // key allowd key length.
        int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
        System.out.printf("max key len: %d\n",maxKeyLen);
        // -----------------------------------------------------------------

        char[] testPass = "changeit".toCharArray();
        String testAlias = "express";

        // -----------------------------------------------------------------
        // Open source TrustStore and extract certificate and key
        FileInputStream jksFis  = new FileInputStream("G:\\testSrc.jks");
        KeyStore jksKS = KeyStore.getInstance(KeyStore.getDefaultType());
        jksKS.load(jksFis, testPass);
        PrivateKey jksPK = (PrivateKey) jksKS.getKey(testAlias,testPass);
        RSAKey rsaKey = (RSAKey)jksPK;
        int rsaKeyLen = rsaKey.getModulus().bitLength();
        System.out.printf("JKS key length is %d\n",rsaKeyLen); // 2048
        X509Certificate[] jksCerts = new X509Certificate[1];
        jksCerts[0] = (X509Certificate) jksKS.getCertificate(testAlias);

        // -----------------------------------------------------------------
        // Create new default type keystore and add certificate and key.
        KeyStore jksDest = KeyStore.getInstance(KeyStore.getDefaultType());
        jksDest.load(null,null);
        jksDest.setKeyEntry(testAlias, jksPK, testPass, jksCerts);
        FileOutputStream jfos = new FileOutputStream("G:\\testDest.jks");
        jksDest.store(jfos, testPass);
        jfos.close();

        // -----------------------------------------------------------------
        // Create Bouncy Castle KeyStore and add certificate and key
        Security.addProvider(new BouncyCastleProvider());
        KeyStore bksKS = KeyStore.getInstance("PKCS12","BC");
        bksKS.load(null,null);
        bksKS.setKeyEntry(testAlias, jksPK, testPass, jksCerts);
        FileOutputStream bksFos = new FileOutputStream("G:\\testDest.bks");
        bksKS.store(bksFos, testPass);
        bksFos.close();

        // -------------------------
        // Open file and check key length:
        bksKS = KeyStore.getInstance("PKCS12","BC");
        FileInputStream bksFis  = new FileInputStream("G:\\testDest.bks");
        bksKS.load(bksFis, testPass);
        PrivateKey bpk = (PrivateKey) bksKS.getKey(testAlias,testPass);
        rsaKey = (RSAKey)bpk;
        rsaKeyLen = rsaKey.getModulus().bitLength();
        System.out.printf("BKS key length is %d\n",rsaKeyLen); // 2048
        X509Certificate bkCert = (X509Certificate) bksKS.getCertificate(testAlias);
        System.out.printf("Issuer name: %s", bkCert.getIssuerDN().getName());
    }catch(Exception e){
        e.printStackTrace();
    }
}
Will
  • 93
  • 3
  • 12