-rw-r--r-- 5613 cryptattacktester-20231020/random.cpp raw
#include <random> #include "random.h" #ifdef MT19937_64 // ----- using namespace std; static mt19937_64 rng; void random_seed(bigint seed) { rng.seed(seed); } static uniform_int_distribution<short> choose_bit(0,1); bool random_bool(void) { return choose_bit(rng); } static uniform_int_distribution<int> choose_int( numeric_limits<int>::min(), numeric_limits<int>::max() ); int random_int(void) { return choose_int(rng); } static uniform_int_distribution<unsigned int> choose_uint( numeric_limits<unsigned int>::min(), numeric_limits<unsigned int>::max() ); unsigned int random_uint(void) { return choose_uint(rng); } static uniform_int_distribution<long> choose_long( numeric_limits<long>::min(), numeric_limits<long>::max() ); long random_long(void) { return choose_long(rng); } static uniform_int_distribution<unsigned long> choose_ulong( numeric_limits<unsigned long>::min(), numeric_limits<unsigned long>::max() ); unsigned long random_ulong(void) { return choose_ulong(rng); } static uniform_int_distribution<long long> choose_longlong( numeric_limits<long long>::min(), numeric_limits<long long>::max() ); long long random_longlong(void) { return choose_longlong(rng); } static uniform_int_distribution<unsigned long long> choose_ulonglong( numeric_limits<unsigned long long>::min(), numeric_limits<unsigned long long>::max() ); unsigned long long random_ulonglong(void) { return choose_ulonglong(rng); } #else // ----- #include <string.h> // salsa20 code copied from tweetnacl #define FOR(i,n) for (i = 0;i < n;++i) #define sv static void typedef unsigned char u8; typedef unsigned long u32; static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); } static u32 ld32(const u8 *x) { u32 u = x[3]; u = (u<<8)|x[2]; u = (u<<8)|x[1]; return (u<<8)|x[0]; } sv st32(u8 *x,u32 u) { int i; FOR(i,4) { x[i] = u; u >>= 8; } } sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h) { u32 w[16],x[16],y[16],t[4]; int i,j,m; FOR(i,4) { x[5*i] = ld32(c+4*i); x[1+i] = ld32(k+4*i); x[6+i] = ld32(in+4*i); x[11+i] = ld32(k+16+4*i); } FOR(i,16) y[i] = x[i]; FOR(i,20) { FOR(j,4) { FOR(m,4) t[m] = x[(5*j+4*m)%16]; t[1] ^= L32(t[0]+t[3], 7); t[2] ^= L32(t[1]+t[0], 9); t[3] ^= L32(t[2]+t[1],13); t[0] ^= L32(t[3]+t[2],18); FOR(m,4) w[4*j+(j+m)%4] = t[m]; } FOR(m,16) x[m] = w[m]; } if (h) { FOR(i,16) x[i] += y[i]; FOR(i,4) { x[5*i] -= ld32(c+4*i); x[6+i] -= ld32(in+4*i); } FOR(i,4) { st32(out+4*i,x[5*i]); st32(out+16+4*i,x[6+i]); } } else FOR(i,16) st32(out + 4 * i,x[i] + y[i]); } int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c) { core(out,in,k,c,0); return 0; } static const u8 sigma[17] = "expand 32-byte k"; int crypto_stream_salsa20_xor(u8 *c,const u8 *m,long long b,const u8 *n,const u8 *k) { u8 z[16],x[64]; u32 u,i; if (!b) return 0; FOR(i,16) z[i] = 0; FOR(i,8) z[i] = n[i]; while (b >= 64) { crypto_core_salsa20(x,z,k,sigma); FOR(i,64) c[i] = (m?m[i]:0) ^ x[i]; u = 1; for (i = 8;i < 16;++i) { u += (u32) z[i]; z[i] = u; u >>= 8; } b -= 64; c += 64; if (m) m += 64; } if (b) { crypto_core_salsa20(x,z,k,sigma); FOR(i,b) c[i] = (m?m[i]:0) ^ x[i]; } return 0; } int crypto_stream_salsa20(u8 *c,long long d,const u8 *n,const u8 *k) { return crypto_stream_salsa20_xor(c,0,d,n,k); } #define KEYBYTES 32 #define OUTPUTBYTES 736 #define NONCEBYTES 24 static unsigned char g[KEYBYTES]; static unsigned char r[OUTPUTBYTES]; static unsigned long long pos = OUTPUTBYTES; static unsigned char nonce[NONCEBYTES] = {0}; static unsigned char nonce1[NONCEBYTES] = {1}; static unsigned char nonce2[NONCEBYTES] = {2}; static unsigned char nonce3[NONCEBYTES] = {3}; static void randombytes(void *x_void,long long xlen) { unsigned char *x = (unsigned char *) x_void; while (xlen > 0) { if (pos == OUTPUTBYTES) { unsigned char x[KEYBYTES+OUTPUTBYTES]; crypto_stream_salsa20(x,sizeof x,nonce,g); memcpy(g,x,KEYBYTES); memcpy(r,x+KEYBYTES,OUTPUTBYTES); pos = 0; } *x++ = r[pos]; xlen -= 1; r[pos++] = 0; } } void random_seed(bigint seed) { for (bigint i = 0;i < KEYBYTES;++i) g[i] = 0; if (seed < 0) { g[0] = 1; seed = -seed; } for (bigint i = nbits(seed);i >= -1;--i) { unsigned char x[KEYBYTES]; unsigned char *n = nonce1; if (i < 0) n = nonce2; else if (seed.bit(i)) n = nonce3; crypto_stream_salsa20(x,sizeof x,n,g); memcpy(g,x,KEYBYTES); } pos = OUTPUTBYTES; } bool random_bool(void) { unsigned char result; randombytes(&result,sizeof result); return result%2; } int random_int(void) { int result; randombytes(&result,sizeof result); return result; } unsigned int random_uint(void) { unsigned int result; randombytes(&result,sizeof result); return result; } long random_long(void) { long result; randombytes(&result,sizeof result); return result; } unsigned long random_ulong(void) { unsigned long result; randombytes(&result,sizeof result); return result; } long long random_longlong(void) { long long result; randombytes(&result,sizeof result); return result; } unsigned long long random_ulonglong(void) { unsigned long long result; randombytes(&result,sizeof result); return result; } #endif // ----- bigint random_bigint_below(const bigint &m) { // XXX: handle larger ranges bigint result = random_longlong(); return result%m; }