[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnetlib/tests/runtime/System/Security/Cryptog
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnetlib/tests/runtime/System/Security/Cryptography TestRNG.cs,NONE,1.1 CryptoTestCase.cs,1.3,1.4 TestCryptography.cs,1.1,1.2 |
Date: |
Tue, 26 Nov 2002 21:13:24 -0500 |
Update of
/cvsroot/dotgnu-pnet/pnetlib/tests/runtime/System/Security/Cryptography
In directory
subversions:/tmp/cvs-serv23898/tests/runtime/System/Security/Cryptography
Modified Files:
CryptoTestCase.cs TestCryptography.cs
Added Files:
TestRNG.cs
Log Message:
Implement cryptography tests and fixes that involve random number generation.
--- NEW FILE ---
/*
* TestRNG.cs - Test the random number generator.
*
* Copyright (C) 2002 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
using CSUnit;
using System;
using System.Security.Cryptography;
public class TestRNG : TestCase
{
// Internal state.
private static byte[] randomBits;
// Constructor.
public TestRNG(String name)
: base(name)
{
// Nothing to do here.
}
// Set up for the tests.
protected override void Setup()
{
// Nothing to do here.
}
// Clean up after the tests.
protected override void Cleanup()
{
// Nothing to do here.
}
// Test that the random number generator actually works by seeing
// if it generates non-zero byte streams. There is a small non-zero
// probability that a working random number generator will in fact
// generate an all-zero stream, but since that is about 1^-128, the
// chances of it happening by accident are quite rare.
public void TestRNGWorks()
{
if(!CryptoTestCase.RandomWorks())
{
Fail("random number generator does not
work");
}
}
// Check that "GetNonZeroBytes" does indeed do that. We generate
// a large amount of random material to increase the chance that
// the underlying generator will generate a zero which needs to
// be corrected by "GetNonZeroBytes". If the random number
// generator doesn't work at all, we avoid running this test so
// that we don't get an infinite loop inside the library.
public void TestRNGNonZeroWorks()
{
if(CryptoTestCase.RandomWorks())
{
int round;
int index;
byte[] rand = new byte [16384];
RandomNumberGenerator rng =
RandomNumberGenerator.Create();
for(round = 0; round < 32; ++round)
{
rng.GetNonZeroBytes(rand);
for(index = 0; index < 16;
++index)
{
if(rand[index] == 0x00)
{
Fail("zero byte
found in generated stream");
}
}
}
}
}
// The following tests are based on the statistical testing requirements
// for cryptographic random number generators from NIST:
//
// NIST FIPS PUB 140-2: Security requirements for Cryptographic Modules
// http://csrc.nist.gov/publications/fips/fips140-2/fips1402.pdf
//
// There are lots of other statistical tests in the following NIST
// standard, which we haven't implement yet due to their complexity:
//
// NIST SP 800-22: A Statistical Test Suite for Random and Pseudorandom
// Number Generators for Cryptographic Applications
//
http://csrc.nist.gov/publications/nistpubs/800-22/sp-800-22-051501.pdf
// Perform the NIST "monobit" test.
public void TestRNGBit()
{
// Generate 20,000 bits of random material,
which we
// will also be using for the later NIST tests.
randomBits = new byte [20000 / 8];
RandomNumberGenerator rng =
RandomNumberGenerator.Create();
rng.GetBytes(randomBits);
// Count the number of 1 bits in the vector.
int count = 0;
int bit;
for(bit = 0; bit < 20000; ++bit)
{
if((randomBits[bit / 8] & (1 << (bit &
7))) != 0)
{
++count;
}
}
// Determine if there is a sufficient number of
0's and 1's.
if(count <= 9725)
{
Fail("insufficient number of 1's in the
stream");
}
else if(count >= 10275)
{
Fail("insufficient number of 0's in the
stream");
}
}
// Perform the NIST "poker" test.
public void TestRNGPoker()
{
// Count the occurrences of each 4-bit value.
int[] counts = new int [16];
int posn;
for(posn = 0; posn < (20000 / 8); ++posn)
{
++(counts[randomBits[posn] & 0x0F]);
++(counts[(randomBits[posn] >> 4) &
0x0F]);
}
// Compute the co-efficient and check it.
double sum = 0.0;
for(posn = 0; posn < 16; ++posn)
{
sum += ((double)(counts[posn])) *
((double)(counts[posn]));
}
double coeff = (16.0 / 5000.0) * sum - 5000.0;
if(coeff <= 2.16 || coeff >= 46.17)
{
Fail("incorrect poker value");
}
}
// Perform the NIST "runs" and "longruns" tests in one pass.
public void TestRNGRuns()
{
// Count the length of the runs within the
stream.
int[] counts0 = new int [6];
int[] counts1 = new int [6];
int bit;
int prev = -1;
int value, count;
count = 0;
for(bit = 0; bit < 20000; ++bit)
{
if((randomBits[bit / 8] & (1 << (bit &
7))) != 0)
{
value = 1;
}
else
{
value = 0;
}
if(prev != value)
{
if(prev != -1)
{
if(count < 6)
{
if(value != 0)
{
++(counts1[count - 1]);
}
else
{
++(counts0[count - 1]);
}
}
else
{
if(value != 0)
{
++(counts1[5]);
}
else
{
++(counts0[5]);
}
if(count >= 26)
{
Fail("long run detected");
}
}
count = 1;
prev = value;
}
else
{
prev = value;
++count;
}
}
else
{
++count;
}
}
if(count < 6)
{
if(value != 0)
{
++(counts1[count - 1]);
}
else
{
++(counts0[count - 1]);
}
}
else
{
if(value != 0)
{
++(counts1[5]);
}
else
{
++(counts0[5]);
}
if(count >= 26)
{
Fail("long run detected");
}
}
// Determine if the run lengths are within
// the required ranges.
if(counts0[0] < 2315 || counts0[0] > 2685)
{
Fail("too many or too few 0 runs of
length 1");
}
if(counts1[0] < 2315 || counts1[0] > 2685)
{
Fail("too many or too few 1 runs of
length 1");
}
if(counts0[1] < 1114 || counts0[1] > 1386)
{
Fail("too many or too few 0 runs of
length 2");
}
if(counts1[1] < 1114 || counts1[1] > 1386)
{
Fail("too many or too few 1 runs of
length 2");
}
if(counts0[2] < 527 || counts0[2] > 723)
{
Fail("too many or too few 0 runs of
length 3");
}
if(counts1[2] < 527 || counts1[2] > 723)
{
Fail("too many or too few 1 runs of
length 3");
}
if(counts0[3] < 240 || counts0[3] > 384)
{
Fail("too many or too few 0 runs of
length 4");
}
if(counts1[3] < 240 || counts1[3] > 384)
{
Fail("too many or too few 1 runs of
length 4");
}
if(counts0[4] < 103 || counts0[4] > 209)
{
Fail("too many or too few 0 runs of
length 5");
}
if(counts1[4] < 103 || counts1[4] > 209)
{
Fail("too many or too few 1 runs of
length 5");
}
if(counts0[5] < 103 || counts0[5] > 209)
{
Fail("too many or too few 0 runs of
length 6+");
}
if(counts1[5] < 103 || counts1[5] > 209)
{
Fail("too many or too few 1 runs of
length 6+");
}
}
}; // TestRNG
Index: CryptoTestCase.cs
===================================================================
RCS file:
/cvsroot/dotgnu-pnet/pnetlib/tests/runtime/System/Security/Cryptography/CryptoTestCase.cs,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -r1.3 -r1.4
*** CryptoTestCase.cs 26 Nov 2002 11:52:00 -0000 1.3
--- CryptoTestCase.cs 27 Nov 2002 02:13:22 -0000 1.4
***************
*** 64,67 ****
--- 64,86 ----
}
+ // Determine if the random number generator appears to be working.
+ // We use this before calling "GenerateKey" for "DES" and "TripleDES",
+ // to prevent infinite loops in the test suite.
+ public static bool RandomWorks()
+ {
+ int index;
+ byte[] rand = new byte [16];
+ RandomNumberGenerator rng =
RandomNumberGenerator.Create();
+ rng.GetBytes(rand);
+ for(index = 0; index < 16; ++index)
+ {
+ if(rand[index] != 0x00)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
// Run a symmetric algorithm test.
protected void RunSymmetric(SymmetricAlgorithm alg, byte[] key,
***************
*** 258,270 ****
// Check the initial property values.
AssertEquals("initial key size is incorrect",
! alg.KeySize,
expectedKeySize);
AssertEquals("initial block size is incorrect",
! alg.BlockSize,
expectedBlockSize);
AssertEquals("initial feedback block size is
incorrect",
! alg.FeedbackSize,
expectedBlockSize);
AssertEquals("initial cipher mode is incorrect",
! alg.Mode,
CipherMode.CBC);
AssertEquals("initial padding mode is
incorrect",
! alg.Padding,
PaddingMode.PKCS7);
AssertNotNull("legal key size array is null",
alg.LegalKeySizes);
--- 277,289 ----
// Check the initial property values.
AssertEquals("initial key size is incorrect",
! expectedKeySize,
alg.KeySize);
AssertEquals("initial block size is incorrect",
! expectedBlockSize,
alg.BlockSize);
AssertEquals("initial feedback block size is
incorrect",
! expectedBlockSize,
alg.FeedbackSize);
AssertEquals("initial cipher mode is incorrect",
! CipherMode.CBC,
alg.Mode);
AssertEquals("initial padding mode is
incorrect",
! PaddingMode.PKCS7,
alg.Padding);
AssertNotNull("legal key size array is null",
alg.LegalKeySizes);
***************
*** 280,284 ****
// TODO: Try setting the key size to all legal
values.
! // TODO: check automatic key and IV generation
}
--- 299,317 ----
// TODO: Try setting the key size to all legal
values.
! // Check automatic key and IV generation. If
the random
! // number generator doesn't work, then skip the
test for
! // DES and TripleDES, to prevent an infinite
loop within
! // those algorithm's weak key checking code.
! if((!(alg is DES) && !(alg is TripleDES)) ||
RandomWorks())
! {
! byte[] key = alg.Key;
! AssertNotNull("generated key should not
be null", key);
! AssertEquals("generated key is the
wrong size",
! alg.KeySize,
key.Length * 8);
! byte[] iv = alg.IV;
! AssertNotNull("generated IV should not
be null", iv);
! AssertEquals("generated IV is the wrong
size",
! alg.BlockSize,
iv.Length * 8);
! }
}
Index: TestCryptography.cs
===================================================================
RCS file:
/cvsroot/dotgnu-pnet/pnetlib/tests/runtime/System/Security/Cryptography/TestCryptography.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** TestCryptography.cs 22 Nov 2002 00:17:48 -0000 1.1
--- TestCryptography.cs 27 Nov 2002 02:13:22 -0000 1.2
***************
*** 37,40 ****
--- 37,41 ----
suite.AddTests(typeof(TestSHA384));
suite.AddTests(typeof(TestSHA512));
+ suite.AddTests(typeof(TestRNG));
return suite;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnetlib/tests/runtime/System/Security/Cryptography TestRNG.cs,NONE,1.1 CryptoTestCase.cs,1.3,1.4 TestCryptography.cs,1.1,1.2,
Rhys Weatherley <address@hidden> <=
- Prev by Date:
[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Security/Cryptography RijndaelManaged.cs,1.1,1.2 TripleDESCryptoServiceProvider.cs,1.1,1.2
- Next by Date:
[Dotgnu-pnet-commits] CVS: pnetlib/System/Net IPAddress.cs,1.8,1.9
- Previous by thread:
[Dotgnu-pnet-commits] CVS: pnetlib/runtime/System/Security/Cryptography RijndaelManaged.cs,1.1,1.2 TripleDESCryptoServiceProvider.cs,1.1,1.2
- Next by thread:
[Dotgnu-pnet-commits] CVS: pnetlib/System/Net IPAddress.cs,1.8,1.9
- Index(es):