diff options
3 files changed, 194 insertions, 4 deletions
diff --git a/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java b/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java index 388ca30d..869f5bc5 100644 --- a/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java +++ b/src/main/java/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java @@ -149,7 +149,7 @@ public class V2TBSCertListGenerator if (invalidityDate != null) { - v.add(createInvalidityDateExtension(revocationDate)); + v.add(createInvalidityDateExtension(invalidityDate)); } internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v)); @@ -158,7 +158,7 @@ public class V2TBSCertListGenerator { ASN1EncodableVector v = new ASN1EncodableVector(); - v.add(createInvalidityDateExtension(revocationDate)); + v.add(createInvalidityDateExtension(invalidityDate)); internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v)); } @@ -262,7 +262,7 @@ public class V2TBSCertListGenerator return new DERSequence(v); } - private static ASN1Sequence createInvalidityDateExtension(Time invalidityDate) + private static ASN1Sequence createInvalidityDateExtension(ASN1GeneralizedTime invalidityDate) { ASN1EncodableVector v = new ASN1EncodableVector(); diff --git a/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java b/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java new file mode 100644 index 00000000..209b5e21 --- /dev/null +++ b/src/main/java/org/bouncycastle/crypto/prng/FixedSecureRandom.java @@ -0,0 +1,135 @@ +package org.bouncycastle.crypto.prng; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.SecureRandom; + +public class FixedSecureRandom + extends SecureRandom +{ + private byte[] _data; + + private int _index; + private int _intPad; + + public FixedSecureRandom(byte[] value) + { + this(false, new byte[][] { value }); + } + + public FixedSecureRandom( + byte[][] values) + { + this(false, values); + } + + /** + * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger + * implementation. + */ + public FixedSecureRandom( + boolean intPad, + byte[] value) + { + this(intPad, new byte[][] { value }); + } + + /** + * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger + * implementation. + */ + public FixedSecureRandom( + boolean intPad, + byte[][] values) + { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + for (int i = 0; i != values.length; i++) + { + try + { + bOut.write(values[i]); + } + catch (IOException e) + { + throw new IllegalArgumentException("can't save value array."); + } + } + + _data = bOut.toByteArray(); + + if (intPad) + { + _intPad = _data.length % 4; + } + } + + public void nextBytes(byte[] bytes) + { + System.arraycopy(_data, _index, bytes, 0, bytes.length); + + _index += bytes.length; + } + + // + // classpath's implementation of SecureRandom doesn't currently go back to nextBytes + // when next is called. We can't override next as it's a final method. + // + public int nextInt() + { + int val = 0; + + val |= nextValue() << 24; + val |= nextValue() << 16; + + if (_intPad == 2) + { + _intPad--; + } + else + { + val |= nextValue() << 8; + } + + if (_intPad == 1) + { + _intPad--; + } + else + { + val |= nextValue(); + } + + return val; + } + + // + // classpath's implementation of SecureRandom doesn't currently go back to nextBytes + // when next is called. We can't override next as it's a final method. + // + public long nextLong() + { + long val = 0; + + val |= (long)nextValue() << 56; + val |= (long)nextValue() << 48; + val |= (long)nextValue() << 40; + val |= (long)nextValue() << 32; + val |= (long)nextValue() << 24; + val |= (long)nextValue() << 16; + val |= (long)nextValue() << 8; + val |= (long)nextValue(); + + return val; + } + + public boolean isExhausted() + { + return _index == _data.length; + } + + private int nextValue() + { + return _data[_index++] & 0xff; + } +} diff --git a/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java b/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java index 7d4f7497..5c122a69 100644 --- a/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java +++ b/src/test/java/org/bouncycastle/asn1/test/GenerationTest.java @@ -4,11 +4,13 @@ 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; @@ -348,7 +350,60 @@ public class GenerationTest // // check we can add a custom reason // - gen.addCRLEntry(new ASN1Integer(1), new Time(new Date(1000)), 128); + 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() |