Skip to content

Instantly share code, notes, and snippets.

@Gsealy
Created October 27, 2018 03:42
Show Gist options
  • Save Gsealy/30704c7c098f3f8620a065cb61fd68bb to your computer and use it in GitHub Desktop.
Save Gsealy/30704c7c098f3f8620a065cb61fd68bb to your computer and use it in GitHub Desktop.
PKCS12.java
package cn.com.infosec.PKCS12;
import java.io.ByteArrayInputStream;
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.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.cert.X509CRLHolder;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX500NameUtil;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.crypto.engines.RC2Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS12PfxPdu;
import org.bouncycastle.pkcs.PKCS12PfxPduBuilder;
import org.bouncycastle.pkcs.PKCS12SafeBag;
import org.bouncycastle.pkcs.PKCS12SafeBagBuilder;
import org.bouncycastle.pkcs.bc.BcPKCS12MacCalculatorBuilder;
import org.bouncycastle.pkcs.bc.BcPKCS12PBEOutputEncryptorBuilder;
import org.bouncycastle.pkcs.jcajce.JcaPKCS12SafeBagBuilder;
public class PKCS12 {
private static KeyPair keyPair;
private static KeyPair CAkeyPair;
private static String BC = "BC";
private static char[] passwd = {'1', '2', '3', '4', '5', '6'};
private static String certPath = "d:/test.pfx";
private static String issuer =
"C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
static {
try {
// Client 秘钥对
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
keyPair = kpg.generateKeyPair();
// CA 秘钥对
KeyPairGenerator kpca = KeyPairGenerator.getInstance("RSA");
kpca.initialize(1024);
CAkeyPair = kpca.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public static void genPkx() throws Exception {
PrivateKey privKey = keyPair.getPrivate();
PublicKey pubKey = keyPair.getPublic();
// 创建证书链
X509Certificate[] chain = createCertChain(pubKey);
// 创建Pfx
PKCS12PfxPdu pfx = createPfx(privKey, pubKey, chain);
//
// now try reading our object
//
KeyStore store = KeyStore.getInstance("PKCS12", "BC");
// initialize keystore with pfx
store.load(new ByteArrayInputStream(pfx.toASN1Structure().getEncoded()), passwd);
// store.setKeyEntry("Eric's Key", privKey, passwd, chain);
FileOutputStream fout = new FileOutputStream(certPath);
store.store(fout, passwd);
fout.close();
}
private static X509Certificate[] createCertChain(PublicKey pubKey) throws Exception {
PrivateKey caPrivKey = CAkeyPair.getPrivate();
PublicKey caPubKey = CAkeyPair.getPublic();
PrivateKey intPrivKey = keyPair.getPrivate();
PublicKey intPubKey = keyPair.getPublic();
X509Certificate[] chain = new X509Certificate[3];
chain[2] = createMasterCert(caPubKey, caPrivKey);
chain[1] = createIntermediateCert(intPubKey, caPrivKey, chain[2]);
chain[0] = createCert(pubKey, intPrivKey, intPubKey);
return chain;
}
public static X509Certificate createMasterCert(PublicKey pubKey, PrivateKey privKey)
throws Exception {
//
// signers name
//
String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
//
// subjects name - the same as we are self signed.
//
String subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
//
// create the certificate - version 3
//
X509v3CertificateBuilder v1CertBuilder =
new JcaX509v3CertificateBuilder(new X500Name(issuer), BigInteger.valueOf(1),
new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30),
new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30)),
new X500Name(subject), pubKey);
// sign with GM
X509CertificateHolder cert = v1CertBuilder
.build(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(privKey));
return new JcaX509CertificateConverter().setProvider(BC).getCertificate(cert);
}
public static X509Certificate createIntermediateCert(PublicKey pubKey, PrivateKey caPrivKey,
X509Certificate caCert) throws Exception {
//
// subject name builder.
//
X500NameBuilder subjectBuilder = new X500NameBuilder(BCStyle.INSTANCE);
subjectBuilder.addRDN(BCStyle.C, "AU");
subjectBuilder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
subjectBuilder.addRDN(BCStyle.OU, "Bouncy Intermediate Certificate");
subjectBuilder.addRDN(BCStyle.EmailAddress, "feedback-crypto@bouncycastle.org");
//
// create the certificate - version 3
//
X509v3CertificateBuilder v3CertBuilder = new JcaX509v3CertificateBuilder(
JcaX500NameUtil.getIssuer(caCert), BigInteger.valueOf(2),
new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30),
new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30)),
subjectBuilder.build(), pubKey);
//
// extensions
//
JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
v3CertBuilder.addExtension(Extension.subjectKeyIdentifier, false,
utils.createSubjectKeyIdentifier(pubKey));
v3CertBuilder.addExtension(Extension.authorityKeyIdentifier, false,
utils.createAuthorityKeyIdentifier(caCert));
v3CertBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
X509CertificateHolder cert = v3CertBuilder
.build(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(caPrivKey));
return new JcaX509CertificateConverter().setProvider(BC).getCertificate(cert);
}
public static X509Certificate createCert(PublicKey pubKey, PrivateKey caPrivKey,
PublicKey caPubKey) throws Exception {
//
// signer name builder.
//
X500NameBuilder issuerBuilder = new X500NameBuilder(BCStyle.INSTANCE);
issuerBuilder.addRDN(BCStyle.C, "AU");
issuerBuilder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
issuerBuilder.addRDN(BCStyle.OU, "Bouncy Intermediate Certificate");
issuerBuilder.addRDN(BCStyle.EmailAddress, "feedback-crypto@bouncycastle.org");
//
// subject name builder
//
X500NameBuilder subjectBuilder = new X500NameBuilder(BCStyle.INSTANCE);
subjectBuilder.addRDN(BCStyle.C, "AU");
subjectBuilder.addRDN(BCStyle.O, "The Legion of the Bouncy Castle");
subjectBuilder.addRDN(BCStyle.L, "Melbourne");
subjectBuilder.addRDN(BCStyle.CN, "Eric H. Echidna");
subjectBuilder.addRDN(BCStyle.EmailAddress, "feedback-crypto@bouncycastle.org");
//
// create the certificate - version 3
//
X509v3CertificateBuilder v3CertBuilder =
new JcaX509v3CertificateBuilder(issuerBuilder.build(), BigInteger.valueOf(3),
new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30),
new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30)),
subjectBuilder.build(), pubKey);
//
// add the extensions
//
JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils();
v3CertBuilder.addExtension(Extension.subjectKeyIdentifier, false,
utils.createSubjectKeyIdentifier(pubKey));
v3CertBuilder.addExtension(Extension.authorityKeyIdentifier, false,
utils.createAuthorityKeyIdentifier(caPubKey));
X509CertificateHolder cert = v3CertBuilder
.build(new JcaContentSignerBuilder("SHA1withRSA").setProvider(BC).build(caPrivKey));
return new JcaX509CertificateConverter().setProvider(BC).getCertificate(cert);
}
private static PKCS12PfxPdu createPfx(PrivateKey privKey, PublicKey pubKey,
X509Certificate[] chain) throws Exception {
JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
PKCS12SafeBagBuilder taCertBagBuilder = new JcaPKCS12SafeBagBuilder(chain[2]);
// Cert Bag
// CA ta
taCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("Bouncy Primary Certificate"));
PKCS12SafeBagBuilder caCertBagBuilder = new JcaPKCS12SafeBagBuilder(chain[1]);
// Inter ca
caCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("Bouncy Intermediate Certificate"));
PKCS12SafeBagBuilder eeCertBagBuilder = new JcaPKCS12SafeBagBuilder(chain[0]);
// user ee
eeCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("Eric's Key"));
eeCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
extUtils.createSubjectKeyIdentifier(pubKey));
// TODO
PKCS12SafeBagBuilder keyBagBuilder = new JcaPKCS12SafeBagBuilder(privKey,
new BcPKCS12PBEOutputEncryptorBuilder(
PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC,
new CBCBlockCipher(new DESedeEngine())).build(passwd));
keyBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("Eric's Key"));
keyBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
extUtils.createSubjectKeyIdentifier(pubKey));
// CRL Bag
X509CRL crl = CrlBag();
X509CRLHolder acrl = new X509CRLHolder(crl.getEncoded());
PKCS12SafeBagBuilder crlBagBuilder = new PKCS12SafeBagBuilder(acrl.toASN1Structure());
crlBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("Eric's Key"));
crlBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
extUtils.createSubjectKeyIdentifier(pubKey));
// construct the actual key store
//
PKCS12PfxPduBuilder pfxPduBuilder = new PKCS12PfxPduBuilder();
PKCS12SafeBag[] certs = new PKCS12SafeBag[3];
certs[0] = eeCertBagBuilder.build();
certs[1] = caCertBagBuilder.build();
certs[2] = taCertBagBuilder.build();
// TODO
pfxPduBuilder.addEncryptedData(new BcPKCS12PBEOutputEncryptorBuilder(
PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC2_CBC,
new CBCBlockCipher(new RC2Engine())).build(passwd), certs);
pfxPduBuilder.addData(keyBagBuilder.build());
pfxPduBuilder.addData(crlBagBuilder.build());
return pfxPduBuilder.build(new BcPKCS12MacCalculatorBuilder(), passwd);
}
public static X509CRL CrlBag() throws Exception {
FileInputStream fis = new FileInputStream("D:\\GIAG2.crl");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509CRL aCrl = (X509CRL) cf.generateCRL(fis);
return aCrl;
}
public static void main(String[] args) throws Exception {
BouncyCastleProvider bcp = new BouncyCastleProvider();
Security.addProvider(bcp);
genPkx();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment