gpt4 book ai didi

java - 如何使用Java代码将证书和私钥导出为单个文件?

转载 作者:行者123 更新时间:2023-11-29 07:24:39 63 4
gpt4 key购买 nike

我的要求是将证书和私钥结合在一起,然后使用PEMwriter导出文件。

我使用bouncycastle生成私钥和csr。然后,我将CSR提交给CA并获得了证书。
以下代码用于生成密钥对

KeyPair idPair = KeyPairGenerator.getInstance("RSA").genKeyPair();
PublicKey publicKey = idPair.getPublic();
PrivateKey privkey = idPair.getPrivate();


以下代码用于接收证书并将其导出到.cer文件。

CertStore store = response.getCertStore();
Collection<? extends Certificate> certs = store
.getCertificates(null);
Certificate[] chain = new Certificate[certs.size()];

int i = 0;
for (Certificate certificate : certs) {
chain[i++] = certificate;
}

FileOutputStream os = new FileOutputStream("cert.cer");
os.write("-----BEGIN CERTIFICATE-----\n".getBytes("US-ASCII"));
os.write(Base64.encodeBase64(chain[0].getEncoded(), true));
os.write("-----END CERTIFICATE-----\n".getBytes("US-ASCII"));
os.close();


现在,我的目标是打开导出的文件时,必须提示我输入密码以安装/查看证书。我对这部分真的很困惑。以前我将密码添加到密钥库中,如下所示

KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(null, null);

keyStore.setKeyEntry("mykey", (Key) keyPair.getPrivate(), "Password1!".toCharArray(), certz);

ByteArrayOutputStream bout = new ByteArrayOutputStream();
keyStore.store(bout, "Password1!".toCharArray()); // this is the password to open the .p12

byte[] keystore = bout.toByteArray();
bout.close();


但是,现在,我需要使用密码保护证书。这有可能吗?如果是这样,文件扩展名是什么?并且请在编码部分(PemWriter)中指导我。
谢谢

最佳答案

以下代码用于接收证书并将其导出到.cer文件。


        CertStore store = response.getCertStore();
Collection<? extends Certificate> certs = store
.getCertificates(null);
Certificate[] chain = new Certificate[certs.size()];
int i = 0;
for (Certificate certificate : certs) {
chain[i++] = certificate;
}


旁白:您不需要该循环即可将 Collection转换为数组,只需执行一次 .toArray (new T[optionally_correct_size])调用即可。另一方面,由于仅使用第一个元素,因此根本不需要数组,只需 Collection<T>.iterator().next()

更实质性地,另一方面,使用私钥完成的许多(但绝对不是全部)操作也需要完整的证书链,而不仅仅是叶子/终端实体证书,才能正常工作。例如,某些签名者可以在没有链的情况下计算签名,但是在某些情况下或某些情况下,签名无法得到验证,因此将被接收者拒绝。由于您不知道如何使用导出文件以及使用导出文件的方式和用途,因此无法提供任何建议。而且,如果需要完整的链,那么您是否可以只使用一系列单独的/单独的PEM证书还是需要其他内容,也会有所不同。

我不知道您在使用什么 Base64编码器;该签名与BouncyCastle签名不匹配。我希望它能正确产生换行符。 PEM格式不仅是BEGIN行,base64,END行;它是BEGIN行,带换行符的base64,END行。某些软件即使在没有断线的情况下也可以正常运行,但是某些软件有时会失败。请参见 RFC 7468 sec 2 near the end


  现在,我的目标是打开导出的文件时,必须提示我输入密码以安装/查看证书。 ...但是,现在,我需要使用密码保护证书。这有可能吗?


您需要区分私钥和证书。尽管以重要的方式关联,但是它们是不同的事情,私钥被设计为私有/秘密,而证书被设计为公开。特别是,PEM格式证书未加密,因此任何人都可以查看该证书并将其用于公钥操作(加密或验证),或者通过其他方式使用该证书。

