Windows |
UNIX |
#pragma comment(lib, "advapi32.lib") BYTE buf[32]; // however much you need H CRYPTPROV h; if (!CryptAcquireContext(&h,0,0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) die("CryptAquire failed"); if (!CryptGenRandom(h,sizeof(buf),buf)) die("CryptGen failed"); |
Read bytes from the file /dev/urandom (Don't bother with /dev/random) |
Name |
Usage |
Timing |
Comments |
Mersenne
Twister |
std::mt19937 generator; next=generator(); |
12ns |
Initialization is slow, and the algorithm is
complicated (but fast). |
C++11 default_random_engine |
std::default_random_engine generator; next=generator(); |
12ns |
This is just the 1988 version of Park-Miller,
minstd_rand0. It cycles after two billion steps. |
Park-Miller |
next = (last * 48271) % 2147483647UL; or std::minstd_rand. |
5ns |
Gets stuck if given an input of zero. Surprisingly fast because the compiler transforms the mod to a multiply. |
drand48 |
48-bit arithmetic: next = last*0x5DEECE66DuL + 13; |
10ns |
Low hex digits cycle through this sequence: 0d6bc92785e341af |
randu |
31-bit arithmetic: next = last * 65539; |
5ns |
Only useful with odd numbers. Gets stuck if given an input of zero. Low hex digits cycle through 1,3,9,B. All values fall into 15 planes in 3D (fails spectral test). |
srand(3); // the key std::string plaintext=bar, ciphertext=""; for (unsigned int i=0;i<plaintext.size();i++) { int keyi=rand()&0xff; // 8 bits of pseudorandom data keyi&=0x1f; // drop to 5 bits to stay in printable ASCII char c=plaintext[i]; // extract char from input c=c^keyi; // encryption! (or decryption, same thing) ciphertext+=c; // add char to output } return ciphertext;Note we only XOR the low 5 bits of the character data, solely to avoid the hassle of reading and writing binary data. For a real cipher, you would use all 8 bits, resulting in binary garbage as ciphertext, which can't be safely printed to the screen.
unsigned long randS ,mulBy ,addBy ; // In the 1990's, these were 4 bytes eachThe integers at the top are generated from a combination of entropy sources like a high-resolution timer and an expanded version of the passphrase. randS and randS2 get stored to the file. Because there are six integers, a total of 192 bits, we're actually pretty good on total entropy--it'd be hard to enumerate all the keys. Now we encrypt the data by combining two pseudorandom streams:
unsigned long randS2,mulBy2,addBy2;
randS=(long)newDialog;randS2=(long)*myH; // OS memory handles as entropy source
randS2^=TickCount(); // 60ths of a second as entropy source
mulBy =184038653L;addBy =103701121L;//start with good, arbitrary numbers
mulBy2=194625377L;addBy2=203465495L;
short len=strlen(i);
for (short i=len;i<41;i++) // repeat passphrase to fill up buffer
pass[i]=pass[i%len]-i;
for (short i=0;i<8;i++)
{//pervert these numbers by the password in a deterministic way.
//Recall that the low four bits of the password are the most random ones.
//hence, we will xor by the low two bits each iteration (masking the passwd)
mulBy^=(long(pass[i<<2])<<(i<<1))+pass[i+3];
addBy^=(long(pass[(i<<2)+1])<<(i<<1))+pass[i+1];
mulBy2^=(long(pass[(i<<2)+2])<<(i<<1))+pass[i+2];
addBy2^=(long(pass[(i<<2)+3])<<(i<<1))+pass[i+0];
}
dat[i]^=(randS =randS *mulBy +addBy )We do have a potential differential cryptanalysis problem because we're just using XOR to combine the keys with the data, but the randS and randS2 entropy sources make this hard to pull off in practice. There was also a checksum, designed to prevent data modification attacks, but the checksum is also a simple XOR of the data, so it'd be easy enough for an attacker to modify the checksum as well.
^(randS2=randS2*mulBy2+addBy2);