-rw-r--r-- 7035 high-ctidh-20210523/testrandom.c
#include <stdio.h> #include <stdlib.h> #include <assert.h> #include "random.h" #include "crypto_declassify.h" void test_random_coin(void) { printf("random_coin\n"); fflush(stdout); uint64_t dist[2]; uint64_t loop; for (uint64_t den = 1;den <= 10;++den) { for (uint64_t num = 0;num <= den;++num) { dist[0] = dist[1] = 0; for (loop = 0;loop < 16384*den;++loop) { int64_t r = random_coin(num,den); assert(r <= 0); assert(r >= -1); ++dist[-r]; } assert(dist[0]+dist[1] == loop); if (num == 0) { assert(dist[1] == 0); } else if (num == den) { assert(dist[1] == loop); } else { assert(dist[1] > (16384-1536)*num); assert(dist[1] < (16384+1536)*num); } } } } void test_boundedl1_2(void) { printf("boundedl1_2\n"); fflush(stdout); long long dist[11][11]; int8_t e[4]; long long table[6] = {1,5,13,25,41,61}; for (long long S = 0;S <= 5;++S) { for (long long i = 0;i < 11;++i) for (long long j = 0;j < 11;++j) dist[i][j] = 0; for (long long loop = 0;loop < table[S]*16384;++loop) { e[0] = loop; e[3] = loop; random_boundedl1(e+1,2,S); assert(e[0] == (int8_t) loop); assert(e[3] == (int8_t) loop); assert(abs(e[1])+abs(e[2]) <= S); ++dist[e[1]+S][e[2]+S]; } long long numnonzero = 0; long long maxnonzero = 0; long long minnonzero = 0; for (long long i = 0;i < 11;++i) for (long long j = 0;j < 11;++j) { long long expected = llabs(i-S)+llabs(j-S)<=S; long long D = dist[i][j]; if (D) { if (!numnonzero) maxnonzero = minnonzero = D; else { if (D > maxnonzero) maxnonzero = D; if (D < minnonzero) minnonzero = D; } ++numnonzero; assert(expected); } else { assert(!expected); } } assert(minnonzero >= 16384-1536); assert(maxnonzero <= 16384+1536); } } void test_boundedl1_3(void) { printf("boundedl1_3\n"); fflush(stdout); long long dist[11][11][11]; int8_t e[5]; long long table[6] = {1,7,25,63,129,231}; for (long long S = 0;S <= 5;++S) { for (long long i = 0;i < 11;++i) for (long long j = 0;j < 11;++j) for (long long k = 0;k < 11;++k) dist[i][j][k] = 0; for (long long loop = 0;loop < table[S]*16384;++loop) { e[0] = loop; e[4] = loop; random_boundedl1(e+1,3,S); assert(e[0] == (int8_t) loop); assert(e[4] == (int8_t) loop); assert(abs(e[1])+abs(e[2])+abs(e[3]) <= S); ++dist[e[1]+S][e[2]+S][e[3]+S]; } long long numnonzero = 0; long long maxnonzero = 0; long long minnonzero = 0; for (long long i = 0;i < 11;++i) for (long long j = 0;j < 11;++j) for (long long k = 0;k < 11;++k) { long long expected = llabs(i-S)+llabs(j-S)+llabs(k-S)<=S; long long D = dist[i][j][k]; if (D) { if (!numnonzero) maxnonzero = minnonzero = D; else { if (D > maxnonzero) maxnonzero = D; if (D < minnonzero) minnonzero = D; } ++numnonzero; assert(expected); } else { assert(!expected); } } assert(minnonzero >= 16384-1536); assert(maxnonzero <= 16384+1536); } } #define MAXOUTPUTS 256 #define wMAX 24 #define SMAX 24 double batchkeys(long long w,long long S) { assert(w >= 0); assert(w <= wMAX); assert(S >= 0); assert(S <= SMAX); double poly[wMAX+1]; double newpoly[wMAX+1]; for (long long j = 0;j <= w;++j) poly[j] = 0; poly[0] = 1; for (long long i = 0;i < w;++i) { for (long long j = 0;j <= w;++j) newpoly[j] = poly[j]; for (long long j = 0;j < w;++j) newpoly[j+1] += poly[j]; for (long long j = 0;j <= w;++j) poly[j] = newpoly[j]; } for (long long i = 0;i < S;++i) { for (long long j = 0;j <= w;++j) newpoly[j] = poly[j]; for (long long j = 0;j < w;++j) newpoly[j+1] += 2*poly[j]; for (long long j = 0;j <= w;++j) poly[j] = newpoly[j]; } return poly[w]; } double binomial(long long x,long long y) { assert(x >= y); assert(y >= 0); double result = 1; for (long long i = 0;i < y;++i) result *= x-i; for (long long i = 0;i < y;++i) result /= y-i; return result; } double batchkeys_binomial(long long w,long long S) { double result = 0; for (long long k = 0;k <= w && k <= S;++k) result += binomial(w,k)*binomial(S,k)*(1<<k); return result; } void test_batchkeys(void) { printf("batchkeys\n"); fflush(stdout); for (long long w = 0;w <= wMAX;++w) for (long long S = 0;S <= wMAX;++S) assert(batchkeys(w,S) == batchkeys_binomial(w,S)); assert(batchkeys(2,0) == 1); assert(batchkeys(2,1) == 5); assert(batchkeys(2,2) == 13); assert(batchkeys(2,3) == 25); assert(batchkeys(2,4) == 41); assert(batchkeys(2,5) == 61); assert(batchkeys(3,0) == 1); assert(batchkeys(3,1) == 7); assert(batchkeys(3,2) == 25); assert(batchkeys(3,3) == 63); assert(batchkeys(3,4) == 129); assert(batchkeys(3,5) == 231); } void test_boundedl1_generic(void) { printf("boundedl1_generic\n"); fflush(stdout); int8_t outputs[MAXOUTPUTS][wMAX]; long long freq[MAXOUTPUTS]; for (long long w = 0;w <= wMAX;++w) { for (long long S = 0;S <= SMAX;++S) { long long expoutputs = batchkeys(w,S); if (expoutputs >= MAXOUTPUTS) break; printf("%lld %lld %lld\n",w,S,expoutputs); fflush(stdout); long long numoutputs = 0; for (long long i = 0;i < MAXOUTPUTS;++i) freq[i] = 0; for (long long loop = 0;loop < 16384*expoutputs;++loop) { int8_t e[wMAX]; random_boundedl1(e,w,S); crypto_declassify(e,sizeof e); int found = 0; for (long long i = 0;i < numoutputs;++i) { found = 1; for (long long j = 0;j < w;++j) if (e[j] != outputs[i][j]) { found = 0; break; } if (found) { ++freq[i]; break; } } if (!found) { assert(numoutputs < expoutputs); assert(numoutputs < MAXOUTPUTS); for (long long j = 0;j < w;++j) outputs[numoutputs][j] = e[j]; ++freq[numoutputs]; numoutputs += 1; } } assert(numoutputs == expoutputs); for (long long i = 0;i < numoutputs;++i) { long long outputsum = 0; for (long long j = 0;j < w;++j) { assert(outputs[i][j] <= S); assert(outputs[i][j] >= -S); outputsum += llabs(outputs[i][j]); } assert(outputsum <= S); assert(freq[i] >= 16384-1536); assert(freq[i] <= 16384+1536); } } } } int main() { test_batchkeys(); test_random_coin(); test_boundedl1_2(); test_boundedl1_3(); test_boundedl1_generic(); return 0; }