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 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 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