2013-08-19 9 views
8

Użyłem następującego kodu do wygenerowania sekwencji liczb pseudolosowych, które były używane do celów kryptograficznych, ale potem czytałem gdzieś, że może nie być bardzo bezpieczne. Czy ktoś może mi dać implementację lepszego generatora C - głównym celem jest, aby ta metoda była szybka. Na przykład zrobiłem kilka badań i natknąłem się na metodę Blum Blum Shub, która całkowicie zniszczyłaby wydajność, wykonując obliczenia pow (N).Szybki generator liczb pseudolosowych do kryptografii w C

PS. Proszę nie cytować artykułów Wikipedii bez kodu C/C++. Szukam próbki kodu C lub C++ tego, co pokazuję poniżej.

#define ROL(v, shift) ((((v) >> ((sizeof(v) * 8) - (shift))) | ((v) << (shift)))) 

ULONGLONG uiPSN = doSeed(); //64-bit unsigned integer 

for(int i = 0; i < sizeOfArray; i++) 
{ 
    uiPSN = uiPSN * 214013L + 2531011L; 
    uiPSN = ROL(uiPSN, 16); 

    //Apply 'uiPSN' 
} 
+1

Zdecydowanie radzę użyć PRNG obsługującego Hash-DRBG lub HMAC-DRBG, szczególnie jeśli masz jakiekolwiek zamiary na certyfikację FIPS. Algorytmy i ich wymagania są dostępne na stronie [NIST] (http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf) i są * nie * trywialne (dobre bezpieczeństwo rzadko jest). – WhozCraig

+0

[Mersenne Twister] (http://en.wikipedia.org/wiki/Mersenne_twister) to dobra równowaga między szybkością a "przypadkowością". Wiele implementacji Open Source istnieje dla wielu języków. Możesz pobrać implementację 'C++' [tutaj] (http: //www.bedaux.net/mtrand /) –

+0

@awashburn Lub użyj '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' – Rapptz

Odpowiedz

14

ISAAC (http://www.burtleburtle.net/bob/rand/isaacafa.html) jest prawdopodobnie jednym z najszybciej kryptograficznego PRNGs (kod na miejscu). Inne podejście polega na użyciu szyfru blokowego w trybie licznika. Coś takiego jak TwoFish, który jest dość szybki i swobodnie dostępny, byłoby skuteczne.

Jeśli nie potrzebujesz dużej liczby numerów, wszystkie nowoczesne systemy operacyjne mają wbudowane RNG nadające się do użytku kryptograficznego, ale zazwyczaj nie mogą wytwarzać dużej liczby liczb, ponieważ polegają na gromadzeniu entropii ze źródeł takich jak czasy wejściowe . Systemy uniksopodobne (Linux, OSX) mają/dev/random, Windows ma CryptGenRandom. Nawet jeśli nie są one odpowiednie do twoich potrzeb, prawdopodobnie powinieneś użyć ich do zaszczepienia PRNG, którego używasz.

+0

+1 naprawdę przydatna i ogólnie dobra odpowiedź –

-4

Polecam Mersenne-Twister, którego używam od czasu do czasu.

Kod C to here.

Jeśli używasz C++ 11, masz mersenne twister jako część samej biblioteki. Mersenne Twister jest obecnie jednym z najlepszych algorytmów.

Oto jak zaimplementować w C++ 11, jako funkcję. To bardzo proste. mt19937 jest zbudowany w Mersenne Twister w C++ 11.

std::vector<double> classname::mersennetwister(const int& My,const int& Mz,const int& Ny,const int& Nz) 
{ 
int ysize = (My + 2*Ny + 1); 
int zsize = (Mz + 2*Nz + 1); 
int matsize = ysize*zsize; 
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); 
std::mt19937_64 generator (seed); 
std::uniform_real_distribution<double> distribution(0,1); 
std::vector<double> randarray = f.array1dgen(matsize,0); 
for (int i=0;i<matsize;++i) 
{ 
    randarray[i] = distribution(generator); 
} 
return(randarray); 
} 
+3

Wikipedia na temat wad MT: "Algorytm w swoim natywna forma nie nadaje się do kryptografii (w przeciwieństwie do Blum Blum Shub). Przestrzeganie wystarczającej liczby iteracji (624 w przypadku MT19937, ponieważ jest to wielkość wektora stanu, z którego tworzone są kolejne iteracje) pozwala przewidzieć całą przyszłość iteracje. " – delnan

+0

@delnan Może potrzebuje tylko garści losowych liczb, znacznie mniej niż 624 iteracji? –

+1

@awashburn Wtedy będzie dobrze, oczywiście.Ale nie można po prostu * założyć * i zalecić rozwiązanie, które jest zepsute, jeśli to (często nieuzasadnione) założenie nie jest prawdziwe. – delnan

5

Sprawdź (lub użyj) generator liczb losowych w bibliotece OpenSSL.

Najtrudniejszą częścią z dowolnym bezpiecznym generatorem liczb losowych jest wysiew. Jeśli korzystasz z systemu Windows, rozważ użycie funkcji rand_s(). W systemie Linux zobacz/dev/urand.

Niektóre metody rozsiewania nie są zbyt szybko wybierane po ponownym uruchomieniu komputera. Możesz utworzyć plik z losowymi bajtami. Skorzystaj z pliku i metody systemu operacyjnego do zaszczepienia. Okresowo użyj generatora liczb losowych, aby napisać nowy plik.

1

Nie "zwijaj swojej własnej" kryptografii. Zamiast tego użyj certyfikowanej biblioteki.

Aby zwiększyć szybkość, spróbuj użyć biblioteki, która może działać na GPU, który ma znacznie więcej mocy obliczeniowej.