* see: http://www.bouncycastle.org/wiki/display/JA1/X.509+Public+Key+Certificate+and+Certification+Request+Generation
*
* @throws Exception
*/
public void generate() throws Exception {
X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
certGenerator.reset();
/*
Sets up the subject distinguished name.
The issuer should be the same for all self signed CAs as this then allows selection of acceptable certificates
by the server
*/
certGenerator.setIssuerDN(new X509Name(BouncyKeygenService.issuer));
Vector<DERObjectIdentifier> subjectDnOids = new Vector<DERObjectIdentifier>();
Vector<String> subjectDnValues = new Vector<String>();
subjectDnOids.add(X509Name.O);
subjectDnValues.add("FOAF+SSL");
subjectDnOids.add(X509Name.OU);
subjectDnValues.add("The Community Of Self Signers");
//DNs have to be unique, so we put a webID here. The first one
String webId = sans.getFirst();
subjectDnOids.add(X509Name.UID);
subjectDnValues.add(webId);
subjectDnOids.add(X509Name.CN);
subjectDnValues.add(CN);
X509Name DName = new X509Name(subjectDnOids, subjectDnValues);
certGenerator.setSubjectDN(DName);
/*
Sets up the validity dates.
*/
certGenerator.setNotBefore(getStartDate());
certGenerator.setNotAfter(getEndDate());
/*
set a random number for the serial number
*/
certGenerator.setSerialNumber(service.nextRandom());
/*
Sets the public-key to embed in this certificate.
*/
certGenerator.setPublicKey(getSubjectPublicKey().getPublicKey());
/*
* Sets the signature algorithm.
*/
// String pubKeyAlgorithm = service.caPubKey.getAlgorithm();
// if (pubKeyAlgorithm.equals("DSA")) {
// certGenerator.setSignatureAlgorithm("SHA1WithDSA");
// } else if (pubKeyAlgorithm.equals("RSA")) {
certGenerator.setSignatureAlgorithm("SHA1WithRSAEncryption");
// } else {
// RuntimeException re = new RuntimeException(
// "Algorithm not recognised: " + pubKeyAlgorithm);
// LOGGER.error(re.getMessage(), re);
// throw re;
// }
/*
Adds the Basic Constraint (CA: false) extension.
*/
certGenerator.addExtension(X509Extension.basicConstraints, true,
new BasicConstraints(false));
/*
Adds the Key Usage extension.
*/
certGenerator.addExtension(X509Extension.keyUsage, true, new KeyUsage(
KeyUsage.digitalSignature | KeyUsage.nonRepudiation
| KeyUsage.keyEncipherment | KeyUsage.keyAgreement
| KeyUsage.keyCertSign));
/*
Adds the Netscape certificate type extension.
sslClient: the certificate is selectable by the client
the certificate can be used for mime encryption.
(perhaps the above should be settable. It is not clear that most certs should be used that way, as their life
span could be very short)
*/
certGenerator.addExtension(MiscObjectIdentifiers.netscapeCertType,
false, new NetscapeCertType(NetscapeCertType.sslClient
| NetscapeCertType.smime));
/*
* Adds the authority key identifier extension.
* Bruno pointed out that this is not needed, as the authority's key is never checked in this setup!
* so I am commenting it out, to be removed at a later date.
*
AuthorityKeyIdentifierStructure authorityKeyIdentifier;
try {
authorityKeyIdentifier = new AuthorityKeyIdentifierStructure(
service.certificate.getPublicKey());
} catch (InvalidKeyException e) {
throw new Exception("failed to parse CA cert. This should never happen", e);
}
certGenerator.addExtension(X509Extensions.AuthorityKeyIdentifier,
false, authorityKeyIdentifier);
*/
/*
Adds the subject key identifier extension.
*/
SubjectKeyIdentifier subjectKeyIdentifier = new SubjectKeyIdentifierStructure(
getSubjectPublicKey().getPublicKey());
certGenerator.addExtension(X509Extension.subjectKeyIdentifier, false,
subjectKeyIdentifier);
/*
Adds the subject alternative-name extension (critical).
*/
if (sans.size() == 0) {
throw new Exception("WebId not set!");
}
if (sans.size() == 1) {
GeneralNames subjectAltNames = new GeneralNames(new GeneralName(
GeneralName.uniformResourceIdentifier, webId));
certGenerator.addExtension(X509Extension.subjectAlternativeName,
true, subjectAltNames);
} else {
// BouncyCastle has a pretty inflexible API. It would have made more sense to just
// pass an array of Names to the constructor.
GeneralName[] names = new GeneralName[sans.size()];
Iterator<String> sanIt = sans.iterator();
int i = 0;
while (sanIt.hasNext()) {
names[i] = new GeneralName(GeneralName.uniformResourceIdentifier, sanIt.next());
i++;
}
certGenerator.addExtension(X509Extension.subjectAlternativeName,
true, new DERSequence(names));
}
/*
Creates and sign this certificate with the private key corresponding
to the public key of the FOAF+SSL DN
*/
cert = certGenerator.generate(service.privateKey);
/*
Checks that this certificate has indeed been correctly signed.
*/
cert.verify(service.certificate.getPublicKey());