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