簡體   English   中英

如何使用Java代碼將證書和私鑰導出為單個文件?

[英]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 / MIMEbcpkix上存在許多現有的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM