<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0" />

FalconRNG

class FalconRNG
using System; namespace Org.BouncyCastle.Pqc.Crypto.Falcon { internal class FalconRNG { private byte[] bd; private byte[] sd; private int ptr; private FalconConversions convertor; internal FalconRNG() { bd = new byte[512]; sd = new byte[256]; convertor = new FalconConversions(); } internal void prng_init(SHAKE256 src) { byte[] array = new byte[56]; src.i_shake256_extract(array, 0, 56); for (int i = 0; i < 14; i++) { uint x = (uint)(array[i << 2] | (array[(i << 2) + 1] << 8) | (array[(i << 2) + 2] << 16) | (array[(i << 2) + 3] << 24)); Array.Copy(convertor.int_to_bytes((int)x), 0, sd, i << 2, 4); } ulong num = convertor.bytes_to_uint(sd, 48); ulong num2 = convertor.bytes_to_uint(sd, 52); Array.Copy(convertor.ulong_to_bytes(num + (num2 << 32)), 0, sd, 48, 8); prng_refill(); } private void QROUND(uint[] state, int a, int b, int c, int d) { state[a] += state[b]; state[d] ^= state[a]; state[d] = ((state[d] << 16) | (state[d] >> 16)); state[c] += state[d]; state[b] ^= state[c]; state[b] = ((state[b] << 12) | (state[b] >> 20)); state[a] += state[b]; state[d] ^= state[a]; state[d] = ((state[d] << 8) | (state[d] >> 24)); state[c] += state[d]; state[b] ^= state[c]; state[b] = ((state[b] << 7) | (state[b] >> 25)); } private void prng_refill() { uint[] array = new uint[4] { 1634760805, 857760878, 2036477234, 1797285236 }; ulong num = convertor.bytes_to_ulong(sd, 48); for (int i = 0; i < 8; i++) { uint[] array2 = new uint[16]; Array.Copy(array, 0, array2, 0, 4); Array.Copy(convertor.bytes_to_uint_array(sd, 0, 12), 0, array2, 4, 12); array2[14] ^= (uint)(int)num; array2[15] ^= (uint)(int)(num >> 32); for (int j = 0; j < 10; j++) { QROUND(array2, 0, 4, 8, 12); QROUND(array2, 1, 5, 9, 13); QROUND(array2, 2, 6, 10, 14); QROUND(array2, 3, 7, 11, 15); QROUND(array2, 0, 5, 10, 15); QROUND(array2, 1, 6, 11, 12); QROUND(array2, 2, 7, 8, 13); QROUND(array2, 3, 4, 9, 14); } for (int k = 0; k < 4; k++) { array2[k] += array[k]; } for (int k = 4; k < 14; k++) { array2[k] += convertor.bytes_to_uint(sd, 4 * k - 16); } array2[14] += (uint)(int)(convertor.bytes_to_uint(sd, 40) ^ (int)num); array2[15] += (uint)(int)(convertor.bytes_to_uint(sd, 44) ^ (int)(num >> 32)); num++; for (int k = 0; k < 16; k++) { bd[(i << 2) + (k << 5)] = (byte)array2[k]; bd[(i << 2) + (k << 5) + 1] = (byte)(array2[k] >> 8); bd[(i << 2) + (k << 5) + 2] = (byte)(array2[k] >> 16); bd[(i << 2) + (k << 5) + 3] = (byte)(array2[k] >> 24); } } Array.Copy(convertor.ulong_to_bytes(num), 0, sd, 48, 8); ptr = 0; } internal void prng_get_bytes(byte[] dstsrc, int dst, int len) { int num = dst; while (len > 0) { int num2 = bd.Length - ptr; if (num2 > len) num2 = len; Array.Copy(bd, 0, dstsrc, num, num2); num += num2; len -= num2; ptr += num2; if (ptr == bd.Length) prng_refill(); } } internal ulong prng_get_u64() { int num = ptr; if (num >= bd.Length - 9) { prng_refill(); num = 0; } ptr = num + 8; return bd[num] | ((ulong)bd[num + 1] << 8) | ((ulong)bd[num + 2] << 16) | ((ulong)bd[num + 3] << 24) | ((ulong)bd[num + 4] << 32) | ((ulong)bd[num + 5] << 40) | ((ulong)bd[num + 6] << 48) | ((ulong)bd[num + 7] << 56); } internal uint prng_get_u8() { byte result = bd[ptr++]; if (ptr == bd.Length) prng_refill(); return result; } } }