// RandGen.cpp #include "StdAfx.h" #include "../../Windows/Synchronization.h" #include "RandGen.h" #ifndef _WIN32 #include <unistd.h> #define USE_POSIX_TIME #define USE_POSIX_TIME2 #endif #ifdef USE_POSIX_TIME #include <time.h> #ifdef USE_POSIX_TIME2 #include <sys/time.h> #endif #endif // This is not very good random number generator. // Please use it only for salt. // First generated data block depends from timer and processID. // Other generated data blocks depend from previous state // Maybe it's possible to restore original timer value from generated value. #define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x)); void CRandomGenerator::Init() { CSha256 hash; Sha256_Init(&hash); #ifdef _WIN32 DWORD w = ::GetCurrentProcessId(); HASH_UPD(w); w = ::GetCurrentThreadId(); HASH_UPD(w); #else pid_t pid = getpid(); HASH_UPD(pid); pid = getppid(); HASH_UPD(pid); #endif for (unsigned i = 0; i < #ifdef _DEBUG 2; #else 1000; #endif i++) { #ifdef _WIN32 LARGE_INTEGER v; if (::QueryPerformanceCounter(&v)) HASH_UPD(v.QuadPart); #endif #ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME2 timeval v; if (gettimeofday(&v, 0) == 0) { HASH_UPD(v.tv_sec); HASH_UPD(v.tv_usec); } #endif time_t v2 = time(NULL); HASH_UPD(v2); #endif DWORD tickCount = ::GetTickCount(); HASH_UPD(tickCount); for (unsigned j = 0; j < 100; j++) { Sha256_Final(&hash, _buff); Sha256_Init(&hash); Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); } } Sha256_Final(&hash, _buff); _needInit = false; } static NWindows::NSynchronization::CCriticalSection g_CriticalSection; void CRandomGenerator::Generate(Byte *data, unsigned size) { g_CriticalSection.Enter(); if (_needInit) Init(); while (size > 0) { CSha256 hash; Sha256_Init(&hash); Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); Sha256_Final(&hash, _buff); Sha256_Init(&hash); UInt32 salt = 0xF672ABD1; HASH_UPD(salt); Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE); Byte buff[SHA256_DIGEST_SIZE]; Sha256_Final(&hash, buff); for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size > 0; i++, size--) *data++ = buff[i]; } g_CriticalSection.Leave(); } CRandomGenerator g_RandomGenerator;