将证书加载到KeyStore(JAVA) [英] Load certificate to KeyStore (JAVA)

查看:172
本文介绍了将证书加载到KeyStore(JAVA)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在将证书加载到密钥存储区时遇到问题.我可以使用以下命令在控制台中创建该证书: 我想出了如何使用privateKey.key加载cloudCA.pem,但是我找不到在其中添加rootCA.pem的方法.这是我当前的代码.感谢帮助.

I have problem with loading certifiacate to key store. I can create that certificate in console with this command openssl pkcs12 -export -out cloudCA.p12 -inkey Cloud\ privateLey.key -in cloudCa.pem -certfile rootCa.pem -name "cloudCA" I figured out how to load cloudCA.pem with privateKey.key but I can't find a way how to add there rootCA.pem. This is my current code. Thank 's for help.

//Regular patterns for certificate.
private static final Pattern CERT_PATTERN = Pattern.compile(
        "-+BEGIN\\s+.*CERTIFICATE[^-]*-+(?:\\s|\\r|\\n)+" + // Header
                "([a-z0-9+/=\\r\\n]+)" +                    // Base64 text
                "-+END\\s+.*CERTIFICATE[^-]*-+",            // Footer
        CASE_INSENSITIVE);

private static final Pattern KEY_PATTERN = Pattern.compile(
        "-+BEGIN\\s+.*PRIVATE\\s+KEY[^-]*-+(?:\\s|\\r|\\n)+" + // Header
                "([a-z0-9+/=\\r\\n]+)" +                       // Base64 text
                "-+END\\s+.*PRIVATE\\s+KEY[^-]*-+",            // Footer
        CASE_INSENSITIVE);


public static KeyStore loadKeyStore(String certificate, String privateKey, Optional<String> keyPassword)
        throws IOException, GeneralSecurityException {

    List<X509Certificate> certificateChain = readCertificateChain(certificate);
    if (certificateChain.isEmpty()) {
        throw new CertificateException("Certificate file string does not contain any certificates: ");
    }

    //Load and customize key string to byte array.
    byte[] data = Base64.getDecoder().decode(privateKey.replace("\n","")
            .replace("-----BEGIN RSA PRIVATE KEY-----", "")
            .replace("-----END RSA PRIVATE KEY-----", "")
            .replace(" ", ""));

    /* Add PKCS#8 formatting */
    ASN1EncodableVector v = new ASN1EncodableVector();
    v.add(new ASN1Integer(0));
    ASN1EncodableVector v2 = new ASN1EncodableVector();
    v2.add(new ASN1ObjectIdentifier(PKCSObjectIdentifiers.rsaEncryption.getId()));
    v2.add(DERNull.INSTANCE);
    v.add(new DERSequence(v2));
    v.add(new DEROctetString(data));
    ASN1Sequence seq = new DERSequence(v);
    byte[] privKey = seq.getEncoded("DER");

    PKCS8EncodedKeySpec spec = new  PKCS8EncodedKeySpec(privKey);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    PrivateKey key = fact.generatePrivate(spec);

    KeyStore keyStore = KeyStore.getInstance("JKS");
    keyStore.load(null, null);
    keyStore.setKeyEntry("CloudCA", key, keyPassword.orElse("").toCharArray(), certificateChain.stream().toArray(Certificate[]::new));
    return keyStore;
}


private static List<X509Certificate> readCertificateChain(String contents) throws GeneralSecurityException {

    Matcher matcher = CERT_PATTERN.matcher(contents);
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    List<X509Certificate> certificates = new ArrayList<>();

    int start = 0;
    while (matcher.find(start)) {
        byte[] buffer = Base64.getMimeDecoder().decode(matcher.group(1).getBytes(US_ASCII));
        certificates.add((X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(buffer)));
        start = matcher.end();
    }

    return certificates;
}

推荐答案

首先,使用openssl pkcs12 -export创建的PKCS12文件已经已经是Java密钥库;尽管密钥库的Java版本低于9 default 的JKS格式,它们也支持PKCS12,而j9 up现在默认为PKCS12.因此,您只需要使用PKCS12密钥库就可以了.但是SO是关于编程的,因此根本不需要做任何事情的解决方案可能就没必要了:)

First, your PKCS12 file created with openssl pkcs12 -export is already a Java keystore; although Java versions below 9 default to JKS format for keystores they also support PKCS12, and j9 up now defaults to PKCS12. So you could just use the PKCS12 keystore and you're done. But SO is about programming so a solution that doesn't require doing anything at all might be off-topic :)

如果您想要(或以某种方式需要)自己构建密钥库,并且在一个文件中拥有实体证书(如果顾名思义,实际上是一个从属CA,并且直接在根目录下),而在另一个文件中拥有根证书,您可以阅读其中的每个内容并形成链接,例如:

If you want (or somehow need) to build the keystore yourself, and you have the entity cert in one file (if really a subordinate CA as your name suggests, and directly under the root) and the root cert in another, you can read each of them in and form the chain, like:

// read privatekey, reformat to PKCS8 and process-in as you do now

CertificateFactory fact = CertificateFactory.getInstance("X.509");
InputStream file1 = new FileInputStream("mycert.pem"), file2 = new FileInputStream("rootcert.pem");
Certificate[] chain = { fact.generateCertificate(file1), fact.generateCertificate(file2) };
file1.close(); file2.close(); // or use try-with-resources
// if already in memory use ByteArrayInputStream's instead, 
// and maybe don't bother closing

// basically unchanged
KeyStore keyStore = KeyStore.getInstance("JKS"); // or maybe "PKCS12" ?
keyStore.load(null, null);
keyStore.setKeyEntry("name", key, (keypass), chain);

// either use this keystore as is, or store it (to a file, 
// or maybe somewhere else like a database) for later use

请注意,您不需要删除PEM标头/尾部并将自己转换为base64即可,CertificateFactory自上世纪以来一直能够读取PEM.尽管如果您的PEM文件在PEM块之前包含额外的注释"信息(OpenSSL经常创建的文件),但是您需要使用相当新的Java版本(IIRC j6或j7)来处理那个.

Note you don't need to remove the PEM header/trailer and convert base64 to binary yourself, CertificateFactory has been able to read PEM since last century. Although if your PEM files contain extra 'comment' info before the PEM block, which files created by OpenSSL often do, you need a fairly recent Java version (IIRC j6 or maybe j7) to handle that.

或者,如果将证书(在文件或内存中)连接起来,则可以使用CertificateFactory.generateCertificates(注意s)将它们都读取为Collection,然后将其转换为数组.同样,这已经处理了PEM,因此您不必解析和转换它.请注意,您可以将CollectionList(如上面的代码中一样)直接转换为数组,而无需先通过Stream.

Alternatively if you concatenate the certs -- either in a file, or in memory -- you could use CertificateFactory.generateCertificates (note the s) to read both of them to a Collection which you then convert to an array. Again this handles PEM already so you don't have to parse and convert it. Note you can convert either a Collection or a List (as in your code above) to an array directly, without needing to go through a Stream first.

这篇关于将证书加载到KeyStore(JAVA)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