Java将密钥保存到密钥库KeyStoreException

Java将密钥保存到密钥库KeyStoreException,java,bouncycastle,keystore,Java,Bouncycastle,Keystore,我尝试生成RSA CA密钥对和证书,并将其保存到密钥库。 我的代码是: import java.io.FileOutputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.SecureRandom; import java.secur

我尝试生成RSA CA密钥对和证书,并将其保存到密钥库。 我的代码是:

import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Date;

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

    private static final  String storeType = "PKCS12";
        private static final  String storePassword = "password";
        private static final  String storePath = "/usr/lib/java/keystore.ks";
        private static final Date startDate = new Date(System.currentTimeMillis());                                         // time from which certificate is valid
        private static final Date expiryDate = new Date(System.currentTimeMillis() + 2L * 365L * 24L * 60L * 60L * 1000L);   // time after which certificate is not valid (2 years)
        private static final BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());  
        private static X500Name issuer;
        private static X500Name subject; 
        private static KeyPair pair;

        public static void saveKeys() throws Exception{
            Security.addProvider(new BouncyCastleProvider());

            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            keyPairGen.initialize(2048, new SecureRandom());
            pair = keyPairGen.generateKeyPair();
            byte[] pub = pair.getPublic().getEncoded();
            byte[] priv = pair.getPrivate().getEncoded();
            SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.getInstance(pub);

            issuer = new X500Name("CN=CA");
            subject = issuer;

            X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
                  issuer,       //issuer (CA)
                  serialNumber,
                  startDate, expiryDate,
                  subject,      //subject
                  pubInfo);

            //signature for sig
            ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSA").build(pair.getPrivate());
            X509CertificateHolder certHolder = certBuilder.build(sigGen);
            X509Certificate caCert = new JcaX509CertificateConverter().getCertificate(certHolder);

            X509Certificate[] chain = new X509Certificate[3];
            chain[2] = caCert;

            KeyStore store;
            try {
                store = KeyStore.getInstance(storeType);
                store.load(null,null);
            store.setKeyEntry("CA-Key", priv, chain);  
            store.store(new FileOutputStream("public.p12"), null);

            } catch (Exception e) {
                e.printStackTrace();
            } 
然后我得到一个错误:

java.security.KeyStoreException: Private key is not stored as PKCS#8 EncryptedPrivateKeyInfo: java.io.IOException: overrun, bytes = 1194
    at sun.security.pkcs12.PKCS12KeyStore.engineSetKeyEntry(PKCS12KeyStore.java:687)
    at java.security.KeyStore.setKeyEntry(KeyStore.java:1174)
    at storeKeys.saveKeys(storeKeys.java:95)
    at storeKeys.main(storeKeys.java:146)
Caused by: java.io.IOException: overrun, bytes = 1194

如何将私钥加密为正确的格式?我在哪里可以给密钥库提供保存密钥的路径?

如果您看到该方法的java文档,它会说:

将给定密钥(已受保护)分配给给定别名

如果受保护密钥的类型为java.security.PrivateKey,则它必须附带一个证书链,以证明相应的公钥如果基础密钥库实现是jks类型,则密钥必须按照PKCS#8标准中的定义编码为EncryptedPrivateKeyInfo。

它说的是JKS,但看起来它也希望PKCS12使用加密的私钥格式

因此,不能只传入私钥字节数组

为了让事情变得更简单,您可以这样做:

PrivateKeyEntry privateKeyEntry = new PrivateKeyEntry(pair.getPrivate(), chain);
store.setEntry("CA-Key", privateKeyEntry, new KeyStore.PasswordProtection(storePassword.toCharArray()));
keystore.store(..)
方法中,第一个参数是keystore路径。第二个参数是密钥库的密码

所以你可以这样做:

store.store(new FileOutputStream(new File(storePath)), storePassword.toCharArray());

在java.security.KeyStore$PrivateKeyEntry.(KeyStore.java:532)的java.security.KeyStore$PrivateKeyEntry.(KeyStore.java:491)的线程“main”java.lang.NullPointerException中给出了异常,这可能是因为您的证书链。您只有1个自签名证书,您将其存储在
变量中。但您定义的大小为3,并将自签名证书存储在数组的第3个位置。所以前2个是空的。尝试将大小更改为1,并将自签名证书放在第0个位置,然后再次尝试。我得到了一个文件output.p12,但其中没有任何内容,如何将priv key存储到该文件中?@nolags如果上述代码毫无例外地执行,您应该保存它。有错误吗?没有错误!我没有给FileOutputStream内容?!