summary refs log tree commit diff
path: root/crypto/test/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/test/src/util')
-rw-r--r--crypto/test/src/util/test/FixedSecureRandom.cs236
-rw-r--r--crypto/test/src/util/test/SimpleTest.cs6
-rw-r--r--crypto/test/src/util/test/TestRandomBigInteger.cs55
-rw-r--r--crypto/test/src/util/test/UncloseableStream.cs5
4 files changed, 301 insertions, 1 deletions
diff --git a/crypto/test/src/util/test/FixedSecureRandom.cs b/crypto/test/src/util/test/FixedSecureRandom.cs

index d8598ac24..1368aa231 100644 --- a/crypto/test/src/util/test/FixedSecureRandom.cs +++ b/crypto/test/src/util/test/FixedSecureRandom.cs
@@ -2,16 +2,90 @@ using System; using System.IO; using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Encoders; + +using M = Org.BouncyCastle.Math; namespace Org.BouncyCastle.Utilities.Test { public class FixedSecureRandom : SecureRandom { + private static readonly M.BigInteger REGULAR = new M.BigInteger("01020304ffffffff0506070811111111", 16); + private static readonly M.BigInteger ANDROID = new M.BigInteger("1111111105060708ffffffff01020304", 16); + private static readonly M.BigInteger CLASSPATH = new M.BigInteger("3020104ffffffff05060708111111", 16); + + private static readonly bool isAndroidStyle; + private static readonly bool isClasspathStyle; + private static readonly bool isRegularStyle; + + static FixedSecureRandom() + { + M.BigInteger check1 = new M.BigInteger(128, new RandomChecker()); + M.BigInteger check2 = new M.BigInteger(120, new RandomChecker()); + + isAndroidStyle = check1.Equals(ANDROID); + isRegularStyle = check1.Equals(REGULAR); + isClasspathStyle = check2.Equals(CLASSPATH); + } + private byte[] _data; private int _index; - protected FixedSecureRandom( + /** + * Base class for sources of fixed "Randomness" + */ + public class Source + { + internal byte[] data; + + internal Source(byte[] data) + { + this.data = data; + } + } + + /** + * Data Source - in this case we just expect requests for byte arrays. + */ + public class Data + : Source + { + public Data(byte[] data) + : base(data) + { + } + } + + /** + * BigInteger Source - in this case we expect requests for data that will be used + * for BigIntegers. The FixedSecureRandom will attempt to compensate for platform differences here. + */ + public class BigInteger + : Source + { + public BigInteger(byte[] data) + : base(data) + { + } + + public BigInteger(int bitLength, byte[] data) + : base(ExpandToBitLength(bitLength, data)) + { + } + + public BigInteger(string hexData) + : this(Hex.Decode(hexData)) + { + } + + public BigInteger(int bitLength, string hexData) + : base(ExpandToBitLength(bitLength, Hex.Decode(hexData))) + { + } + } + + protected FixedSecureRandom( byte[] data) { _data = data; @@ -38,6 +112,103 @@ namespace Org.BouncyCastle.Utilities.Test return new FixedSecureRandom(bOut.ToArray()); } + public FixedSecureRandom( + Source[] sources) + { + MemoryStream bOut = new MemoryStream(); + + if (isRegularStyle) + { + if (isClasspathStyle) + { + for (int i = 0; i != sources.Length; i++) + { + try + { + if (sources[i] is BigInteger) + { + byte[] data = sources[i].data; + int len = data.Length - (data.Length % 4); + for (int w = data.Length - len - 1; w >= 0; w--) + { + bOut.WriteByte(data[w]); + } + for (int w = data.Length - len; w < data.Length; w += 4) + { + bOut.Write(data, w, 4); + } + } + else + { + bOut.Write(sources[i].data, 0, sources[i].data.Length); + } + } + catch (IOException e) + { + throw new ArgumentException("can't save value source."); + } + } + } + else + { + for (int i = 0; i != sources.Length; i++) + { + try + { + bOut.Write(sources[i].data, 0, sources[i].data.Length); + } + catch (IOException e) + { + throw new ArgumentException("can't save value source."); + } + } + } + } + else if (isAndroidStyle) + { + for (int i = 0; i != sources.Length; i++) + { + try + { + if (sources[i] is BigInteger) + { + byte[] data = sources[i].data; + int len = data.Length - (data.Length % 4); + for (int w = 0; w < len; w += 4) + { + bOut.Write(data, data.Length - (w + 4), 4); + } + if (data.Length - len != 0) + { + for (int w = 0; w != 4 - (data.Length - len); w++) + { + bOut.WriteByte(0); + } + } + for (int w = 0; w != data.Length - len; w++) + { + bOut.WriteByte(data[len + w]); + } + } + else + { + bOut.Write(sources[i].data, 0, sources[i].data.Length); + } + } + catch (IOException e) + { + throw new ArgumentException("can't save value source."); + } + } + } + else + { + throw new InvalidOperationException("Unrecognized BigInteger implementation"); + } + + _data = bOut.ToArray(); + } + public override byte[] GenerateSeed(int numBytes) { return SecureRandom.GetNextBytes(this, numBytes); @@ -65,5 +236,68 @@ namespace Org.BouncyCastle.Utilities.Test { get { return _index == _data.Length; } } + + private class RandomChecker + : SecureRandom + { + byte[] data = Hex.Decode("01020304ffffffff0506070811111111"); + int index = 0; + + public override void NextBytes(byte[] bytes) + { + Array.Copy(data, index, bytes, 0, bytes.Length); + + index += bytes.Length; + } + } + + private static byte[] ExpandToBitLength(int bitLength, byte[] v) + { + if ((bitLength + 7) / 8 > v.Length) + { + byte[] tmp = new byte[(bitLength + 7) / 8]; + + Array.Copy(v, 0, tmp, tmp.Length - v.Length, v.Length); + if (isAndroidStyle) + { + if (bitLength % 8 != 0) + { + uint i = BE_To_UInt32(tmp, 0); + UInt32_To_BE(i << (8 - (bitLength % 8)), tmp, 0); + } + } + + return tmp; + } + else + { + if (isAndroidStyle && bitLength < (v.Length * 8)) + { + if (bitLength % 8 != 0) + { + uint i = BE_To_UInt32(v, 0); + UInt32_To_BE(i << (8 - (bitLength % 8)), v, 0); + } + } + } + + return v; + } + + internal static uint BE_To_UInt32(byte[] bs, int off) + { + return (uint)bs[off] << 24 + | (uint)bs[off + 1] << 16 + | (uint)bs[off + 2] << 8 + | (uint)bs[off + 3]; + } + + internal static void UInt32_To_BE(uint n, byte[] bs, int off) + { + bs[off] = (byte)(n >> 24); + bs[off + 1] = (byte)(n >> 16); + bs[off + 2] = (byte)(n >> 8); + bs[off + 3] = (byte)(n); + } } } diff --git a/crypto/test/src/util/test/SimpleTest.cs b/crypto/test/src/util/test/SimpleTest.cs
index 1639431cc..45b8a6a06 100644 --- a/crypto/test/src/util/test/SimpleTest.cs +++ b/crypto/test/src/util/test/SimpleTest.cs
@@ -27,6 +27,12 @@ namespace Org.BouncyCastle.Utilities.Test throw new TestFailedException(SimpleTestResult.Failed(this, message)); } + internal void IsTrue(bool value) + { + if (!value) + throw new TestFailedException(SimpleTestResult.Failed(this, "no message")); + } + internal void IsTrue(string message, bool value) { if (!value) diff --git a/crypto/test/src/util/test/TestRandomBigInteger.cs b/crypto/test/src/util/test/TestRandomBigInteger.cs new file mode 100644
index 000000000..ef38293b9 --- /dev/null +++ b/crypto/test/src/util/test/TestRandomBigInteger.cs
@@ -0,0 +1,55 @@ +using System; + +using M = Org.BouncyCastle.Math; + +namespace Org.BouncyCastle.Utilities.Test +{ + /** + * A fixed secure random designed to return data for someone needing to create a single BigInteger. + */ + public class TestRandomBigInteger + : FixedSecureRandom + { + /** + * Constructor from a base 10 represention of a BigInteger. + * + * @param encoding a base 10 represention of a BigInteger. + */ + public TestRandomBigInteger(string encoding) + : this(encoding, 10) + { + } + + /** + * Constructor from a base radix represention of a BigInteger. + * + * @param encoding a String BigInteger of base radix. + * @param radix the radix to use. + */ + public TestRandomBigInteger(string encoding, int radix) + : base(new FixedSecureRandom.Source[] { new FixedSecureRandom.BigInteger(BigIntegers.AsUnsignedByteArray(new M.BigInteger(encoding, radix))) }) + { + } + + /** + * Constructor based on a byte array. + * + * @param encoding a 2's complement representation of the BigInteger. + */ + public TestRandomBigInteger(byte[] encoding) + : base(new FixedSecureRandom.Source[] { new FixedSecureRandom.BigInteger(encoding) }) + { + } + + /** + * Constructor which ensures encoding will produce a BigInteger from a request from the passed in bitLength. + * + * @param bitLength bit length for the BigInteger data request. + * @param encoding bytes making up the encoding. + */ + public TestRandomBigInteger(int bitLength, byte[] encoding) + : base(new FixedSecureRandom.Source[] { new FixedSecureRandom.BigInteger(bitLength, encoding) }) + { + } + } +} diff --git a/crypto/test/src/util/test/UncloseableStream.cs b/crypto/test/src/util/test/UncloseableStream.cs
index 2a3b4229b..0a7a16e66 100644 --- a/crypto/test/src/util/test/UncloseableStream.cs +++ b/crypto/test/src/util/test/UncloseableStream.cs
@@ -5,6 +5,11 @@ using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Utilities.Test { + /// <summary> + /// This is a testing utility class to check the property that a <c>Stream</c> is never + /// closed in some particular context - typically when wrapped by another <c>Stream</c> that + /// should not be forwarding its <c>Stream.Close()</c> calls. Not needed in production code. + /// </summary> public class UncloseableStream : FilterStream {