【问题标题】:Java p12 Generation from a existing keys从现有密钥生成 Java p12
【发布时间】:2018-06-11 13:10:46
【问题描述】:

我正在用 Java 编写一个使用 Crt 参数生成 RSA 密钥的程序。我可以将密钥导出到 .pem 文件中,但我需要将其导出到 pkcs12 文件中。我如何在 Java 中做到这一点?

【问题讨论】:

  • 欢迎来到 SO!这不是一个指导网站。如果您发布尝试导出 pkcs12 文件的尝试,其他人可以帮助您!

标签: java cryptography rsa


【解决方案1】:

Java 通过KeyStore.getInstance("PKCS12") 包含对 PKCS#12 密钥存储的本机支持。但是,通常密钥存储要求您提供匹配的私钥/证书 对。仅提供公钥而不是证书是不够的。您必须创建一个证书,例如 自签名证书 才能使用 PKCS#12 密钥存储提供程序。

我尝试使用匿名类型创建自己的 Certificate 实例,但 PKCS#12 密钥库似乎只允许 X.509 证书(但它只会在您 存储时告诉您 em> 密钥存储,即它不是快速失败


这里有一些代码用于创建自签名证书并存储私钥和生成的自签名证书:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;

import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.CertIOException;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.util.encoders.Hex;

public class StoreRSAKeyPairInPKCS12 {

    public static void main(String[] args) throws Exception {

        // --- generate a key pair (you did this already it seems)
        KeyPairGenerator rsaGen = KeyPairGenerator.getInstance("RSA");
        final KeyPair pair = rsaGen.generateKeyPair();

        // --- create the self signed cert
        Certificate cert = createSelfSigned(pair);

        // --- create a new pkcs12 key store in memory
        KeyStore pkcs12 = KeyStore.getInstance("PKCS12");
        pkcs12.load(null, null);

        // --- create entry in PKCS12
        pkcs12.setKeyEntry("privatekeyalias", pair.getPrivate(), "entrypassphrase".toCharArray(), new Certificate[] {cert});

        // --- store PKCS#12 as file
        try (FileOutputStream p12 = new FileOutputStream("mystore.p12")) {
            pkcs12.store(p12, "p12passphrase".toCharArray());
        }

        // --- read PKCS#12 as file
        KeyStore testp12 = KeyStore.getInstance("PKCS12");
        try (FileInputStream p12 = new FileInputStream("mystore.p12")) {
            testp12.load(p12, "p12passphrase".toCharArray());
        }

        // --- retrieve private key
        System.out.println(Hex.toHexString(testp12.getKey("privatekeyalias", "entrypassphrase".toCharArray()).getEncoded()));
    }

    private static X509Certificate createSelfSigned(KeyPair pair) throws OperatorCreationException, CertIOException, CertificateException {
        X500Name dnName = new X500Name("CN=publickeystorageonly");
        BigInteger certSerialNumber = BigInteger.ONE;

        Date startDate = new Date(); // now

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.add(Calendar.YEAR, 1);
        Date endDate = calendar.getTime();

        ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(pair.getPrivate());
        JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(dnName, certSerialNumber, startDate, endDate, dnName, pair.getPublic());

        return new JcaX509CertificateConverter().getCertificate(certBuilder.build(contentSigner));
    }

}

您至少需要 Bouncy Castle 的 PKIX 库 (bcpkix-jdk15on.jar),可能还需要 Bouncy Castle 提供者的库。 不需要安装 Bouncy Castle 提供程序

【讨论】:

  • 我之前的答案包含一个指向创建自签名证书的旧答案的链接,但它非常垃圾并且使用了旧的 Bouncy Castle 实现,所以我不得不从另一个答案重构代码。跨度>
  • 其他答案可以在here找到。
  • 非常感谢您的回答,它对我帮助很大,这正是我所需要的 ;) ;)
  • 在 openssl 中,我可以导出 p12 文件而没有证书,选项 -nocerts 可以用 Java 做到吗?
猜你喜欢
  • 2020-05-01
  • 1970-01-01
  • 2019-06-11
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
  • 2012-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多