From 2b976f5364cfdbc37d3086019d93483c983eb80b Mon Sep 17 00:00:00 2001 From: David Hook Date: Fri, 31 May 2013 17:07:45 +1000 Subject: initial reshuffle --- .../org/bouncycastle/pkcs/PKCS12PfxPduBuilder.java | 179 +++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 pkix/src/main/java/org/bouncycastle/pkcs/PKCS12PfxPduBuilder.java (limited to 'pkix/src/main/java/org/bouncycastle/pkcs/PKCS12PfxPduBuilder.java') diff --git a/pkix/src/main/java/org/bouncycastle/pkcs/PKCS12PfxPduBuilder.java b/pkix/src/main/java/org/bouncycastle/pkcs/PKCS12PfxPduBuilder.java new file mode 100644 index 00000000..563ca048 --- /dev/null +++ b/pkix/src/main/java/org/bouncycastle/pkcs/PKCS12PfxPduBuilder.java @@ -0,0 +1,179 @@ +package org.bouncycastle.pkcs; + +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DLSequence; +import org.bouncycastle.asn1.pkcs.AuthenticatedSafe; +import org.bouncycastle.asn1.pkcs.ContentInfo; +import org.bouncycastle.asn1.pkcs.MacData; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.Pfx; +import org.bouncycastle.cms.CMSEncryptedDataGenerator; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.operator.OutputEncryptor; + +/** + * A builder for the PKCS#12 Pfx key and certificate store. + *

+ * For example: you can build a basic key store for the user owning privKey as follows: + *

+ *
+ *      X509Certificate[] chain = ....
+ *      PublicKey         pubKey = ....
+ *      PrivateKey        privKey = ....
+ *      JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+ *
+ *      PKCS12SafeBagBuilder taCertBagBuilder = new JcaPKCS12SafeBagBuilder(chain[2]);
+ *
+ *      taCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString("Bouncy Primary Certificate"));
+ *
+ *      PKCS12SafeBagBuilder caCertBagBuilder = new JcaPKCS12SafeBagBuilder(chain[1]);
+ *
+ *      caCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString("Bouncy Intermediate Certificate"));
+ *
+ *      PKCS12SafeBagBuilder eeCertBagBuilder = new JcaPKCS12SafeBagBuilder(chain[0]);
+ *
+ *      eeCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName, new DERBMPString("Eric's Key"));
+ *      eeCertBagBuilder.addBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId, extUtils.createSubjectKeyIdentifier(pubKey));
+ *
+ *      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));
+ *
+ *      //
+ *      // 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();
+ *
+ *      pfxPduBuilder.addEncryptedData(new BcPKCS12PBEOutputEncryptorBuilder(PKCSObjectIdentifiers.pbeWithSHAAnd40BitRC2_CBC, new CBCBlockCipher(new RC2Engine())).build(passwd), certs);
+ *
+ *      pfxPduBuilder.addData(keyBagBuilder.build());
+ *
+ *      PKCS12PfxPdu pfx = pfxPduBuilder.build(new BcPKCS12MacCalculatorBuilder(), passwd);
+ * 
+ * + */ +public class PKCS12PfxPduBuilder +{ + private ASN1EncodableVector dataVector = new ASN1EncodableVector(); + + /** + * Add a SafeBag that is to be included as is. + * + * @param data the SafeBag to add. + * @return this builder. + * @throws IOException + */ + public PKCS12PfxPduBuilder addData(PKCS12SafeBag data) + throws IOException + { + dataVector.add(new ContentInfo(PKCSObjectIdentifiers.data, new DEROctetString(new DLSequence(data.toASN1Structure()).getEncoded()))); + + return this; + } + + /** + * Add a SafeBag that is to be wrapped in a EncryptedData object. + * + * @param dataEncryptor the encryptor to use for encoding the data. + * @param data the SafeBag to include. + * @return this builder. + * @throws IOException if a issue occurs processing the data. + */ + public PKCS12PfxPduBuilder addEncryptedData(OutputEncryptor dataEncryptor, PKCS12SafeBag data) + throws IOException + { + return addEncryptedData(dataEncryptor, new DERSequence(data.toASN1Structure())); + } + + /** + * Add a set of SafeBags that are to be wrapped in a EncryptedData object. + * + * @param dataEncryptor the encryptor to use for encoding the data. + * @param data the SafeBags to include. + * @return this builder. + * @throws IOException if a issue occurs processing the data. + */ + public PKCS12PfxPduBuilder addEncryptedData(OutputEncryptor dataEncryptor, PKCS12SafeBag[] data) + throws IOException + { + ASN1EncodableVector v = new ASN1EncodableVector(); + + for (int i = 0; i != data.length; i++) + { + v.add(data[i].toASN1Structure()); + } + + return addEncryptedData(dataEncryptor, new DLSequence(v)); + } + + private PKCS12PfxPduBuilder addEncryptedData(OutputEncryptor dataEncryptor, ASN1Sequence data) + throws IOException + { + CMSEncryptedDataGenerator envGen = new CMSEncryptedDataGenerator(); + + try + { + dataVector.add(envGen.generate(new CMSProcessableByteArray(data.getEncoded()), dataEncryptor).toASN1Structure()); + } + catch (CMSException e) + { + throw new PKCSIOException(e.getMessage(), e.getCause()); + } + + return this; + } + + /** + * Build the Pfx structure, protecting it with a MAC calculated against the passed in password. + * + * @param macCalcBuilder a builder for a PKCS12 mac calculator. + * @param password the password to use. + * @return a Pfx object. + * @throws PKCSException on a encoding or processing error. + */ + public PKCS12PfxPdu build(PKCS12MacCalculatorBuilder macCalcBuilder, char[] password) + throws PKCSException + { + AuthenticatedSafe auth = AuthenticatedSafe.getInstance(new DLSequence(dataVector)); + byte[] encAuth; + + try + { + encAuth = auth.getEncoded(); + } + catch (IOException e) + { + throw new PKCSException("unable to encode AuthenticatedSafe: " + e.getMessage(), e); + } + + ContentInfo mainInfo = new ContentInfo(PKCSObjectIdentifiers.data, new DEROctetString(encAuth)); + MacData mData = null; + + if (macCalcBuilder != null) + { + MacDataGenerator mdGen = new MacDataGenerator(macCalcBuilder); + + mData = mdGen.build(password, encAuth); + } + + // + // output the Pfx + // + Pfx pfx = new Pfx(mainInfo, mData); + + return new PKCS12PfxPdu(pfx); + } +} -- cgit v1.2.3