java - 将 .p12 文件返回给客户端而不创建 keystore 文件

标签 java ssl keystore pfx pkcs#12

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

创建根证书的简化代码:

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

主类如下所示:

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

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

提前致谢!

最佳答案

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

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

关于java - 将 .p12 文件返回给客户端而不创建 keystore 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33091424/

相关文章:

android - 使用 Android 硬件支持的 KeyStore

java - keystore 更改密码

java - Apache CXF 客户端在测试需要服务器名称指示 (SNI) 的服务器时出错

java - 从Keystore获取私钥

java - 使用方法调用合并两个数组

javascript - 为什么 Cesium 查看器在我添加时不显示模型?

java - 尝试通知线程已使用 Exchanger 创建对象会导致两个线程都被锁定

Java 放置俄罗斯方 block 像 block 算法

c++ - Boost SSL 编译失败

ssl - 通配符证书名称的格式是什么?