Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

rng.cpp

00001 // rng.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "rng.h"
00005 
00006 #include <time.h>
00007 #include <math.h>
00008 
00009 NAMESPACE_BEGIN(CryptoPP)
00010 
00011 // linear congruential generator
00012 // originally by William S. England
00013 
00014 // do not use for cryptographic purposes
00015 
00016 /*
00017 ** Original_numbers are the original published m and q in the
00018 ** ACM article above.  John Burton has furnished numbers for
00019 ** a reportedly better generator.  The new numbers are now
00020 ** used in this program by default.
00021 */
00022 
00023 #ifndef LCRNG_ORIGINAL_NUMBERS
00024 const word32 LC_RNG::m=2147483647L;
00025 const word32 LC_RNG::q=44488L;
00026 
00027 const word16 LC_RNG::a=(unsigned int)48271L;
00028 const word16 LC_RNG::r=3399;
00029 #else
00030 const word32 LC_RNG::m=2147483647L;
00031 const word32 LC_RNG::q=127773L;
00032 
00033 const word16 LC_RNG::a=16807;
00034 const word16 LC_RNG::r=2836;
00035 #endif
00036 
00037 byte LC_RNG::GenerateByte()
00038 {
00039         word32 hi = seed/q;
00040         word32 lo = seed%q;
00041 
00042         long test = a*lo - r*hi;
00043 
00044         if (test > 0)
00045                 seed = test;
00046         else
00047                 seed = test+ m;
00048 
00049         return (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3));
00050 }
00051 
00052 // ********************************************************
00053 
00054 X917RNG::X917RNG(BlockTransformation *c, const byte *seed, unsigned long deterministicTimeVector)
00055         : cipher(c),
00056           S(cipher->BlockSize()),
00057           dtbuf(S),
00058           randseed(seed, S),
00059           randbuf(S),
00060           randbuf_counter(0),
00061           m_deterministicTimeVector(deterministicTimeVector)
00062 {
00063         if (m_deterministicTimeVector)
00064         {
00065                 memset(dtbuf, 0, S);
00066                 memcpy(dtbuf, (byte *)&m_deterministicTimeVector, STDMIN((int)sizeof(m_deterministicTimeVector), S));
00067         }
00068         else
00069         {
00070                 time_t tstamp1 = time(0);
00071                 xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S));
00072                 cipher->ProcessBlock(dtbuf);
00073                 clock_t tstamp2 = clock();
00074                 xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S));
00075                 cipher->ProcessBlock(dtbuf);
00076         }
00077 }
00078 
00079 byte X917RNG::GenerateByte()
00080 {
00081         if (randbuf_counter==0)
00082         {
00083                 // calculate new enciphered timestamp
00084                 if (m_deterministicTimeVector)
00085                 {
00086                         xorbuf(dtbuf, (byte *)&m_deterministicTimeVector, STDMIN((int)sizeof(m_deterministicTimeVector), S));
00087                         while (++m_deterministicTimeVector == 0) {}     // skip 0
00088                 }
00089                 else
00090                 {
00091                         clock_t tstamp = clock();
00092                         xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S));
00093                 }
00094                 cipher->ProcessBlock(dtbuf);
00095 
00096                 // combine enciphered timestamp with seed
00097                 xorbuf(randseed, dtbuf, S);
00098 
00099                 // generate a new block of random bytes
00100                 cipher->ProcessBlock(randseed, randbuf);
00101 
00102                 // compute new seed vector
00103                 for (int i=0; i<S; i++)
00104                         randseed[i] = randbuf[i] ^ dtbuf[i];
00105                 cipher->ProcessBlock(randseed);
00106 
00107                 randbuf_counter=S;
00108         }
00109         return(randbuf[--randbuf_counter]);
00110 }
00111 
00112 MaurerRandomnessTest::MaurerRandomnessTest()
00113         : sum(0.0), n(0)
00114 {
00115         for (unsigned i=0; i<V; i++)
00116                 tab[i] = 0;
00117 }
00118 
00119 inline void MaurerRandomnessTest::Put(byte inByte)
00120 {
00121         if (n >= Q)
00122                 sum += log(double(n - tab[inByte]));
00123         tab[inByte] = n;
00124         n++;
00125 }
00126 
00127 void MaurerRandomnessTest::Put(const byte *inString, unsigned int length)
00128 {
00129         while (length--)
00130                 Put(*inString++);
00131 }
00132 
00133 double MaurerRandomnessTest::GetTestValue() const
00134 {
00135         double fTu = (sum/(n-Q))/log(2.0);      // this is the test value defined by Maurer
00136 
00137         double value = fTu * 0.1392;            // arbitrarily normalize it to
00138         return value > 1.0 ? 1.0 : value;       // a number between 0 and 1
00139 }
00140 
00141 NAMESPACE_END

Generated on Sun Mar 14 20:44:28 2004 for Crypto++ by doxygen 1.3.6-20040222