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