c82b83f0c067fb2644bd4207d5359e379aef88e9
[crypto_lab3.git] / src / Rand.cpp
1 #include "Rand.h"
2
3 #include <iostream>
4 #include <iomanip>
5 #include <fstream>
6 using namespace std;
7
8 mpz_class Rand::randSize(int sizeBits, bool forceSize)
9 {
10 const int nbBitsFirstByte = ((sizeBits - 1) % 8) + 1; // >= 1 and <= 8
11 const int nbBytes = sizeBits / 8 + (nbBitsFirstByte != 8 ? 1 : 0);
12
13 // A fixed rand value used during benchmark tests.
14 // char randBytes[] {(char)0x3d, (char)0x3f, (char)0x74, (char)0xa3, (char)0xcb, (char)0xba, (char)0x2e, (char)0x26, (char)0xf4, (char)0x5a, (char)0x05, (char)0xb0, (char)0x91, (char)0x2d, (char)0x13, (char)0x4c, (char)0x81, (char)0xa4, (char)0x4e, (char)0x8d, (char)0x50, (char)0xc6, (char)0xa5, (char)0x6e, (char)0x69, (char)0x3b, (char)0x1d, (char)0xa1, (char)0x68, (char)0x79, (char)0x87, (char)0xbe, (char)0xbf, (char)0xc0, (char)0x3d, (char)0x06, (char)0x4a, (char)0x74, (char)0xc8, (char)0x36, (char)0xa0, (char)0x92, (char)0x0c, (char)0xb4, (char)0x99, (char)0x6e, (char)0x64, (char)0x27, (char)0x61, (char)0x18, (char)0xe5, (char)0x07, (char)0xf1, (char)0xcb, (char)0x45, (char)0x57, (char)0x84, (char)0xa8, (char)0xbc, (char)0x25, (char)0x00, (char)0x1c, (char)0x7f, (char)0x1c, (char)0xf7, (char)0x40, (char)0xc5, (char)0x09, (char)0x73, (char)0xbf, (char)0xde, (char)0xb2, (char)0x65, (char)0x15, (char)0x64, (char)0xb4, (char)0x94, (char)0x8f, (char)0x1c, (char)0x6b, (char)0x84, (char)0x4b, (char)0x69, (char)0x6f, (char)0xc7, (char)0x71, (char)0x26, (char)0x3c, (char)0x58, (char)0x5f, (char)0x08, (char)0x34, (char)0x29, (char)0x9a, (char)0xfb, (char)0x95, (char)0x9d, (char)0x4f, (char)0x27, (char)0x49, (char)0x94, (char)0xc4, (char)0x26, (char)0x76, (char)0xc1, (char)0x8e, (char)0x30, (char)0x7f, (char)0x93, (char)0x63, (char)0x68, (char)0x3c, (char)0x0b, (char)0x8f, (char)0x5d, (char)0xff, (char)0x09, (char)0x68, (char)0x1b, (char)0x41, (char)0xea, (char)0xfd, (char)0xe1, (char)0xd5, (char)0x77, (char)0x1d, (char)0x3b, (char)0xda, (char)0x6f, (char)0xb8, (char)0xbe, (char)0x86, (char)0x25, (char)0x8a, (char)0xc1, (char)0x2c, (char)0x87, (char)0xd0, (char)0x24, (char)0xe9, (char)0x0d, (char)0xb3, (char)0x23, (char)0xcb, (char)0x40, (char)0xa3, (char)0x40, (char)0xc7, (char)0x2c, (char)0x3e, (char)0x08, (char)0xdf, (char)0xdc, (char)0xaa, (char)0x7a, (char)0x4a, (char)0x02, (char)0x23, (char)0x73, (char)0xb3, (char)0xc9, (char)0xe5, (char)0x2a, (char)0x36, (char)0xf3, (char)0xd1, (char)0x59, (char)0xfd, (char)0x74, (char)0x63, (char)0x46, (char)0x92, (char)0x47, (char)0x48, (char)0xf0, (char)0x05, (char)0x4c, (char)0xf9, (char)0x92, (char)0xe2, (char)0xe8, (char)0x7e, (char)0x52, (char)0x1a, (char)0x84, (char)0x47, (char)0x9a, (char)0xb5, (char)0x25, (char)0xdc, (char)0xb2, (char)0xed, (char)0x02, (char)0x65, (char)0x76, (char)0x3e, (char)0xad, (char)0xc0, (char)0x3c, (char)0xa0, (char)0x30, (char)0x83, (char)0x0c, (char)0xbe, (char)0x09, (char)0x63, (char)0x36, (char)0x3c, (char)0xc4, (char)0x94, (char)0x79, (char)0x74, (char)0x30, (char)0x71, (char)0x1b, (char)0xac, (char)0x0c, (char)0x2f, (char)0xcf, (char)0xf4, (char)0x68, (char)0x26, (char)0xd9, (char)0xb4, (char)0xb5, (char)0x3c, (char)0x07, (char)0x41, (char)0xa4, (char)0xde, (char)0x80, (char)0x00, (char)0x70, (char)0x06, (char)0x8c, (char)0xa7, (char)0x1b, (char)0x81, (char)0xcb, (char)0x6b, (char)0xc7, (char)0x20, (char)0x45, (char)0x0e, (char)0x23, (char)0x19, (char)0xb8, (char)0xa3, (char)0x29, (char)0x29, (char)0xf4, (char)0x99, (char)0xde, (char)0xfb, (char)0xad, (char)0xa5 };
15
16 char randBytes[nbBytes];
17 readRand(randBytes, nbBytes);
18
19 // We discard the n most significant bits where n >= 0 && n <= 7.
20 if (nbBitsFirstByte != 8)
21 randBytes[0] &= 0xFF >> (8 - nbBitsFirstByte);
22
23 // If asked we set the most significant bit to 1.
24 if (forceSize)
25 randBytes[0] |= 0x01 << (nbBitsFirstByte - 1);
26
27 mpz_class n;
28 mpz_import(n.get_mpz_t(), nbBytes, 1, sizeof(char), 1, 0, randBytes); // Big-endian -> most significant byte first.
29 return n;
30 }
31
32 mpz_class Rand::randLimits(const mpz_class& from, const mpz_class& to)
33 {
34 const mpz_class nbValues = to - from + 1;
35 const size_t nbBits = mpz_sizeinbase(mpz_class(nbValues - 1).get_mpz_t(), 2);
36
37 // A 'nbBytes' size random number is generated, if it matches the given limits we return it.
38 for (;;)
39 {
40 mpz_class n = randSize(nbBits, false) + from;
41 if (n >= from && n <= to)
42 return n;
43 }
44 }
45
46 mpz_class Rand::randPrime(const int size_bits)
47 {
48 mpz_class r = randSize(size_bits);
49 mpz_nextprime(r.get_mpz_t(), r.get_mpz_t());
50 return r;
51 }
52
53 void Rand::readRand(char* to, int size)
54 {
55 const string RANDOM_SOURCE("/dev/urandom");
56
57 static fstream ifs(RANDOM_SOURCE, ios_base::in);
58 if (!ifs)
59 {
60 cerr << "Unable to read the random source: " << RANDOM_SOURCE << endl;
61 throw 1;
62 }
63
64 ifs.read(to, size);
65 }