001: package org.bouncycastle.x509.examples;
002:
003: import java.security.cert.*;
004: import java.security.spec.RSAPrivateCrtKeySpec;
005: import java.security.spec.RSAPublicKeySpec;
006: import java.security.*;
007: import java.math.*;
008: import java.util.Date;
009: import java.util.Hashtable;
010: import java.util.Vector;
011:
012: import org.bouncycastle.jce.X509Principal;
013: import org.bouncycastle.jce.provider.*;
014: import org.bouncycastle.asn1.*;
015: import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
016: import org.bouncycastle.asn1.misc.NetscapeCertType;
017: import org.bouncycastle.asn1.x509.GeneralName;
018: import org.bouncycastle.x509.*;
019:
020: /**
021: * A simple example that generates an attribute certificate.
022: */
023: public class AttrCertExample {
024: static X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator();
025: static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
026:
027: /**
028: * we generate the AC issuer's certificate
029: */
030: public static X509Certificate createAcIssuerCert(PublicKey pubKey,
031: PrivateKey privKey) throws Exception {
032: //
033: // signers name
034: //
035: String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
036:
037: //
038: // subjects name - the same as we are self signed.
039: //
040: String subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
041:
042: //
043: // create the certificate - version 1
044: //
045:
046: v1CertGen.setSerialNumber(BigInteger.valueOf(10));
047: v1CertGen.setIssuerDN(new X509Principal(issuer));
048: v1CertGen.setNotBefore(new Date(System.currentTimeMillis()
049: - 1000L * 60 * 60 * 24 * 30));
050: v1CertGen.setNotAfter(new Date(System.currentTimeMillis()
051: + (1000L * 60 * 60 * 24 * 30)));
052: v1CertGen.setSubjectDN(new X509Principal(subject));
053: v1CertGen.setPublicKey(pubKey);
054: v1CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
055:
056: X509Certificate cert = v1CertGen
057: .generateX509Certificate(privKey);
058:
059: cert.checkValidity(new Date());
060:
061: cert.verify(pubKey);
062:
063: return cert;
064: }
065:
066: /**
067: * we generate a certificate signed by our CA's intermediate certficate
068: */
069: public static X509Certificate createClientCert(PublicKey pubKey,
070: PrivateKey caPrivKey, PublicKey caPubKey) throws Exception {
071: //
072: // issuer
073: //
074: String issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
075:
076: //
077: // subjects name table.
078: //
079: Hashtable attrs = new Hashtable();
080: Vector order = new Vector();
081:
082: attrs.put(X509Principal.C, "AU");
083: attrs.put(X509Principal.O, "The Legion of the Bouncy Castle");
084: attrs.put(X509Principal.L, "Melbourne");
085: attrs.put(X509Principal.CN, "Eric H. Echidna");
086: attrs.put(X509Principal.EmailAddress,
087: "feedback-crypto@bouncycastle.org");
088:
089: order.addElement(X509Principal.C);
090: order.addElement(X509Principal.O);
091: order.addElement(X509Principal.L);
092: order.addElement(X509Principal.CN);
093: order.addElement(X509Principal.EmailAddress);
094:
095: //
096: // create the certificate - version 3
097: //
098: v3CertGen.reset();
099:
100: v3CertGen.setSerialNumber(BigInteger.valueOf(20));
101: v3CertGen.setIssuerDN(new X509Principal(issuer));
102: v3CertGen.setNotBefore(new Date(System.currentTimeMillis()
103: - 1000L * 60 * 60 * 24 * 30));
104: v3CertGen.setNotAfter(new Date(System.currentTimeMillis()
105: + (1000L * 60 * 60 * 24 * 30)));
106: v3CertGen.setSubjectDN(new X509Principal(order, attrs));
107: v3CertGen.setPublicKey(pubKey);
108: v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
109:
110: //
111: // add the extensions
112: //
113:
114: v3CertGen.addExtension(MiscObjectIdentifiers.netscapeCertType,
115: false, new NetscapeCertType(
116: NetscapeCertType.objectSigning
117: | NetscapeCertType.smime));
118:
119: X509Certificate cert = v3CertGen
120: .generateX509Certificate(caPrivKey);
121:
122: cert.checkValidity(new Date());
123:
124: cert.verify(caPubKey);
125:
126: return cert;
127: }
128:
129: public static void main(String args[]) throws Exception {
130: Security.addProvider(new BouncyCastleProvider());
131:
132: //
133: // personal keys
134: //
135: RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
136: new BigInteger(
137: "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7",
138: 16), new BigInteger("11", 16));
139:
140: RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec(
141: new BigInteger(
142: "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7",
143: 16),
144: new BigInteger("11", 16),
145: new BigInteger(
146: "9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89",
147: 16),
148: new BigInteger(
149: "c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb",
150: 16),
151: new BigInteger(
152: "f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5",
153: 16),
154: new BigInteger(
155: "b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391",
156: 16),
157: new BigInteger(
158: "d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd",
159: 16),
160: new BigInteger(
161: "b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19",
162: 16));
163:
164: //
165: // ca keys
166: //
167: RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec(
168: new BigInteger(
169: "b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5",
170: 16), new BigInteger("11", 16));
171:
172: RSAPrivateCrtKeySpec caPrivKeySpec = new RSAPrivateCrtKeySpec(
173: new BigInteger(
174: "b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5",
175: 16),
176: new BigInteger("11", 16),
177: new BigInteger(
178: "92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619",
179: 16),
180: new BigInteger(
181: "f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03",
182: 16),
183: new BigInteger(
184: "b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947",
185: 16),
186: new BigInteger(
187: "1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5",
188: 16),
189: new BigInteger(
190: "6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded",
191: 16),
192: new BigInteger(
193: "dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339",
194: 16));
195:
196: //
197: // set up the keys
198: //
199: KeyFactory fact = KeyFactory.getInstance("RSA", "BC");
200: PrivateKey caPrivKey = fact.generatePrivate(caPrivKeySpec);
201: PublicKey caPubKey = fact.generatePublic(caPubKeySpec);
202: PrivateKey privKey = fact.generatePrivate(privKeySpec);
203: PublicKey pubKey = fact.generatePublic(pubKeySpec);
204:
205: //
206: // note in this case we are using the CA certificate for both the client cetificate
207: // and the attribute certificate. This is to make the vcode simpler to read, in practice
208: // the CA for the attribute certificate should be different to that of the client certificate
209: //
210: X509Certificate caCert = createAcIssuerCert(caPubKey, caPrivKey);
211: X509Certificate clientCert = createClientCert(pubKey,
212: caPrivKey, caPubKey);
213:
214: // Instantiate a new AC generator
215: X509V2AttributeCertificateGenerator acGen = new X509V2AttributeCertificateGenerator();
216:
217: acGen.reset();
218:
219: //
220: // Holder: here we use the IssuerSerial form
221: //
222: acGen.setHolder(new AttributeCertificateHolder(clientCert));
223:
224: // set the Issuer
225: acGen.setIssuer(new AttributeCertificateIssuer(caCert
226: .getSubjectX500Principal()));
227:
228: //
229: // serial number (as it's an example we don't have to keep track of the
230: // serials anyway
231: //
232: acGen.setSerialNumber(new BigInteger("1"));
233:
234: // not Before
235: acGen
236: .setNotBefore(new Date(
237: System.currentTimeMillis() - 50000));
238:
239: // not After
240: acGen.setNotAfter(new Date(System.currentTimeMillis() + 50000));
241:
242: // signature Algorithmus
243: acGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
244:
245: // the actual attributes
246: GeneralName roleName = new GeneralName(GeneralName.rfc822Name,
247: "DAU123456789");
248: ASN1EncodableVector roleSyntax = new ASN1EncodableVector();
249: roleSyntax.add(roleName);
250:
251: // roleSyntax OID: 2.5.24.72
252: X509Attribute attributes = new X509Attribute("2.5.24.72",
253: new DERSequence(roleSyntax));
254:
255: acGen.addAttribute(attributes);
256:
257: // finally create the AC
258: X509V2AttributeCertificate att = (X509V2AttributeCertificate) acGen
259: .generateCertificate(caPrivKey, "BC");
260:
261: //
262: // starting here, we parse the newly generated AC
263: //
264:
265: // Holder
266:
267: AttributeCertificateHolder h = att.getHolder();
268: if (h.match(clientCert)) {
269: if (h.getEntityNames() != null) {
270: System.out.println(h.getEntityNames().length
271: + " entity names found");
272: }
273: if (h.getIssuer() != null) {
274: System.out.println(h.getIssuer().length
275: + " issuer names found, serial number "
276: + h.getSerialNumber());
277: }
278: System.out.println("Matches original client x509 cert");
279: }
280:
281: // Issuer
282:
283: AttributeCertificateIssuer issuer = att.getIssuer();
284: if (issuer.match(caCert)) {
285: if (issuer.getPrincipals() != null) {
286: System.out.println(issuer.getPrincipals().length
287: + " entity names found");
288: }
289: System.out.println("Matches original ca x509 cert");
290: }
291:
292: // Dates
293: System.out.println("valid not before: " + att.getNotBefore());
294: System.out.println("valid not before: " + att.getNotAfter());
295:
296: // check the dates, an exception is thrown in checkValidity()...
297:
298: try {
299: att.checkValidity();
300: att.checkValidity(new Date());
301: } catch (Exception e) {
302: System.out.println(e);
303: }
304:
305: // verify
306:
307: try {
308: att.verify(caPubKey, "BC");
309: } catch (Exception e) {
310: System.out.println(e);
311: }
312:
313: // Attribute
314: X509Attribute[] attribs = att.getAttributes();
315: System.out.println("cert has " + attribs.length
316: + " attributes:");
317: for (int i = 0; i < attribs.length; i++) {
318: X509Attribute a = attribs[i];
319: System.out.println("OID: " + a.getOID());
320:
321: // currently we only check for the presence of a 'RoleSyntax' attribute
322:
323: if (a.getOID().equals("2.5.24.72")) {
324: System.out.println("rolesyntax read from cert!");
325: }
326: }
327: }
328: }
|