Created
October 27, 2018 03:42
-
-
Save Gsealy/30704c7c098f3f8620a065cb61fd68bb to your computer and use it in GitHub Desktop.
PKCS12.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, "[email protected]"); | |
// | |
// 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, "[email protected]"); | |
// | |
// 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, "[email protected]"); | |
// | |
// 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