package org.bouncycastle.asn1.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.Date;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1GeneralizedTime;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1OutputStream;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.oiw.ElGamalParameter;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.Extensions;
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.TBSCertList;
import org.bouncycastle.asn1.x509.TBSCertificate;
import org.bouncycastle.asn1.x509.Time;
import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator;
import org.bouncycastle.asn1.x509.V2TBSCertListGenerator;
import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.test.SimpleTest;
public class GenerationTest
extends SimpleTest
{
private byte[] v1Cert = Base64.decode(
"MIGtAgEBMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYDVQQKDA1Cb"
+ "3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAxMlowNjELMA"
+ "kGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3Q"
+ "gMTAaMA0GCSqGSIb3DQEBAQUAAwkAMAYCAQECAQI=");
private byte[] v3Cert = Base64.decode(
"MIIBSKADAgECAgECMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYD"
+ "VQQKDA1Cb3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAw"
+ "MlowNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNV"
+ "BAsMBlRlc3QgMjAYMBAGBisOBwIBATAGAgEBAgECAwQAAgEDo4GVMIGSMGEGA1Ud"
+ "IwEB/wRXMFWAFDZPdpHPzKi7o8EJokkQU2uqCHRRoTqkODA2MQswCQYDVQQDDAJB"
+ "VTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwGVGVzdCAyggECMCAG"
+ "A1UdDgEB/wQWBBQ2T3aRz8you6PBCaJJEFNrqgh0UTALBgNVHQ8EBAMCBBA=");
private byte[] v3CertNullSubject = Base64.decode(
"MIHGoAMCAQICAQIwDQYJKoZIhvcNAQEEBQAwJTELMAkGA1UEAwwCQVUxFjAUBgNVB"
+ "AoMDUJvdW5jeSBDYXN0bGUwHhcNNzAwMTAxMDAwMDAxWhcNNzAwMTAxMDAwMDAyWj"
+ "AAMBgwEAYGKw4HAgEBMAYCAQECAQIDBAACAQOjSjBIMEYGA1UdEQEB/wQ8MDqkODA"
+ "2MQswCQYDVQQDDAJBVTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwG"
+ "VGVzdCAy");
private byte[] v2CertList = Base64.decode(
"MIIBQwIBATANBgkqhkiG9w0BAQUFADAlMQswCQYDVQQDDAJBVTEWMBQGA1UECgwN" +
"Qm91bmN5IENhc3RsZRcNNzAwMTAxMDAwMDAwWhcNNzAwMTAxMDAwMDAyWjAiMCAC" +
"AQEXDTcwMDEwMTAwMDAwMVowDDAKBgNVHRUEAwoBCqCBxTCBwjBhBgNVHSMBAf8E" +
"VzBVgBQ2T3aRz8you6PBCaJJEFNrqgh0UaE6pDgwNjELMAkGA1UEAwwCQVUxFjAU" +
"BgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3QgMoIBAjBDBgNVHRIE" +
"PDA6pDgwNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzAN" +
"BgNVBAsMBlRlc3QgMzAKBgNVHRQEAwIBATAMBgNVHRwBAf8EAjAA");
private void tbsV1CertGen()
throws IOException
{
V1TBSCertificateGenerator gen = new V1TBSCertificateGenerator();
Date startDate = new Date(1000);
Date endDate = new Date(12000);
gen.setSerialNumber(new ASN1Integer(1));
gen.setStartDate(new Time(startDate));
gen.setEndDate(new Time(endDate));
gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
gen.setSubject(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 1"));
gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE),
new RSAPublicKey(BigInteger.valueOf(1), BigInteger.valueOf(2)));
gen.setSubjectPublicKeyInfo(info);
TBSCertificate tbs = gen.generateTBSCertificate();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
aOut.writeObject(tbs);
if (!Arrays.areEqual(bOut.toByteArray(), v1Cert))
{
fail("failed v1 cert generation");
}
ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v1Cert));
ASN1Primitive o = aIn.readObject();
bOut = new ByteArrayOutputStream();
aOut = new ASN1OutputStream(bOut);
aOut.writeObject(o);
if (!Arrays.areEqual(bOut.toByteArray(), v1Cert))
{
fail("failed v1 cert read back test");
}
}
private AuthorityKeyIdentifier createAuthorityKeyId(
SubjectPublicKeyInfo info,
X500Name name,
int sNumber)
{
GeneralName genName = new GeneralName(name);
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(genName);
return new AuthorityKeyIdentifier(
info, GeneralNames.getInstance(new DERSequence(v)), BigInteger.valueOf(sNumber));
}
private void tbsV3CertGen()
throws IOException
{
V3TBSCertificateGenerator gen = new V3TBSCertificateGenerator();
Date startDate = new Date(1000);
Date endDate = new Date(2000);
gen.setSerialNumber(new ASN1Integer(2));
gen.setStartDate(new Time(startDate));
gen.setEndDate(new Time(endDate));
gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
gen.setSubject(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"));
gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
gen.setSubjectPublicKeyInfo(info);
Extensions ex = new Extensions(new Extension[] {
new Extension(Extension.authorityKeyIdentifier, true, new DEROctetString(createAuthorityKeyId(info, new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2))),
new Extension(Extension.subjectKeyIdentifier, true, new DEROctetString(new SubjectKeyIdentifier(getDigest(info)))),
new Extension(Extension.keyUsage, false, new DEROctetString(new KeyUsage(KeyUsage.dataEncipherment)))
});
gen.setExtensions(ex);
TBSCertificate tbs = gen.generateTBSCertificate();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
aOut.writeObject(tbs);
if (!Arrays.areEqual(bOut.toByteArray(), v3Cert))
{
fail("failed v3 cert generation");
}
ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v3Cert));
ASN1Primitive o = aIn.readObject();
bOut = new ByteArrayOutputStream();
aOut = new ASN1OutputStream(bOut);
aOut.writeObject(o);
if (!Arrays.areEqual(bOut.toByteArray(), v3Cert))
{
fail("failed v3 cert read back test");
}
}
private void tbsV3CertGenWithNullSubject()
throws IOException
{
V3TBSCertificateGenerator gen = new V3TBSCertificateGenerator();
Date startDate = new Date(1000);
Date endDate = new Date(2000);
gen.setSerialNumber(new ASN1Integer(2));
gen.setStartDate(new Time(startDate));
gen.setEndDate(new Time(endDate));
gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.md5WithRSAEncryption, DERNull.INSTANCE));
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
gen.setSubjectPublicKeyInfo(info);
try
{
gen.generateTBSCertificate();
fail("null subject not caught!");
}
catch (IllegalStateException e)
{
if (!e.getMessage().equals("not all mandatory fields set in V3 TBScertificate generator"))
{
fail("unexpected exception", e);
}
}
Extensions ex = new Extensions(new Extension(Extension.subjectAlternativeName, true,
new DEROctetString(new GeneralNames(new GeneralName(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"))))));
gen.setExtensions(ex);
TBSCertificate tbs = gen.generateTBSCertificate();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
aOut.writeObject(tbs);
if (!Arrays.areEqual(bOut.toByteArray(), v3CertNullSubject))
{
fail("failed v3 null sub cert generation");
}
ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v3CertNullSubject));
ASN1Primitive o = aIn.readObject();
bOut = new ByteArrayOutputStream();
aOut = new ASN1OutputStream(bOut);
aOut.writeObject(o);
if (!Arrays.areEqual(bOut.toByteArray(), v3CertNullSubject))
{
fail("failed v3 null sub cert read back test");
}
}
private void tbsV2CertListGen()
throws IOException
{
V2TBSCertListGenerator gen = new V2TBSCertListGenerator();
gen.setIssuer(new X500Name("CN=AU,O=Bouncy Castle"));
gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), CRLReason.aACompromise);
gen.setNextUpdate(new Time(new Date(2000)));
gen.setThisUpdate(new Time(new Date(500)));
gen.setSignature(new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption, DERNull.INSTANCE));
SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(OIWObjectIdentifiers.elGamalAlgorithm, new ElGamalParameter(BigInteger.valueOf(1), BigInteger.valueOf(2))), new ASN1Integer(3));
ExtensionsGenerator extGen = new ExtensionsGenerator();
extGen.addExtension(Extension.authorityKeyIdentifier, true, createAuthorityKeyId(info, new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2));
extGen.addExtension(Extension.issuerAlternativeName, false, new GeneralNames(new GeneralName(new X500Name("CN=AU,O=Bouncy Castle,OU=Test 3"))));
extGen.addExtension(Extension.cRLNumber, false, new ASN1Integer(1));
extGen.addExtension(Extension.issuingDistributionPoint, true, IssuingDistributionPoint.getInstance(new DERSequence()));
Extensions ex = extGen.generate();
gen.setExtensions(ex);
TBSCertList tbs = gen.generateTBSCertList();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ASN1OutputStream aOut = new ASN1OutputStream(bOut);
aOut.writeObject(tbs);
if (!Arrays.areEqual(bOut.toByteArray(), v2CertList))
{
System.out.println(new String(Base64.encode(bOut.toByteArray())));
fail("failed v2 cert list generation");
}
ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(v2CertList));
ASN1Primitive o = aIn.readObject();
bOut = new ByteArrayOutputStream();
aOut = new ASN1OutputStream(bOut);
aOut.writeObject(o);
if (!Arrays.areEqual(bOut.toByteArray(), v2CertList))
{
fail("failed v2 cert list read back test");
}
gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), CRLReason.aACompromise);
gen.addCRLEntry(new ASN1Integer(2), new Time(new Date(1000)), CRLReason.affiliationChanged, new ASN1GeneralizedTime(new Date(2000)));
TBSCertList crl = gen.generateTBSCertList();
TBSCertList.CRLEntry[] entries = crl.getRevokedCertificates();
for (int i = 0; i != entries.length; i++)
{
TBSCertList.CRLEntry entry = entries[i];
if (entry.getUserCertificate().equals(new ASN1Integer(1)))
{
Extensions extensions = entry.getExtensions();
Extension ext = extensions.getExtension(Extension.reasonCode);
CRLReason r = CRLReason.getInstance(ext.getParsedValue());
if (r.getValue().intValue() != CRLReason.aACompromise)
{
fail("reason code mismatch");
}
}
else if (entry.getUserCertificate().equals(new ASN1Integer(2)))
{
Extensions extensions = entry.getExtensions();
Extension ext = extensions.getExtension(Extension.reasonCode);
CRLReason r = CRLReason.getInstance(ext.getParsedValue());
if (r.getValue().intValue() != CRLReason.affiliationChanged)
{
fail("reason code mismatch");
}
ext = extensions.getExtension(Extension.invalidityDate);
ASN1GeneralizedTime t = ASN1GeneralizedTime.getInstance(ext.getParsedValue());
try
{
if (!t.getDate().equals(new Date(2000)))
{
fail("invalidity date mismatch");
}
}
catch (ParseException e)
{
fail("can't parse date", e);
}
}
}
}
public void performTest()
throws Exception
{
tbsV1CertGen();
tbsV3CertGen();
tbsV3CertGenWithNullSubject();
tbsV2CertListGen();
}
public String getName()
{
return "Generation";
}
private static byte[] getDigest(SubjectPublicKeyInfo spki)
{
Digest digest = new SHA1Digest();
byte[] resBuf = new byte[digest.getDigestSize()];
byte[] bytes = spki.getPublicKeyData().getBytes();
digest.update(bytes, 0, bytes.length);
digest.doFinal(resBuf, 0);
return resBuf;
}
public static void main(
String[] args)
{
runTest(new GenerationTest());
}
}