Return .p12 文件到客户端而不创建密钥库文件

Return .p12 file to client without creating keystore file

有没有什么方法可以 return 将扩展名为 .p12 的文件(base64 编码的字符串,稍后在客户端解码并以 .p12 扩展名保存)发送到客户端,而不将其存储到 PKCS12 密钥库?我有用于创建根证书、客户端证书和将 keyentry 设置为 PKCS12 密钥库的代码,但我不想在文件系统上有 .p12 文件,只是为了生成它并将其 return 发送给客户端。谢谢!

创建根证书的简化代码:

public static void createRootCertificate(PublicKey pubKey, PrivateKey privKey) {    
    certGen.setSerialNumber(...);
    certGen.setIssuerDN(...);
    certGen.setNotBefore(...);
    certGen.setNotAfter(...);
    certGen.setSubjectDN(...);
    certGen.setPublicKey(pubKey);
    certGen.setSignatureAlgorithm("SHA1WithRSA");

    // add extensions, key identifier, etc.

    X509Certificate cert = certGen.generateX509Certificate(privKey);
    cert.checkValidity(new Date());
    cert.verify(pubKey);
}

根证书及其私钥创建后保存到受信任的存储区。

然后,在生成客户端证书的服务中,我从可信存储中读取根证书并生成客户端证书:

public static Certificate createClientCertificate(PublicKey pubKey) {   

    PrivateKey rootPrivateKey = ... //read key from trusted store
    X509Certificate rootCertificate = ... //read certificate from trusted store

    certGen.setSerialNumber(...);
    certGen.setIssuerDN(...); // rootCertificate.getIssuerDN ...
    certGen.setNotBefore(...);
    certGen.setNotAfter(...);
    certGen.setSubjectDN(...);
    certGen.setPublicKey(pubKey);
    certGen.setSignatureAlgorithm("SHA1WithRSA");

    // add extensions, issuer key, etc.

    X509Certificate cert = certGen.generateX509Certificate(rootPrivateKey);
    cert.checkValidity(new Date());
    cert.verify(rootCertificate.getPublicKey(););

    return cert;
}

主要 class 看起来像这样:

public static void main(String[] args) {        
    // assume I have all needed keys generated
    createRootCertificate(rootPubKey, rootPrivKey);
    X509Certificate clientCertificate = createClientCertificate(client1PubKey);

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

    store.load(null, null);

    store.setKeyEntry("Client1_Key", client1PrivKey, passwd, new Certificate[]{clientCertificate});    
    FileOutputStream fOut = new FileOutputStream("client1.p12");   
    store.store(fOut, passwd);
}

在上面的代码之后,我正在读取 client1.p12 并创建该文件的 Base64 编码响应。当我在客户端解码响应并使用 .p12 扩展名保存时一切正常,我可以将其导入浏览器。这可以在不将其存储到文件的情况下完成吗?

我试过:

store.setKeyEntry("Client1_Key", client1PrivKey, passwd, new Certificate[]{clientCertificate}); 

之后:

Key key = store.getKey("Client1_Key", passwd);

但是当对密钥变量进行编码、发送到客户端而不是对其进行解码并以 .p12 扩展名保存时,浏览器会提示文件无效或已损坏。

提前致谢!

只需使用 ByteArrayOutputStream 而不是 FileOutputStream 来存储 p12:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
store.store(baos, passwd);
byte[] p12Bytes = baos.toByteArray();
String p12Base64 = new String(Base64.encode(p12Bytes));