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