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

# 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, unsigned long 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)
    00065 {
    00066         if (m_deterministicTimeVector)
    00067         {
    00068                 memset(dtbuf, 0, S);
    00069                 memcpy(dtbuf, (byte *)&m_deterministicTimeVector, STDMIN((int)sizeof(m_deterministicTimeVector), S));
    00070         }
    00071         else
    00072         {
    00073                 time_t tstamp1 = time(0);
    00074                 xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S));
    00075                 cipher->ProcessBlock(dtbuf);
    00076                 clock_t tstamp2 = clock();
    00077                 xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S));
    00078                 cipher->ProcessBlock(dtbuf);
    00079         }
    00080 }
    00081
    00082 byte X917RNG::GenerateByte()
    00083 {
    00084         if (randbuf_counter==0)
    00085         {
    00086                 // calculate new enciphered timestamp
    00087                 if (m_deterministicTimeVector)
    00088                 {
    00089                         xorbuf(dtbuf, (byte *)&m_deterministicTimeVector, STDMIN((int)sizeof(m_deterministicTimeVector), S));
    00090                         while (++m_deterministicTimeVector == 0) {}     // skip 0
    00091                 }
    00092                 else
    00093                 {
    00094                         clock_t tstamp = clock();
    00095                         xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S));
    00096                 }
    00097                 cipher->ProcessBlock(dtbuf);
    00098
    00099                 // combine enciphered timestamp with seed
    00100                 xorbuf(randseed, dtbuf, S);
    00101
    00102                 // generate a new block of random bytes
    00103                 cipher->ProcessBlock(randseed, randbuf);
    00104
    00105                 // compute new seed vector
    00106                 for (int i=0; i<S; i++)
    00107                         randseed[i] = randbuf[i] ^ dtbuf[i];
    00108                 cipher->ProcessBlock(randseed);
    00109
    00110                 randbuf_counter=S;
    00111         }
    00112         return(randbuf[--randbuf_counter]);
    00113 }
    00114
    00115 #endif
    00116
    00117 MaurerRandomnessTest::MaurerRandomnessTest()
    00118         : sum(0.0), n(0)
    00119 {
    00120         for (unsigned i=0; i<V; i++)
    00121                 tab[i] = 0;
    00122 }
    00123
    00124 inline void MaurerRandomnessTest::Put(byte inByte)
    00125 {
    00126         if (n >= Q)
    00127                 sum += log(double(n - tab[inByte]));
    00128         tab[inByte] = n;
    00129         n++;
    00130 }
    00131
    00132 void MaurerRandomnessTest::Put(const byte *inString, unsigned int length)
    00133 {
    00134         while (length--)
    00135                 Put(*inString++);
    00136 }
    00137
    00138 double MaurerRandomnessTest::GetTestValue() const
    00139 {
    00140         double fTu = (sum/(n-Q))/log(2.0);      // this is the test value defined by Maurer
    00141
    00142         double value = fTu * 0.1392;            // arbitrarily normalize it to
    00143         return value > 1.0 ? 1.0 : value;       // a number between 0 and 1
    00144 }
    00145
    00146 NAMESPACE_END