rng.cpp

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

Generated on Sat Dec 23 02:07:10 2006 for Crypto++ by  doxygen 1.5.1-p1