~ubuntu-branches/debian/squeeze/pycryptopp/squeeze

« back to all changes in this revision

Viewing changes to cryptopp/rng.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Zooko O'Whielacronx
  • Date: 2009-06-22 22:20:50 UTC
  • Revision ID: james.westby@ubuntu.com-20090622222050-hbqmn50dt2kvoz5o
Tags: upstream-0.5.14
ImportĀ upstreamĀ versionĀ 0.5.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// rng.cpp - written and placed in the public domain by Wei Dai
 
2
 
 
3
#include "pch.h"
 
4
 
 
5
#include "rng.h"
 
6
#include "fips140.h"
 
7
 
 
8
#include <math.h>
 
9
 
 
10
NAMESPACE_BEGIN(CryptoPP)
 
11
 
 
12
// linear congruential generator
 
13
// originally by William S. England
 
14
 
 
15
// do not use for cryptographic purposes
 
16
 
 
17
/*
 
18
** Original_numbers are the original published m and q in the
 
19
** ACM article above.  John Burton has furnished numbers for
 
20
** a reportedly better generator.  The new numbers are now
 
21
** used in this program by default.
 
22
*/
 
23
 
 
24
#ifndef LCRNG_ORIGINAL_NUMBERS
 
25
const word32 LC_RNG::m=2147483647L;
 
26
const word32 LC_RNG::q=44488L;
 
27
 
 
28
const word16 LC_RNG::a=(unsigned int)48271L;
 
29
const word16 LC_RNG::r=3399;
 
30
#else
 
31
const word32 LC_RNG::m=2147483647L;
 
32
const word32 LC_RNG::q=127773L;
 
33
 
 
34
const word16 LC_RNG::a=16807;
 
35
const word16 LC_RNG::r=2836;
 
36
#endif
 
37
 
 
38
void LC_RNG::GenerateBlock(byte *output, size_t size)
 
39
{
 
40
        while (size--)
 
41
        {
 
42
                word32 hi = seed/q;
 
43
                word32 lo = seed%q;
 
44
 
 
45
                long test = a*lo - r*hi;
 
46
 
 
47
                if (test > 0)
 
48
                        seed = test;
 
49
                else
 
50
                        seed = test+ m;
 
51
 
 
52
                *output++ = (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3));
 
53
        }
 
54
}
 
55
 
 
56
// ********************************************************
 
57
 
 
58
#ifndef CRYPTOPP_IMPORTS
 
59
 
 
60
X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector)
 
61
        : cipher(c),
 
62
          S(cipher->BlockSize()),
 
63
          dtbuf(S),
 
64
          randseed(seed, S),
 
65
          m_lastBlock(S),
 
66
          m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0)
 
67
{
 
68
  assert (deterministicTimeVector);
 
69
 
 
70
        // for FIPS 140-2
 
71
        GenerateBlock(m_lastBlock, S);
 
72
}
 
73
 
 
74
void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size)
 
75
{
 
76
        while (size > 0)
 
77
        {
 
78
                // calculate new enciphered timestamp
 
79
                if (m_deterministicTimeVector.size())
 
80
                {
 
81
                        cipher->ProcessBlock(m_deterministicTimeVector, dtbuf);
 
82
                        IncrementCounterByOne(m_deterministicTimeVector, S);
 
83
                }
 
84
                else
 
85
                {
 
86
                  assert(false);
 
87
                }
 
88
 
 
89
                // combine enciphered timestamp with seed
 
90
                xorbuf(randseed, dtbuf, S);
 
91
 
 
92
                // generate a new block of random bytes
 
93
                cipher->ProcessBlock(randseed);
 
94
                if (memcmp(m_lastBlock, randseed, S) == 0)
 
95
                        throw SelfTestFailure("X917RNG: Continuous random number generator test failed.");
 
96
 
 
97
                // output random bytes
 
98
                size_t len = UnsignedMin(S, size);
 
99
                target.ChannelPut(channel, randseed, len);
 
100
                size -= len;
 
101
 
 
102
                // compute new seed vector
 
103
                memcpy(m_lastBlock, randseed, S);
 
104
                xorbuf(randseed, dtbuf, S);
 
105
                cipher->ProcessBlock(randseed);
 
106
        }
 
107
}
 
108
 
 
109
#endif
 
110
 
 
111
MaurerRandomnessTest::MaurerRandomnessTest()
 
112
        : sum(0.0), n(0)
 
113
{
 
114
        for (unsigned i=0; i<V; i++)
 
115
                tab[i] = 0;
 
116
}
 
117
 
 
118
size_t MaurerRandomnessTest::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
 
119
{
 
120
        while (length--)
 
121
        {
 
122
                byte inByte = *inString++;
 
123
                if (n >= Q)
 
124
                        sum += log(double(n - tab[inByte]));
 
125
                tab[inByte] = n;
 
126
                n++;
 
127
        }
 
128
        return 0;
 
129
}
 
130
 
 
131
double MaurerRandomnessTest::GetTestValue() const
 
132
{
 
133
        if (BytesNeeded() > 0)
 
134
                throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed");
 
135
 
 
136
        double fTu = (sum/(n-Q))/log(2.0);      // this is the test value defined by Maurer
 
137
 
 
138
        double value = fTu * 0.1392;            // arbitrarily normalize it to
 
139
        return value > 1.0 ? 1.0 : value;       // a number between 0 and 1
 
140
}
 
141
 
 
142
NAMESPACE_END