- Main Page
- Namespaces
- Classes
- Files

- File List
- 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, 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