1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
// rng.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#include "rng.h"
#include <time.h>
#include <math.h>
NAMESPACE_BEGIN(CryptoPP)
// linear congruential generator
// originally by William S. England
// do not use for cryptographic purposes
/*
** Original_numbers are the original published m and q in the
** ACM article above. John Burton has furnished numbers for
** a reportedly better generator. The new numbers are now
** used in this program by default.
*/
#ifndef LCRNG_ORIGINAL_NUMBERS
const word32 LC_RNG::m=2147483647L;
const word32 LC_RNG::q=44488L;
const word16 LC_RNG::a=(unsigned int)48271L;
const word16 LC_RNG::r=3399;
#else
const word32 LC_RNG::m=2147483647L;
const word32 LC_RNG::q=127773L;
const word16 LC_RNG::a=16807;
const word16 LC_RNG::r=2836;
#endif
byte LC_RNG::GenerateByte()
{
word32 hi = seed/q;
word32 lo = seed%q;
long test = a*lo - r*hi;
if (test > 0)
seed = test;
else
seed = test+ m;
return (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3));
}
// ********************************************************
X917RNG::X917RNG(BlockTransformation *c, const byte *seed)
: cipher(c),
S(cipher->BlockSize()),
dtbuf(S),
randseed(seed, S),
randbuf(S),
randbuf_counter(0)
{
time_t tstamp1 = time(0);
xorbuf(dtbuf, (byte *)&tstamp1, STDMIN((int)sizeof(tstamp1), S));
cipher->ProcessBlock(dtbuf);
clock_t tstamp2 = clock();
xorbuf(dtbuf, (byte *)&tstamp2, STDMIN((int)sizeof(tstamp2), S));
cipher->ProcessBlock(dtbuf);
}
byte X917RNG::GenerateByte()
{
if (randbuf_counter==0)
{
// calculate new enciphered timestamp
clock_t tstamp = clock();
xorbuf(dtbuf, (byte *)&tstamp, STDMIN((int)sizeof(tstamp), S));
cipher->ProcessBlock(dtbuf);
// combine enciphered timestamp with seed
xorbuf(randseed, dtbuf, S);
// generate a new block of random bytes
cipher->ProcessBlock(randseed, randbuf);
// compute new seed vector
for (int i=0; i<S; i++)
randseed[i] = randbuf[i] ^ dtbuf[i];
cipher->ProcessBlock(randseed);
randbuf_counter=S;
}
return(randbuf[--randbuf_counter]);
}
MaurerRandomnessTest::MaurerRandomnessTest()
: sum(0.0), n(0)
{
for (unsigned i=0; i<V; i++)
tab[i] = 0;
}
inline void MaurerRandomnessTest::Put(byte inByte)
{
if (n >= Q)
sum += log(double(n - tab[inByte]));
tab[inByte] = n;
n++;
}
void MaurerRandomnessTest::Put(const byte *inString, unsigned int length)
{
while (length--)
Put(*inString++);
}
double MaurerRandomnessTest::GetTestValue() const
{
double fTu = (sum/(n-Q))/log(2.0); // this is the test value defined by Maurer
double value = fTu * 0.1392; // arbitrarily normalize it to
return value > 1.0 ? 1.0 : value; // a number between 0 and 1
}
NAMESPACE_END
|