【问题标题】:InvalidKeyException: Illegal key size saving BouncyCastle but not default provider public keyInvalidKeyException:非法密钥大小保存 BouncyCastle 但不是默认提供者公钥
【发布时间】:2017-06-17 23:22:36
【问题描述】:

我无法将具有 2048 位密钥的证书添加到 Bouncy Castle KeyStore。我已经使用 UnlimitedJCEPolicyJDK7.zip 更新了我的 JCE 版本,包括 JRE 和 JDK 安全文件夹。下面的代码指示错误位置。我正在使用 bcprov-jdk15on-149,但尝试了 bcprov-jdk15on-157,结果相同。有许多关于对称加密问题的帖子,但关于 PKE 的帖子较少。我正在运行 Windows 10 Pro、JRE 7、JDK 1.7.0_51。如有任何建议,我将不胜感激。

        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.

【问题讨论】:

  • 这里不是 RSA 密钥长度的问题,Java 7 对 RSA 密钥长度没有限制。但是对称密钥用于密钥库的加密,而 JKS 和 PKCS12 的加密是不同的。只是为了确定:在你的代码中添加一个检查无限强度政策,……。像这样:stackoverflow.com/a/11541337/2672392
  • 非常感谢,Omikron。我点击了您的链接,并在下面对我的问题的回答中发布了对代码的更改。

标签: java security bouncycastle keystore


【解决方案1】:

安装 JCE 更新的过程看起来很简单,所以我对我正在使用的版本的假设之一可能是错误的。正如 Omikron 在他的有用评论中指出的那样,无论如何这都不重要。他确实让我朝着正确的方向前进,从而导致了解决方案。我在下面发布修改后的代码。我不确定为什么默认的密钥库类型首先起作用而充气城堡没有。也许熟悉 bouncycastle 的人会分享他们的想法。与此同时,我将看看这是否也适用于 Android。

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();
    }
}

【讨论】:

    猜你喜欢
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    相关资源
    最近更新 更多