但是要执行私钥操作(解密或签名),您需要私钥(通常如上所述链接到证书或链),并且私钥可以(至少)以两种不同的方式以常规PEM格式进行密码加密,因此要求密码“打开”它。早在1990年代,OpenSSL便事实上定义了一种PEM加密方案,该方案可用于其几种“传统”或“传统”私钥格式,每种格式各不相同,并在BEGIN行中以PEM类型指示。 -----BEGIN RSA PRIVATE KEY----------BEGIN DSA PRIVATE KEY----------BEGIN EC PRIVATE KEY-----等。稍后, PKCS8为所有算法定义了通用私钥格式,包括Java crypto(JCA)在内的许多其他软件都使用了该算法,包括由 -----BEGIN ENCRYPTED PRIVATE KEY-----指定的加密变体(注意没有算法名称)。 PKCS8版本(仅)已由 RFC7468 sec 11正式发布。 (对于OpenSSH,PuTTY和PGP,私钥还有其他与PEM类似的格式,但是它们都不使用X.509型证书。尽管GnuPG现在既实现了PGP和S / MIME,也使用了X .509 / PKIX(用于S / MIME)。SO上有许多现有的Q,如果您对此感兴趣,还有一些关于security.SX或crypto.SX的Q。) bcpkix实现OpenSSL传统格式和PKCS8格式( s)。 (没有BouncyCastle的仅Java便实现了未加密的PKCS8。)

同样,“旧式” Java密钥库(JKS和JCEKS)使用密码对私钥(而不是证书)进行加密。 PKCS12标准实际上非常灵活(而且很复杂),但是通常实现(包括您的BC-keystore示例)对私钥使用强密码加密,对证书使用很弱的易破解密码加密;我从不十分清楚为什么,因为这样在不提供任何安全性好处的情况下不太方便。


  如果是这样,文件扩展名是什么?


这完全取决于您,或者这些文件用于谁(如果有的话)。没有标准要求文件扩展名匹配文件内容,反之亦然,尽管人们通常这样做是因为它更方便。正式地, .cer应该是DER证书,并且 RFC7468 sec 5.3建议将 .crt用作PEM证书。如果将密钥写到单独的文件中,使用 .key.pem似乎很常见,但是我知道没有任何标准(当然也没有IANA注册)来指定此密钥。 (RFC5958为未加密的DER PKCS8实际上注册了.p8,而RFC8351却在未指定任何扩展名的情况下注册了DER PKCS8加密。)如果您将密钥和证书写入同一文件(PEM格式支持但并非所有程序都支持),我除了 .pem以外,还没有见过其他常规做法。

因此,终于可以解决您的问题了:-)
假设您在提供程序列表(和类路径)中有BC提供程序,在类路径中有bcpkix,在 PrivateKey中有一个 kv对象:

import org.bouncycastle.openssl.PKCS8Generator;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;
import org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder;
import org.bouncycastle.util.io.pem.PemWriter;

// for the OpenSSL legacy form
JcaPEMWriter x = new JcaPEMWriter (new OutputStreamWriter(System.out)); // or whatever
x.writeObject(kv, new JcePEMEncryptorBuilder("DES-EDE3-CBC").build("password".toCharArray()) );
// can substitute AES-{128,192,256}-CBC if desired, for more see source
x.close(); // or flush to keep underlying writer/stream

// for the PKCS8 form
PemWriter y = new PemWriter (new OutputStreamWriter(System.out)); // or whatever
y.writeObject(new JcaPKCS8Generator (kv, new JceOpenSSLPKCS8EncryptorBuilder(
PKCS8Generator.DES3_CBC).setPasssword("password".toCharArray()).build() ) );
// or AES_{128,192,256}_CBC, others will use PBES1 which is deprecated
y.close(); // or flush to keep underlying writer/stream

关于java - 如何使用Java代码将证书和私钥导出为单个文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56287009/

63 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com