001: package org.bouncycastle.jce.examples;
002:
003: import java.io.FileOutputStream;
004: import java.math.BigInteger;
005: import java.security.KeyFactory;
006: import java.security.KeyStore;
007: import java.security.PrivateKey;
008: import java.security.PublicKey;
009: import java.security.Security;
010: import java.security.cert.Certificate;
011: import java.security.cert.X509Certificate;
012: import java.security.spec.RSAPrivateCrtKeySpec;
013: import java.security.spec.RSAPublicKeySpec;
014: import java.util.Date;
015: import java.util.Hashtable;
016: import java.util.Vector;
017:
018: import org.bouncycastle.asn1.DERBMPString;
019: import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
020: import org.bouncycastle.asn1.x509.BasicConstraints;
021: import org.bouncycastle.asn1.x509.X509Extensions;
022: import org.bouncycastle.jce.PrincipalUtil;
023: import org.bouncycastle.jce.X509Principal;
024: import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
025: import org.bouncycastle.jce.provider.BouncyCastleProvider;
026: import org.bouncycastle.x509.X509V1CertificateGenerator;
027: import org.bouncycastle.x509.X509V3CertificateGenerator;
028: import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
029: import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
030:
031: /**
032: * Example of how to set up a certificiate chain and a PKCS 12 store for
033: * a private individual - obviously you'll need to generate your own keys,
034: * and you may need to add a NetscapeCertType extension or add a key
035: * usage extension depending on your application, but you should get the
036: * idea! As always this is just an example...
037: */
038: public class PKCS12Example {
039: static char[] passwd = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o',
040: 'r', 'l', 'd' };
041:
042: static X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator();
043: static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
044:
045: /**
046: * we generate the CA's certificate
047: */
048: public static Certificate createMasterCert(PublicKey pubKey,
049: PrivateKey privKey) throws Exception {
050: //
051: // signers name
052: //
053: String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
054:
055: //
056: // subjects name - the same as we are self signed.
057: //
058: String subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
059:
060: //
061: // create the certificate - version 1
062: //
063:
064: v1CertGen.setSerialNumber(BigInteger.valueOf(1));
065: v1CertGen.setIssuerDN(new X509Principal(issuer));
066: v1CertGen.setNotBefore(new Date(System.currentTimeMillis()
067: - 1000L * 60 * 60 * 24 * 30));
068: v1CertGen.setNotAfter(new Date(System.currentTimeMillis()
069: + (1000L * 60 * 60 * 24 * 30)));
070: v1CertGen.setSubjectDN(new X509Principal(subject));
071: v1CertGen.setPublicKey(pubKey);
072: v1CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
073:
074: X509Certificate cert = v1CertGen
075: .generateX509Certificate(privKey);
076:
077: cert.checkValidity(new Date());
078:
079: cert.verify(pubKey);
080:
081: PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier) cert;
082:
083: //
084: // this is actually optional - but if you want to have control
085: // over setting the friendly name this is the way to do it...
086: //
087: bagAttr.setBagAttribute(
088: PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
089: new DERBMPString("Bouncy Primary Certificate"));
090:
091: return cert;
092: }
093:
094: /**
095: * we generate an intermediate certificate signed by our CA
096: */
097: public static Certificate createIntermediateCert(PublicKey pubKey,
098: PrivateKey caPrivKey, X509Certificate caCert)
099: throws Exception {
100: //
101: // subject name table.
102: //
103: Hashtable attrs = new Hashtable();
104: Vector order = new Vector();
105:
106: attrs.put(X509Principal.C, "AU");
107: attrs.put(X509Principal.O, "The Legion of the Bouncy Castle");
108: attrs.put(X509Principal.OU, "Bouncy Intermediate Certificate");
109: attrs.put(X509Principal.EmailAddress,
110: "feedback-crypto@bouncycastle.org");
111:
112: order.addElement(X509Principal.C);
113: order.addElement(X509Principal.O);
114: order.addElement(X509Principal.OU);
115: order.addElement(X509Principal.EmailAddress);
116:
117: //
118: // create the certificate - version 3
119: //
120: v3CertGen.reset();
121:
122: v3CertGen.setSerialNumber(BigInteger.valueOf(2));
123: v3CertGen.setIssuerDN(PrincipalUtil
124: .getSubjectX509Principal(caCert));
125: v3CertGen.setNotBefore(new Date(System.currentTimeMillis()
126: - 1000L * 60 * 60 * 24 * 30));
127: v3CertGen.setNotAfter(new Date(System.currentTimeMillis()
128: + (1000L * 60 * 60 * 24 * 30)));
129: v3CertGen.setSubjectDN(new X509Principal(order, attrs));
130: v3CertGen.setPublicKey(pubKey);
131: v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
132:
133: //
134: // extensions
135: //
136: v3CertGen.addExtension(X509Extensions.SubjectKeyIdentifier,
137: false, new SubjectKeyIdentifierStructure(pubKey));
138:
139: v3CertGen.addExtension(X509Extensions.AuthorityKeyIdentifier,
140: false, new AuthorityKeyIdentifierStructure(caCert));
141:
142: v3CertGen.addExtension(X509Extensions.BasicConstraints, true,
143: new BasicConstraints(0));
144:
145: X509Certificate cert = v3CertGen
146: .generateX509Certificate(caPrivKey);
147:
148: cert.checkValidity(new Date());
149:
150: cert.verify(caCert.getPublicKey());
151:
152: PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier) cert;
153:
154: //
155: // this is actually optional - but if you want to have control
156: // over setting the friendly name this is the way to do it...
157: //
158: bagAttr.setBagAttribute(
159: PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
160: new DERBMPString("Bouncy Intermediate Certificate"));
161:
162: return cert;
163: }
164:
165: /**
166: * we generate a certificate signed by our CA's intermediate certficate
167: */
168: public static Certificate createCert(PublicKey pubKey,
169: PrivateKey caPrivKey, PublicKey caPubKey) throws Exception {
170: //
171: // signers name table.
172: //
173: Hashtable sAttrs = new Hashtable();
174: Vector sOrder = new Vector();
175:
176: sAttrs.put(X509Principal.C, "AU");
177: sAttrs.put(X509Principal.O, "The Legion of the Bouncy Castle");
178: sAttrs.put(X509Principal.OU, "Bouncy Intermediate Certificate");
179: sAttrs.put(X509Principal.EmailAddress,
180: "feedback-crypto@bouncycastle.org");
181:
182: sOrder.addElement(X509Principal.C);
183: sOrder.addElement(X509Principal.O);
184: sOrder.addElement(X509Principal.OU);
185: sOrder.addElement(X509Principal.EmailAddress);
186:
187: //
188: // subjects name table.
189: //
190: Hashtable attrs = new Hashtable();
191: Vector order = new Vector();
192:
193: attrs.put(X509Principal.C, "AU");
194: attrs.put(X509Principal.O, "The Legion of the Bouncy Castle");
195: attrs.put(X509Principal.L, "Melbourne");
196: attrs.put(X509Principal.CN, "Eric H. Echidna");
197: attrs.put(X509Principal.EmailAddress,
198: "feedback-crypto@bouncycastle.org");
199:
200: order.addElement(X509Principal.C);
201: order.addElement(X509Principal.O);
202: order.addElement(X509Principal.L);
203: order.addElement(X509Principal.CN);
204: order.addElement(X509Principal.EmailAddress);
205:
206: //
207: // create the certificate - version 3
208: //
209: v3CertGen.reset();
210:
211: v3CertGen.setSerialNumber(BigInteger.valueOf(3));
212: v3CertGen.setIssuerDN(new X509Principal(sOrder, sAttrs));
213: v3CertGen.setNotBefore(new Date(System.currentTimeMillis()
214: - 1000L * 60 * 60 * 24 * 30));
215: v3CertGen.setNotAfter(new Date(System.currentTimeMillis()
216: + (1000L * 60 * 60 * 24 * 30)));
217: v3CertGen.setSubjectDN(new X509Principal(order, attrs));
218: v3CertGen.setPublicKey(pubKey);
219: v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
220:
221: //
222: // add the extensions
223: //
224: v3CertGen.addExtension(X509Extensions.SubjectKeyIdentifier,
225: false, new SubjectKeyIdentifierStructure(pubKey));
226:
227: v3CertGen.addExtension(X509Extensions.AuthorityKeyIdentifier,
228: false, new AuthorityKeyIdentifierStructure(caPubKey));
229:
230: X509Certificate cert = v3CertGen
231: .generateX509Certificate(caPrivKey);
232:
233: cert.checkValidity(new Date());
234:
235: cert.verify(caPubKey);
236:
237: PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier) cert;
238:
239: //
240: // this is also optional - in the sense that if you leave this
241: // out the keystore will add it automatically, note though that
242: // for the browser to recognise the associated private key this
243: // you should at least use the pkcs_9_localKeyId OID and set it
244: // to the same as you do for the private key's localKeyId.
245: //
246: bagAttr.setBagAttribute(
247: PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
248: new DERBMPString("Eric's Key"));
249: bagAttr.setBagAttribute(
250: PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
251: new SubjectKeyIdentifierStructure(pubKey));
252:
253: return cert;
254: }
255:
256: public static void main(String[] args) throws Exception {
257: Security.addProvider(new BouncyCastleProvider());
258:
259: //
260: // personal keys
261: //
262: RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
263: new BigInteger(
264: "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7",
265: 16), new BigInteger("11", 16));
266:
267: RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec(
268: new BigInteger(
269: "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7",
270: 16),
271: new BigInteger("11", 16),
272: new BigInteger(
273: "9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89",
274: 16),
275: new BigInteger(
276: "c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb",
277: 16),
278: new BigInteger(
279: "f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5",
280: 16),
281: new BigInteger(
282: "b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391",
283: 16),
284: new BigInteger(
285: "d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd",
286: 16),
287: new BigInteger(
288: "b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19",
289: 16));
290:
291: //
292: // intermediate keys.
293: //
294: RSAPublicKeySpec intPubKeySpec = new RSAPublicKeySpec(
295: new BigInteger(
296: "8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69",
297: 16), new BigInteger("ffff", 16));
298:
299: RSAPrivateCrtKeySpec intPrivKeySpec = new RSAPrivateCrtKeySpec(
300: new BigInteger(
301: "8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69",
302: 16),
303: new BigInteger("ffff", 16),
304: new BigInteger(
305: "7deb1b194a85bcfd29cf871411468adbc987650903e3bacc8338c449ca7b32efd39ffc33bc84412fcd7df18d23ce9d7c25ea910b1ae9985373e0273b4dca7f2e0db3b7314056ac67fd277f8f89cf2fd73c34c6ca69f9ba477143d2b0e2445548aa0b4a8473095182631da46844c356f5e5c7522eb54b5a33f11d730ead9c0cff",
306: 16),
307: new BigInteger(
308: "ef4cede573cea47f83699b814de4302edb60eefe426c52e17bd7870ec7c6b7a24fe55282ebb73775f369157726fcfb988def2b40350bdca9e5b418340288f649",
309: 16),
310: new BigInteger(
311: "97c7737d1b9a0088c3c7b528539247fd2a1593e7e01cef18848755be82f4a45aa093276cb0cbf118cb41117540a78f3fc471ba5d69f0042274defc9161265721",
312: 16),
313: new BigInteger(
314: "6c641094e24d172728b8da3c2777e69adfd0839085be7e38c7c4a2dd00b1ae969f2ec9d23e7e37090fcd449a40af0ed463fe1c612d6810d6b4f58b7bfa31eb5f",
315: 16),
316: new BigInteger(
317: "70b7123e8e69dfa76feb1236d0a686144b00e9232ed52b73847e74ef3af71fb45ccb24261f40d27f98101e230cf27b977a5d5f1f15f6cf48d5cb1da2a3a3b87f",
318: 16),
319: new BigInteger(
320: "e38f5750d97e270996a286df2e653fd26c242106436f5bab0f4c7a9e654ce02665d5a281f2c412456f2d1fa26586ef04a9adac9004ca7f913162cb28e13bf40d",
321: 16));
322:
323: //
324: // ca keys
325: //
326: RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec(
327: new BigInteger(
328: "b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5",
329: 16), new BigInteger("11", 16));
330:
331: RSAPrivateCrtKeySpec caPrivKeySpec = new RSAPrivateCrtKeySpec(
332: new BigInteger(
333: "b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5",
334: 16),
335: new BigInteger("11", 16),
336: new BigInteger(
337: "92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619",
338: 16),
339: new BigInteger(
340: "f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03",
341: 16),
342: new BigInteger(
343: "b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947",
344: 16),
345: new BigInteger(
346: "1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5",
347: 16),
348: new BigInteger(
349: "6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded",
350: 16),
351: new BigInteger(
352: "dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339",
353: 16));
354:
355: //
356: // set up the keys
357: //
358: KeyFactory fact = KeyFactory.getInstance("RSA", "BC");
359: PrivateKey caPrivKey = fact.generatePrivate(caPrivKeySpec);
360: PublicKey caPubKey = fact.generatePublic(caPubKeySpec);
361: PrivateKey intPrivKey = fact.generatePrivate(intPrivKeySpec);
362: PublicKey intPubKey = fact.generatePublic(intPubKeySpec);
363: PrivateKey privKey = fact.generatePrivate(privKeySpec);
364: PublicKey pubKey = fact.generatePublic(pubKeySpec);
365:
366: Certificate[] chain = new Certificate[3];
367:
368: chain[2] = createMasterCert(caPubKey, caPrivKey);
369: chain[1] = createIntermediateCert(intPubKey, caPrivKey,
370: (X509Certificate) chain[2]);
371: chain[0] = createCert(pubKey, intPrivKey, intPubKey);
372:
373: //
374: // add the friendly name for the private key
375: //
376: PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier) privKey;
377:
378: //
379: // this is also optional - in the sense that if you leave this
380: // out the keystore will add it automatically, note though that
381: // for the browser to recognise which certificate the private key
382: // is associated with you should at least use the pkcs_9_localKeyId
383: // OID and set it to the same as you do for the private key's
384: // corresponding certificate.
385: //
386: bagAttr.setBagAttribute(
387: PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
388: new DERBMPString("Eric's Key"));
389: bagAttr.setBagAttribute(
390: PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
391: new SubjectKeyIdentifierStructure(pubKey));
392:
393: //
394: // store the key and the certificate chain
395: //
396: KeyStore store = KeyStore.getInstance("PKCS12", "BC");
397:
398: store.load(null, null);
399:
400: //
401: // if you haven't set the friendly name and local key id above
402: // the name below will be the name of the key
403: //
404: store.setKeyEntry("Eric's Key", privKey, null, chain);
405:
406: FileOutputStream fOut = new FileOutputStream("id.p12");
407:
408: store.store(fOut, passwd);
409: }
410: }
|