diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/asn1/test/GenerationTest.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/asn1/test/GenerationTest.java | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/asn1/test/GenerationTest.java b/bcprov/src/main/java/org/bouncycastle/asn1/test/GenerationTest.java new file mode 100644 index 0000000..aa5444f --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/asn1/test/GenerationTest.java @@ -0,0 +1,441 @@ +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 java.util.Hashtable; +import java.util.Vector; + +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.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.RSAPublicKeyStructure; +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.asn1.x509.X509Extension; +import org.bouncycastle.asn1.x509.X509Extensions; +import org.bouncycastle.asn1.x509.X509Name; +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 RSAPublicKeyStructure(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"); + } + + // + // read back test + // + 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); + + // + // add extensions + // + Vector order = new Vector(); + Hashtable extensions = new Hashtable(); + + order.addElement(X509Extension.authorityKeyIdentifier); + order.addElement(X509Extension.subjectKeyIdentifier); + order.addElement(X509Extension.keyUsage); + + extensions.put(X509Extension.authorityKeyIdentifier, new X509Extension(true, new DEROctetString(createAuthorityKeyId(info, new X500Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2)))); + extensions.put(X509Extension.subjectKeyIdentifier, new X509Extension(true, new DEROctetString(new SubjectKeyIdentifier(getDigest(info))))); + extensions.put(X509Extension.keyUsage, new X509Extension(false, new DEROctetString(new KeyUsage(KeyUsage.dataEncipherment)))); + + X509Extensions ex = new X509Extensions(order, extensions); + + 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"); + } + + // + // read back test + // + 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); + } + } + + // + // add extensions + // + Vector order = new Vector(); + Hashtable extensions = new Hashtable(); + + order.addElement(X509Extension.subjectAlternativeName); + + extensions.put(X509Extension.subjectAlternativeName, new X509Extension(true, new DEROctetString(new GeneralNames(new GeneralName(new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2")))))); + + X509Extensions ex = new X509Extensions(order, extensions); + + 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"); + } + + // + // read back test + // + 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)); + + // + // extensions + // + 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"); + } + + // + // read back test + // + 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"); + } + + // + // check we can add a custom reason + // + gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), CRLReason.aACompromise); + + // + // check invalidity date + 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()); + } +} |