/*
* $Id: PKCS10Test.java,v 1.3 2009/07/15 13:53:40 vtschopp Exp $
*
* Created on Aug 22, 2006 by Valery Tschopp <tschopp@switch.ch>
*
* Copyright (c) 2006 SWITCH - http://www.switch.ch/
*/
package org.glite.slcs.pki.bouncycastle;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import javax.naming.InvalidNameException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import junit.framework.TestCase;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.PolicyInformation;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.asn1.x509.X509NameTokenizer;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.util.Strings;
public class PKCS10Test extends TestCase {
private static String KEY_ALGORITHM = "RSA";
private static int KEY_SIZE = 1024;
private String subject = null;
private String email = null;
private KeyPair keys = null;
protected void setUp() throws Exception {
super.setUp();
this.subject = "C=CH, O=Switch - Teleinformatikdienste fuer Lehre und Forschung, CN=Valery Tschopp 9FEE5EE3";
this.email = "tschopp@switch.ch";
KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
generator.initialize(KEY_SIZE);
this.keys = generator.generateKeyPair();
}
protected void tearDown() throws Exception {
super.tearDown();
}
/**
* This test will fail! Bug in BouncyCastle?
*/
public void testX509Principal() {
X509Principal p = createX509Principal("CN=A+B");
System.out.println("X509Principal=" + p);
assertEquals("CN=A\\+B", p.toString());
p = createX509Principal("DC=hello,CN=A+CN=B");
System.out.println("X509Principal=" + p);
X509Principal expected = new X509Principal("DC=hello,CN=A+CN=B");
System.out.println("X509Principal (expected)=" + expected);
assertEquals(expected, p);
}
@SuppressWarnings("unchecked")
public X509Principal createX509Principal(String dirName) {
Vector oids = new Vector();
Vector values = new Vector();
X509NameTokenizer nTok = new X509NameTokenizer(dirName);
while (nTok.hasMoreTokens()) {
String token = nTok.nextToken();
// Test if the format for this token is correct
LdapName lname = null;
try {
lname = new LdapName(token);
} catch (InvalidNameException e) {
// Invalid, the server did not format correctly, attempt to
// repair this
System.err.println(e);
int index = token.indexOf('=');
if (index == -1) {
throw new IllegalArgumentException(
"badly formated directory string");
}
String name = token.substring(0, index);
String value = token.substring(index + 1);
String formatedValue = Rdn.escapeValue(value);
try {
lname = new LdapName(name + "=" + formatedValue);
} catch (InvalidNameException e1) {
}
}
parseValue(lname, oids, values);
}
return new X509Principal(oids, values);
}
@SuppressWarnings("unchecked")
private void parseValue(LdapName dn, Vector oids, Vector values) {
List<Rdn> rdns = dn.getRdns();
for (Rdn rdn : rdns) {
Attributes attrs = rdn.toAttributes();
NamingEnumeration<? extends Attribute> enums = attrs.getAll();
while (enums.hasMoreElements()) {
Attribute attr = enums.nextElement();
DERObjectIdentifier oid = (DERObjectIdentifier) X509Name.DefaultLookUp.get(Strings.toLowerCase(attr.getID()));
if (oid != null) {
try {
values.add(attr.get().toString());
oids.add(oid);
} catch (NamingException e) {
System.err.println(e);
}
}
}
}
}
/*
* Test method for 'org.glite.slcs.pki.bouncycastle.PKCS10.PKCS10(String,
* PublicKey, PrivateKey, X509Extensions)'
*/
public void testPKCS10StringPublicKeyPrivateKeyX509Extensions()
throws GeneralSecurityException, IOException {
X509Extensions x509Extensions = createX509Extensions();
PKCS10 pkcs10 = new PKCS10(subject, keys.getPublic(),
keys.getPrivate(), x509Extensions);
// store csr
String basename = "testPKCS10StringPublicKeyPrivateKeyX509Extensions";
File pemFile = new File(basename + ".csr");
pemFile.delete();
pemFile.deleteOnExit();
pkcs10.storePEMEncoded(pemFile);
File derFile = new File(basename + ".der");
derFile.delete();
derFile.deleteOnExit();
pkcs10.storeDEREncoded(derFile);
}
@SuppressWarnings("unchecked")
public void testGetX509Extensions() throws GeneralSecurityException,
IOException {
X509Extensions x509Extensions = createX509Extensions();
PKCS10 pkcs10 = new PKCS10(subject, keys.getPublic(),
keys.getPrivate(), x509Extensions);
String basename = "testGetX509Extensions";
File pemFile = new File(basename + ".csr");
pemFile.delete();
pemFile.deleteOnExit();
pkcs10.storePEMEncoded(pemFile);
// reload the PEM file
FileReader reader = new FileReader(pemFile);
PKCS10 pkcs10_reloaded = PKCS10.readPEMEncoded(reader);
X509Extensions x509Extensions_reloaded = pkcs10_reloaded.getX509Extensions();
if (x509Extensions_reloaded != null) {
// dump the X509extensions
Enumeration oids = x509Extensions_reloaded.oids();
while (oids.hasMoreElements()) {
DERObjectIdentifier oid = (DERObjectIdentifier) oids.nextElement();
System.out.println("X509Extension OID: " + oid);
X509Extension x509Extension = x509Extensions_reloaded.getExtension(oid);
System.out.println("X509Extension: " + x509Extension.getValue());
}
}
}
private X509Extensions createX509Extensions() {
// extensions
Hashtable<DERObjectIdentifier, X509Extension> extensions = new Hashtable<DERObjectIdentifier, X509Extension>();
// Key Usage: Digital Signature + Key Encipherment
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature
+ KeyUsage.keyEncipherment);
X509Extension keyUsageExtension = new X509Extension(true,
new DEROctetString(keyUsage));
extensions.put(X509Extensions.KeyUsage, keyUsageExtension);
// Extended Key Usage: TLS Web Client Authentication
ExtendedKeyUsage extendedKeyUsage = new ExtendedKeyUsage(
KeyPurposeId.id_kp_clientAuth);
X509Extension extendedKeyUsageExtension = new X509Extension(false,
new DEROctetString(extendedKeyUsage));
extensions.put(X509Extensions.ExtendedKeyUsage,
extendedKeyUsageExtension);
// Certificate Policies: 2.16.756.1.2.6.3
DERObjectIdentifier policyOID = new DERObjectIdentifier(
"2.16.756.1.2.6.3");
PolicyInformation policyInformation = new PolicyInformation(policyOID);
DERSequence certificatePolicies = new DERSequence(policyInformation);
X509Extension certificatePoliciesExtension = new X509Extension(false,
new DEROctetString(certificatePolicies));
extensions.put(X509Extensions.CertificatePolicies,
certificatePoliciesExtension);
// SubjectAltName: <email>
GeneralName subjectAltName = new GeneralName(GeneralName.rfc822Name,
this.email);
GeneralNames subjectAltNames = new GeneralNames(subjectAltName);
X509Extension subjectAltNameExtension = new X509Extension(false,
new DEROctetString(subjectAltNames));
extensions.put(X509Extensions.SubjectAlternativeName,
subjectAltNameExtension);
// create the X509Extensions object
X509Extensions x509Extensions = new X509Extensions(extensions);
return x509Extensions;
}
}