1 // RandGen.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../Windows/Synchronization.h"
6
7 #include "RandGen.h"
8
9 #ifndef _WIN32
10 #include <unistd.h>
11 #define USE_POSIX_TIME
12 #define USE_POSIX_TIME2
13 #endif
14
15 #ifdef USE_POSIX_TIME
16 #include <time.h>
17 #ifdef USE_POSIX_TIME2
18 #include <sys/time.h>
19 #endif
20 #endif
21
22 // This is not very good random number generator.
23 // Please use it only for salt.
24 // First generated data block depends from timer and processID.
25 // Other generated data blocks depend from previous state
26 // Maybe it's possible to restore original timer value from generated value.
27
28 #define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x));
29
Init()30 void CRandomGenerator::Init()
31 {
32 CSha256 hash;
33 Sha256_Init(&hash);
34
35 #ifdef _WIN32
36 DWORD w = ::GetCurrentProcessId();
37 HASH_UPD(w);
38 w = ::GetCurrentThreadId();
39 HASH_UPD(w);
40 #else
41 pid_t pid = getpid();
42 HASH_UPD(pid);
43 pid = getppid();
44 HASH_UPD(pid);
45 #endif
46
47 for (unsigned i = 0; i <
48 #ifdef _DEBUG
49 2;
50 #else
51 1000;
52 #endif
53 i++)
54 {
55 #ifdef _WIN32
56 LARGE_INTEGER v;
57 if (::QueryPerformanceCounter(&v))
58 HASH_UPD(v.QuadPart);
59 #endif
60
61 #ifdef USE_POSIX_TIME
62 #ifdef USE_POSIX_TIME2
63 timeval v;
64 if (gettimeofday(&v, 0) == 0)
65 {
66 HASH_UPD(v.tv_sec);
67 HASH_UPD(v.tv_usec);
68 }
69 #endif
70 time_t v2 = time(NULL);
71 HASH_UPD(v2);
72 #endif
73
74 DWORD tickCount = ::GetTickCount();
75 HASH_UPD(tickCount);
76
77 for (unsigned j = 0; j < 100; j++)
78 {
79 Sha256_Final(&hash, _buff);
80 Sha256_Init(&hash);
81 Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
82 }
83 }
84 Sha256_Final(&hash, _buff);
85 _needInit = false;
86 }
87
88 static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
89
Generate(Byte * data,unsigned size)90 void CRandomGenerator::Generate(Byte *data, unsigned size)
91 {
92 g_CriticalSection.Enter();
93 if (_needInit)
94 Init();
95 while (size > 0)
96 {
97 CSha256 hash;
98
99 Sha256_Init(&hash);
100 Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
101 Sha256_Final(&hash, _buff);
102
103 Sha256_Init(&hash);
104 UInt32 salt = 0xF672ABD1;
105 HASH_UPD(salt);
106 Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
107 Byte buff[SHA256_DIGEST_SIZE];
108 Sha256_Final(&hash, buff);
109 for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size > 0; i++, size--)
110 *data++ = buff[i];
111 }
112 g_CriticalSection.Leave();
113 }
114
115 CRandomGenerator g_RandomGenerator;
116