2 // RandomNumberGeneratorTest.cs - NUnit Test Cases for RNG
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
10 using NUnit.Framework;
13 using System.Security.Cryptography;
16 namespace MonoTests.System.Security.Cryptography {
19 // a. NIST FIPS PUB 140-2: Security requirements for Cryptographic Modules
20 // http://csrc.nist.gov/publications/fips/fips140-2/fips1402.pdf
21 // b. NIST SP 800-22: A Statistical Test Suite for Random and Pseudorandom Number Generators for Cryptographic Applications
23 // http://csrc.nist.gov/publications/nistpubs/800-22/sp-800-22-051501.pdf
24 // c. IETF RFC1750: Randomness Recommendations for Security
26 // http://www.ietf.org/rfc/rfc1750.txt
28 public class RandomNumberGeneratorTest : TestCase {
29 protected RandomNumberGenerator rng;
31 protected override void SetUp ()
33 rng = RandomNumberGenerator.Create();
36 protected override void TearDown () {}
38 public void AssertEquals (string msg, byte[] array1, byte[] array2)
40 AllTests.AssertEquals (msg, array1, array2);
43 // count the number of 1
44 protected void Monobit (string rngName, byte[] sample)
47 for (int i=0; i < sample.Length; i++) {
49 for (int j = 0; j < 8; j++) {
50 if ((b & 0x01) == 0x01)
56 Assert (rngName + " Monobit x=" + x, ((9725 < x) && (x < 10275)));
59 // 16 patterns (nibbles)
60 protected void Poker (string rngName, byte[] sample)
62 int[] pattern = new int[16];
63 for (int i = 0; i < sample.Length; i++) {
72 for (int i = 0; i < 16; i++)
73 result += (pattern[i] * pattern[i]);
74 result = ((16 * result) / 5000) - 5000;
75 Assert (rngName + " Poker: " + result, ((result > 2.16) && (result < 46.17)));
79 protected void Runs (string rngName, byte[] sample)
81 int[] runs = new int[6];
85 for (int i = sample.Length - 1; i >= 0 ; i--) {
87 for (int j = 0; j < 8; j++) {
88 if ((b & 0x01) == 0x01) {
92 int p = Math.Min (x, 6) - 1;
102 /*int p = Math.Min (x, 6) - 1;
113 Assert (rngName + " Runs length=1: " + runs[0], ((runs[0] >= 2343) && (runs[0] <= 2657)));
114 Assert (rngName + " Runs length=2: " + runs[1], ((runs[1] >= 1135) && (runs[1] <= 1365)));
115 Assert (rngName + " Runs length=3: " + runs[2], ((runs[2] >= 542) && (runs[2] <= 708)));
116 Assert (rngName + " Runs length=4: " + runs[3], ((runs[3] >= 251) && (runs[3] <= 373)));
117 Assert (rngName + " Runs length=5: " + runs[4], ((runs[4] >= 111) && (runs[4] <= 201)));
118 Assert (rngName + " Runs length=6+ " + runs[5], ((runs[5] >= 111) && (runs[5] <= 201)));
121 // no long runs of 26 or more (0 or 1)
122 protected void LongRuns (string rngName, byte[] sample)
128 for (int i = sample.Length - 1; i >= 0 ; i--) {
130 for (int j = 0; j < 8; j++) {
131 if ((b & 0x01) == 0x01) {
135 longestRun = Math.Max (longestRun, currentRun);
144 longestRun = Math.Max (longestRun, currentRun);
153 Assert (rngName + " Long Runs max = " + longestRun, (longestRun < 26));
156 // all tests should be done on the same random sample
157 public void TestFIPS140()
159 string name = rng.ToString();
161 byte[] sample = new byte[2500];
162 rng.GetBytes (sample);
164 Monobit (name, sample);
165 Poker (name, sample);
167 LongRuns (name, sample);