[英]How to export Certificate and private key as a single file using java code?
我的要求是將證書和私鑰結合在一起,然后使用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行, 帶有換行符的END64 ,END行。 某些軟件即使在沒有斷線的情況下也可以正常工作,但是某些軟件有時會失敗。 參見RFC 7468第2秒即將結束 。
現在,我的目標是打開導出的文件時,必須提示我輸入密碼以安裝/查看證書。 ...但是,現在,我需要使用密碼保護證書。 這有可能嗎?
您需要區分私鑰和證書。 盡管以重要的方式關聯,但是它們是不同的事情,私鑰被設計為私有/秘密,而證書被設計為公開。 特別是,PEM格式證書未加密,因此任何人都可以查看該證書並將其用於公鑰操作(加密或驗證),或者以其他方式使用該證書。
但是要執行私鑰操作(解密或簽名),您需要私鑰(通常如上所述鏈接到證書或鏈),並且私鑰可以 (至少)以兩種不同的方式以常規PEM格式進行密碼加密,因此要求密碼“打開”它。 早在1990年代,OpenSSL便事實上定義了一種PEM加密方案,該方案可用於其幾種“傳統”或“傳統”私鑰格式,每種格式各不相同,並在BEGIN行中以PEM類型表示。 -----BEGIN RSA PRIVATE KEY-----
, -----BEGIN DSA PRIVATE KEY-----
-----BEGIN RSA PRIVATE KEY-----
-----BEGIN DSA PRIVATE KEY-----
, -----BEGIN EC PRIVATE KEY-----
私鑰 -----BEGIN EC PRIVATE KEY-----
等。 稍后定義PKCS8 所有算法的通用私鑰格式,包括Java crypto(JCA)在內的許多其他軟件都使用該格式,包括由-----BEGIN ENCRYPTED PRIVATE KEY-----
指定的加密變體(請注意沒有算法名稱)。 RFC7468 sec 11已正式宣布PKCS8版本(僅)。 (對於OpenSSH,PuTTY和PGP,私鑰還有其他與PEM類似的格式,但是它們都不使用X.509型證書。盡管GnuPG現在既實現了PGP和S / MIME,也使用了X .509 / PKIX( 用於S / MIME ) bcpkix
上存在許多現有的Q,如果您對此感興趣,則還有一些關於security.SX或crypto.SX的Q。) bcpkix
實現了OpenSSL-legacy形式和 PKCS8形式。 。 (沒有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,而kv
有一個PrivateKey
對象:
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.security代碼,而無需PemWriter)。
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, null);
Certificate cert = getX509Cert(); // load certificate
ks.setCertificateEntry("myCertAlias", cert);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(PATH + "newKeyStore.p12");
char[] password = PASSWORD_.toCharArray();
ks.store(fos, password);
} finally {
if (fos != null) {
fos.close();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.