Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
randomhash.cc
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2// Author: 2014, Tim Janik, see http://testbit.eu/
3#include "randomhash.hh"
4#include "entropy.hh"
5#include "strings.hh"
6#include "internal.hh"
7
8namespace Ase {
9
10// == Lib::KeccakF1600 ==
11Lib::KeccakF1600::KeccakF1600()
12{
13 reset();
14}
15
16void
17Lib::KeccakF1600::reset ()
18{
19 memset4 ((uint32*) bytes, 0, sizeof (bytes) / 4);
20}
21
22static constexpr const uint8_t KECCAK_RHO_OFFSETS[25] = { 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43,
23 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14 };
24static constexpr const uint64_t KECCAK_ROUND_CONSTANTS[255] = {
25 1, 32898, 0x800000000000808a, 0x8000000080008000, 32907, 0x80000001, 0x8000000080008081, 0x8000000000008009, 138, 136, 0x80008009,
26 0x8000000a, 0x8000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 32778,
27 0x800000008000000a, 0x8000000080008081, 0x8000000000008080, 0x80000001, 0x8000000080008008, 0x8000000080008082, 0x800000008000800a,
28 0x8000000000000003, 0x8000000080000009, 0x8000000000008082, 32777, 0x8000000000000080, 32899, 0x8000000000000081, 1, 32779,
29 0x8000000080008001, 128, 0x8000000000008000, 0x8000000080008001, 9, 0x800000008000808b, 129, 0x8000000000000082, 0x8000008b,
30 0x8000000080008009, 0x8000000080000000, 0x80000080, 0x80008003, 0x8000000080008082, 0x8000000080008083, 0x8000000080000088, 32905,
31 32777, 0x8000000000000009, 0x80008008, 0x80008001, 0x800000000000008a, 0x800000000000000b, 137, 0x80000002, 0x800000000000800b,
32 0x8000800b, 32907, 0x80000088, 0x800000000000800a, 0x80000089, 0x8000000000000001, 0x8000000000008088, 0x8000000000000081, 136,
33 0x80008080, 129, 0x800000000000000b, 0, 137, 0x8000008b, 0x8000000080008080, 0x800000000000008b, 0x8000000000008000,
34 0x8000000080008088, 0x80000082, 11, 0x800000000000000a, 32898, 0x8000000000008003, 0x800000000000808b, 0x800000008000000b,
35 0x800000008000008a, 0x80000081, 0x80000081, 0x80000008, 131, 0x8000000080008003, 0x80008088, 0x8000000080000088, 32768, 0x80008082,
36 0x80008089, 0x8000000080008083, 0x8000000080000001, 0x80008002, 0x8000000080000089, 130, 0x8000000080000008, 0x8000000000000089,
37 0x8000000080000008, 0x8000000000000000, 0x8000000000000083, 0x80008080, 8, 0x8000000080000080, 0x8000000080008080,
38 0x8000000000000002, 0x800000008000808b, 8, 0x8000000080000009, 0x800000000000800b, 0x80008082, 0x80008000, 0x8000000000008008, 32897,
39 0x8000000080008089, 0x80008089, 0x800000008000800a, 0x800000000000008a, 0x8000000000000082, 0x80000002, 0x8000000000008082, 32896,
40 0x800000008000000b, 0x8000000080000003, 10, 0x8000000000008001, 0x8000000080000083, 0x8000000000008083, 139, 32778,
41 0x8000000080000083, 0x800000000000800a, 0x80000000, 0x800000008000008a, 0x80000008, 10, 0x8000000000008088, 0x8000000000000008,
42 0x80000003, 0x8000000000000000, 0x800000000000000a, 32779, 0x8000000080008088, 0x8000000b, 0x80000080, 0x8000808a,
43 0x8000000000008009, 3, 0x80000003, 0x8000000000000089, 0x8000000080000081, 0x800000008000008b, 0x80008003, 0x800000008000800b,
44 0x8000000000008008, 32776, 0x8000000000008002, 0x8000000000000009, 0x80008081, 32906, 0x8000800a, 128, 0x8000000000008089,
45 0x800000000000808a, 0x8000000080008089, 0x80008000, 0x8000000000008081, 0x8000800a, 9, 0x8000000080008002, 0x8000000a, 0x80008002,
46 0x8000000080000000, 0x80000009, 32904, 2, 0x80008008, 0x80008088, 0x8000000080000001, 0x8000808b, 0x8000000000000002,
47 0x8000000080008002, 0x80000083, 32905, 32896, 0x8000000080000082, 0x8000000000000088, 0x800000008000808a, 32906, 0x80008083,
48 0x8000000b, 0x80000009, 32769, 0x80000089, 0x8000000000000088, 0x8000000080008003, 0x80008001, 0x8000000000000003,
49 0x8000000080000080, 0x8000000080008009, 0x8000000080000089, 11, 0x8000000000000083, 0x80008009, 0x80000083, 32768, 0x8000800b, 32770,
50 3, 0x8000008a, 0x8000000080000002, 32769, 0x80000000, 0x8000000080000003, 131, 0x800000008000808a, 32771, 32776, 0x800000000000808b,
51 0x8000000080000082, 0x8000000000000001, 0x8000000000008001, 0x800000008000000a, 0x8000000080008008, 0x800000008000800b,
52 0x8000000000008081, 0x80008083, 0x80000082, 130, 0x8000000080000081, 0x8000000080000002, 32904, 139, 32899, 0x8000000000000008,
53 0x8000008a, 0x800000008000008b, 0x8000808a, 0x8000000000008080, 0x80000088, 0x8000000000008083, 2, 0x80008081, 32771, 32897,
54 0x8000000080008000, 32770, 138,
55};
56
58static inline uint64_t
59bit_rotate64 (uint64_t bits, unsigned int offset)
60{
61 // bitwise rotate-left pattern recognized by gcc & clang iff 64==sizeof (bits)
62#if defined (__x86_64__) && 0 // rolq tends to be slower than C++ with g++ and clang++
63 __asm__ ("rolq %%cl, %0"
64 : "=r" (bits) // out
65 : "0" (bits), "c" (offset) // in
66 : // clobber
67 );
68#else
69 bits = UNLIKELY (offset == 0) ? bits : (bits << offset) | (bits >> (64 - offset));
70#endif
71 return bits;
72}
73
75void
76Lib::KeccakF1600::permute (const uint32_t n_rounds)
77{
78 ASE_ASSERT_RETURN (n_rounds < 255); // adjust the KECCAK_ROUND_CONSTANTS access to lift this assertion
79 // Keccak forward rounds
80 for (size_t round_index = 0; round_index < n_rounds; round_index++)
81 {
82 // theta
83 uint64_t C[5];
84 for (size_t x = 0; x < 5; x++)
85 {
86 C[x] = A[x];
87 for (size_t y = 1; y < 5; y++)
88 C[x] ^= A[x + 5 * y];
89 }
90 for (size_t x = 0; x < 5; x++)
91 {
92 const uint64_t D = C[(5 + x - 1) % 5] ^ bit_rotate64 (C[(x + 1) % 5], 1);
93 for (size_t y = 0; y < 5; y++)
94 A[x + 5 * y] ^= D;
95 }
96 // rho
97 for (size_t y = 0; y < 25; y += 5)
98 {
99 uint64_t *const plane = &A[y];
100 for (size_t x = 0; x < 5; x++)
101 plane[x] = bit_rotate64 (plane[x], KECCAK_RHO_OFFSETS[x + y]);
102 }
103 // pi
104 const uint64_t a[25] = { A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[8], A[9], A[10], A[11], A[12],
105 A[13], A[14], A[15], A[16], A[17], A[18], A[19], A[20], A[21], A[22], A[23], A[24] };
106 for (size_t y = 0; y < 5; y++)
107 for (size_t x = 0; x < 5; x++)
108 {
109 const size_t X = (0 * x + 1 * y) % 5;
110 const size_t Y = (2 * x + 3 * y) % 5;
111 A[X + 5 * Y] = a[x + 5 * y];
112 }
113 // chi
114 for (size_t y = 0; y < 25; y += 5)
115 {
116 uint64_t *const plane = &A[y];
117 for (size_t x = 0; x < 5; x++)
118 C[x] = plane[x] ^ (~plane[(x + 1) % 5] & plane[(x + 2) % 5]);
119 for (size_t x = 0; x < 5; x++)
120 plane[x] = C[x];
121 }
122 // iota
123 A[0 + 5 * 0] ^= KECCAK_ROUND_CONSTANTS[round_index]; // round_index needs %255 for n_rounds>=255
124 }
125}
126
127// == KeccakRng ==
129void
130KeccakRng::permute1600()
131{
132 state_.permute (n_rounds_);
133 opos_ = 0; // fresh outputs available
134}
135
141void
143{
144 std::fill (&state_[0], &state_[256 / 64], 0);
145 permute1600();
146}
147
151void
152KeccakRng::discard (unsigned long long count)
153{
154 while (count)
155 {
156 if (opos_ >= n_nums())
157 permute1600();
158 const unsigned long long ull = std::min ((unsigned long long) n_nums() - opos_, count);
159 opos_ += ull;
160 count -= ull;
161 }
162}
163
169void
170KeccakRng::xor_seed (const uint64_t *seeds, size_t n_seeds)
171{
172 // printerr ("xor_seed(%p): %s\n", this, String ((const char*) seeds, n_seeds * 8));
173 size_t i = 0;
174 while (n_seeds)
175 {
176 if (i > 0) // not first seed block
177 permute1600(); // prepare for next seed block
178 const size_t count = std::min (n_nums(), n_seeds);
179 for (i = 0; i < count; i++)
180 state_[i] ^= seeds[i];
181 seeds += count;
182 n_seeds -= count;
183 }
184 if (i < 25) // apply Simple padding: pad10*
185 state_[i] ^= 0x1; // 1: payload boundary bit for Keccak Sponge compliant padding
186 permute1600(); // integrate seed
187}
188
189void
191{
192 AutoSeeder seeder;
193 seed (seeder);
194}
195
198{
199 // forget all state and leave no trails
200 std::fill (&state_[0], &state_[25], 0xaffeaffeaffeaffe);
201 forget();
202 opos_ = n_nums();
203}
204
205// == SHAKE_Base - primitive for SHA3 hashing ==
206template<size_t HASHBITS, uint8_t DOMAINBITS>
208 Lib::KeccakF1600 state_;
209 const size_t rate_;
210 size_t iopos_;
211 bool feeding_mode_;
212protected:
214 size_t
215 xor_state (size_t offset, const uint8_t *input, size_t n_in)
216 {
217 ASE_ASSERT_RETURN (offset + n_in <= byte_rate(), 0);
218 size_t i;
219 for (i = offset; i < offset + n_in; i++)
220 state_.byte (i) ^= input[i - offset];
221 return i - offset;
222 }
228 void
229 absorb_padding (size_t offset, uint8_t trail = 0x01)
230 {
231 ASE_ASSERT_RETURN (offset < byte_rate()); // offset is first byte following payload
232 ASE_ASSERT_RETURN (trail != 0x00);
233 // MultiRatePadding
234 state_.byte (offset) ^= trail; // 1: payload boundary bit for MultiRatePadding (and SimplePadding)
235 // state_.bits[i..last] ^= 0x0; // 0*: bitrate filler for MultiRatePadding (and SimplePadding)
236 const size_t lastbyte = byte_rate() - 1; // last bitrate byte, may coincide with offset
237 if (offset == lastbyte && trail >= 0x80)
238 state_.permute (24); // prepare new block to append last bit
239 state_.byte (lastbyte) ^= 0x80; // 1: last bitrate bit; required by MultiRatePadding
240 }
241 SHAKE_Base (size_t rate) :
242 rate_ (rate), iopos_ (0), feeding_mode_ (true)
243 {}
244public:
245 size_t
246 byte_rate() const
247 {
248 return rate_ / 8;
249 }
250 void
251 reset()
252 {
253 state_.reset();
254 iopos_ = 0;
255 feeding_mode_ = true;
256 }
257 void
258 update (const uint8_t *data, size_t length)
259 {
260 ASE_ASSERT_RETURN (feeding_mode_ == true);
261 while (length)
262 {
263 const size_t count = std::min (byte_rate() - iopos_, length);
264 xor_state (iopos_, data, count);
265 iopos_ += count;
266 data += count;
267 length -= count;
268 if (iopos_ >= byte_rate())
269 {
270 state_.permute (24);
271 iopos_ = 0;
272 }
273 }
274 }
276 size_t
277 get_hash (uint8_t hashvalue[HASHBITS / 8])
278 {
279 if (feeding_mode_)
280 {
281 const uint8_t shake_delimiter = DOMAINBITS;
282 absorb_padding (iopos_, shake_delimiter);
283 feeding_mode_ = false;
284 state_.permute (24);
285 iopos_ = 0;
286 }
287 const size_t count = HASHBITS / 8;
288 for (size_t i = 0; i < count; i++)
289 hashvalue[i] = state_.byte (i);
290 return count;
291 }
293 void
294 squeeze_digest (uint8_t *output, size_t n_out)
295 {
296 ASE_ASSERT_RETURN (HASHBITS == 0);
297 get_hash (output); // absorb_padding and leave feeding_mode_
298 ASE_ASSERT_RETURN (feeding_mode_ == false);
299 while (n_out)
300 {
301 const size_t count = std::min (n_out, byte_rate() - iopos_);
302 for (size_t i = 0; i < count; i++)
303 output[i] = state_.byte (iopos_ + i);
304 iopos_ += count;
305 output += count;
306 n_out -= count;
307 if (iopos_ >= byte_rate())
308 {
309 state_.permute (24);
310 iopos_ = 0;
311 }
312 }
313 }
314};
315
316// == SHA3_224 ==
317struct SHA3_224::State : SHAKE_Base<224, 0x06> {
318 State() : SHAKE_Base (1152) {}
319};
320
322 state_ (new (&mem_) State())
323{
324 static_assert (sizeof (mem_) >= sizeof (*state_), "");
325}
326
327SHA3_224::~SHA3_224 ()
328{
329 state_->~State();
330}
331
332void
333SHA3_224::update (const uint8_t *data, size_t length)
334{
335 state_->update (data, length);
336}
337
338void
339SHA3_224::digest (uint8_t hashvalue[28])
340{
341 state_->get_hash (hashvalue);
342}
343
344void
346{
347 state_->reset();
348}
349
350void
351sha3_224_hash (const void *data, size_t data_length, uint8_t hashvalue[28])
352{
353 SHA3_224 context;
354 context.update ((const uint8_t*) data, data_length);
355 context.digest (hashvalue);
356}
357
358// == SHA3_256 ==
359struct SHA3_256::State : SHAKE_Base<256, 0x06> {
360 State() : SHAKE_Base (1088) {}
361};
362
364 state_ (new (&mem_) State())
365{
366 static_assert (sizeof (mem_) >= sizeof (*state_), "");
367}
368
369SHA3_256::~SHA3_256 ()
370{
371 state_->~State();
372}
373
374void
375SHA3_256::update (const uint8_t *data, size_t length)
376{
377 state_->update (data, length);
378}
379
380void
381SHA3_256::digest (uint8_t hashvalue[32])
382{
383 state_->get_hash (hashvalue);
384}
385
386void
388{
389 state_->reset();
390}
391
392void
393sha3_256_hash (const void *data, size_t data_length, uint8_t hashvalue[32])
394{
395 SHA3_256 context;
396 context.update ((const uint8_t*) data, data_length);
397 context.digest (hashvalue);
398}
399
400// == SHA3_384 ==
401struct SHA3_384::State : SHAKE_Base<384, 0x06> {
402 State() : SHAKE_Base (832) {}
403};
404
406 state_ (new (&mem_) State())
407{
408 static_assert (sizeof (mem_) >= sizeof (*state_), "");
409}
410
411SHA3_384::~SHA3_384 ()
412{
413 state_->~State();
414}
415
416void
417SHA3_384::update (const uint8_t *data, size_t length)
418{
419 state_->update (data, length);
420}
421
422void
423SHA3_384::digest (uint8_t hashvalue[48])
424{
425 state_->get_hash (hashvalue);
426}
427
428void
430{
431 state_->reset();
432}
433
434void
435sha3_384_hash (const void *data, size_t data_length, uint8_t hashvalue[48])
436{
437 SHA3_384 context;
438 context.update ((const uint8_t*) data, data_length);
439 context.digest (hashvalue);
440}
441
442// == SHA3_512 ==
443struct SHA3_512::State : SHAKE_Base<512, 0x06> {
444 State() : SHAKE_Base (576) {}
445};
446
448 state_ (new (&mem_) State())
449{
450 static_assert (sizeof (mem_) >= sizeof (*state_), "");
451}
452
453SHA3_512::~SHA3_512 ()
454{
455 state_->~State();
456}
457
458void
459SHA3_512::update (const uint8_t *data, size_t length)
460{
461 state_->update (data, length);
462}
463
464void
465SHA3_512::digest (uint8_t hashvalue[64])
466{
467 state_->get_hash (hashvalue);
468}
469
470void
472{
473 state_->reset();
474}
475
476void
477sha3_512_hash (const void *data, size_t data_length, uint8_t hashvalue[64])
478{
479 SHA3_512 context;
480 context.update ((const uint8_t*) data, data_length);
481 context.digest (hashvalue);
482}
483
484// == SHAKE128 ==
485struct SHAKE128::State : SHAKE_Base<0, 0x1f> {
486 State() : SHAKE_Base (1344) {}
487};
488
490 state_ (new (&mem_) State())
491{
492 static_assert (sizeof (mem_) >= sizeof (*state_), "");
493}
494
495SHAKE128::~SHAKE128 ()
496{
497 state_->~State();
498}
499
500void
501SHAKE128::update (const uint8_t *data, size_t length)
502{
503 state_->update (data, length);
504}
505
506void
507SHAKE128::squeeze_digest (uint8_t *hashvalues, size_t n)
508{
509 state_->squeeze_digest (hashvalues, n);
510}
511
512void
514{
515 state_->reset();
516}
517
518void
519shake128_hash (const void *data, size_t data_length, uint8_t *hashvalues, size_t n)
520{
521 SHAKE128 context;
522 context.update ((const uint8_t*) data, data_length);
523 context.squeeze_digest (hashvalues, n);
524}
525
526// == SHAKE256 ==
527struct SHAKE256::State : SHAKE_Base<0, 0x1f> {
528 State() : SHAKE_Base (1088) {}
529};
530
532 state_ (new (&mem_) State())
533{
534 static_assert (sizeof (mem_) >= sizeof (*state_), "");
535}
536
537SHAKE256::~SHAKE256 ()
538{
539 state_->~State();
540}
541
542void
543SHAKE256::update (const uint8_t *data, size_t length)
544{
545 state_->update (data, length);
546}
547
548void
549SHAKE256::squeeze_digest (uint8_t *hashvalues, size_t n)
550{
551 state_->squeeze_digest (hashvalues, n);
552}
553
554void
556{
557 state_->reset();
558}
559
560void
561shake256_hash (const void *data, size_t data_length, uint8_t *hashvalues, size_t n)
562{
563 SHAKE256 context;
564 context.update ((const uint8_t*) data, data_length);
565 context.squeeze_digest (hashvalues, n);
566}
567
568// == Pcg32Rng ==
570 increment_ (0), accu_ (0)
571{
572 auto_seed();
573}
574
575Pcg32Rng::Pcg32Rng (uint64_t offset, uint64_t sequence) :
576 increment_ (0), accu_ (0)
577{
578 seed (offset, sequence);
579}
580
581void
583{
584 AutoSeeder seeder;
585 seed (seeder);
586}
587
588void
589Pcg32Rng::seed (uint64_t offset, uint64_t sequence)
590{
591 accu_ = sequence;
592 increment_ = (sequence << 1) | 1; // force increment_ to be odd
593 accu_ += offset;
594 accu_ = A * accu_ + increment_;
595}
596
597// == Random Numbers ==
598static uint64_t
599global_random64()
600{
601 static KeccakRng *global_rng = NULL;
602 static std::mutex mtx;
604 if (UNLIKELY (!global_rng))
605 {
606 uint64 entropy[32];
607 collect_runtime_entropy (entropy, ARRAY_SIZE (entropy));
608 static std::aligned_storage<sizeof (KeccakRng), alignof (KeccakRng)>::type mem;
609 // 8 rounds provide good statistical shuffling, and
610 // 256 hidden bits make the generator state unguessable
611 global_rng = new (&mem) KeccakRng (256, 8);
612 global_rng->seed (entropy, ARRAY_SIZE (entropy));
613 }
614 return global_rng->random();
615}
616
623{
624 return global_random64();
625}
626
632random_irange (int64_t begin, int64_t end)
633{
634 return_unless (begin < end, begin);
635 const uint64_t range = end - begin;
636 const uint64_t quotient = 0xffffffffffffffffULL / range;
637 const uint64_t bound = quotient * range;
638 uint64_t r = global_random64();
639 while (ASE_UNLIKELY (r >= bound)) // repeats with <50% probability
640 r = global_random64();
641 return begin + r / quotient;
642}
643
648double
650{
651 double r01;
652 do
653 r01 = global_random64() * 5.42101086242752217003726400434970855712890625e-20; // 1.0 / 2^64
654 while (ASE_UNLIKELY (r01 >= 1.0)); // retry if arithmetic exceeds boundary
655 return r01;
656}
657
662double
663random_frange (double begin, double end)
664{
665 return_unless (begin < end, begin + 0 * end); // catch and propagate NaNs
666 const double r01 = global_random64() * 5.42101086242752217003726400434970855712890625e-20; // 1.0 / 2^64
667 return end * r01 + (1.0 - r01) * begin;
668}
669
673{
674 static uint64_t cached_nonce = 0;
675 if (ASE_UNLIKELY (cached_nonce == 0))
676 random_secret (&cached_nonce);
677 return cached_nonce;
678}
679
681void
682random_secret (uint64_t *secret_var)
683{
684 static std::mutex mtx;
686 if (!*secret_var)
687 {
688 uint64_t d;
689 do
690 d = global_random64();
691 while (d == 0); // very unlikely
692 *secret_var = d;
693 }
694}
695
697
698
699Mwc256::Mwc256 (uint64_t x, uint64_t y, uint64_t z, uint64_t c)
700{
701 seed (x, y, z, c);
702}
703
704Mwc256::Mwc256()
705{
706 seed();
707}
708
709void
710Mwc256::seed()
711{
713}
714
715void
716Mwc256::seed (uint64_t x, uint64_t y, uint64_t z, uint64_t c)
717{
718 // modify seed inputs to make multiplicative correlation unlikely, https://pcg.di.unimi.it/pcg.php#conclusions
719 state[0] = x ^ 0xAAAAAAAAAAAAAAAA;
720 state[1] = y * 0x25363F651FC21EB5;
721 state[2] = rotl (z, 37);
722 state[3] = c ^ 0x5555555555555555;
723 // ensure: 0 < c < MWC_A3 - 1
724 while (!state[3] || state[3] >= MWC_A3 - 1)
725 state[3] = state[3] / 2 | 1;
726 for (size_t i = 0; i < 37; i++)
727 next();
728 // Background on multiply-with-carry: https://groups.google.com/g/sci.stat.math/c/p7aLW3TsJys/m/QGb1kti6kN0J
729}
730
731static constexpr uint mwc256_MP_SIZE = 5;
732
733// Minimal, inefficient MPC library, only for MWC jumps.
734static int
735mpc_cmp (const uint64_t *const a, const uint64_t *const b)
736{
737 for (int i = mwc256_MP_SIZE; i-- != 0; ) {
738 if (a[i] < b[i]) return -1;
739 if (a[i] > b[i]) return 1;
740 }
741 return 0;
742}
743
744static void
745mpc_bsub (uint64_t *const a, const uint64_t *const b)
746{
747 // Assumes a >= b
748 int borrow = 0;
749 for (int i = 0; i < mwc256_MP_SIZE; i++)
750 {
751 __int128_t d = (__int128_t) a[i] - (__int128_t) b[i] - (__int128_t) borrow;
752 borrow = d < 0;
753 a[i] = ((__int128_t) UINT64_MAX + 1) + d;
754 }
755}
756
757static void
758mpc_rem (uint64_t *const a, const uint64_t *const m)
759{
760 for (;;)
761 {
762 if (mpc_cmp (a, m) < 0)
763 return;
764 mpc_bsub (a, m);
765 }
766}
767
768static void
769mpc_add (uint64_t *const a, const uint64_t *const b, const uint64_t *const m)
770{
771 int carry = 0;
772 for (int i = 0; i < mwc256_MP_SIZE; i++)
773 {
774 __uint128_t s = (__uint128_t) a[i] + (__uint128_t) b[i] + (__uint128_t) carry;
775 carry = s > UINT64_MAX;
776 a[i] = s;
777 }
778 if (m)
779 mpc_rem (a, m);
780}
781
782static void
783mpc_mul (uint64_t *const a, const uint64_t *const b, const uint64_t *const m)
784{
785 uint64_t r[mwc256_MP_SIZE] = {}, t[mwc256_MP_SIZE];
786 memcpy (t, a, sizeof t);
787
788 int d;
789 for (d = mwc256_MP_SIZE; d-- != 0 && b[d] == 0;)
790 ;
791 d++;
792 for (int i = 0; i < d * 64; i++)
793 {
794 if (b[i >> 6] & (UINT64_C (1) << (i & 63)))
795 mpc_add (r, t, m);
796 mpc_add (t, t, m);
797 }
798
799 memcpy (a, r, sizeof r);
800}
801
802static uint64_t mwc256_mod[mwc256_MP_SIZE] = { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, Mwc256::MWC_A3 - 1 };
803
804Mwc256
805Mwc256::clone128()
806{
807 static uint64_t jump128[mwc256_MP_SIZE] = { 0x49ffebb8aed35da, 0x8aeb90fc17d34f8c, 0x3e78ff9958b436d9, 0x377fc42deaad8b46 };
808 uint64_t newstate[mwc256_MP_SIZE] = { state[0], state[1], state[2], state[3] };
809 mpc_mul (newstate, jump128, mwc256_mod);
810 Mwc256 gen (0, 0, 0, 1);
811 gen.state[0] = newstate[0];
812 gen.state[1] = newstate[1];
813 gen.state[2] = newstate[2];
814 gen.state[3] = newstate[3];
815 return gen;
816}
817
818Mwc256
819Mwc256::clone192()
820{
821 static uint64_t jump192[mwc256_MP_SIZE] = { 0x7cbd7641a0db932f, 0x1eafd94d7d3ac65c, 0xf4fc97e3b80db1b, 0x630e9c671e238c8a };
822 uint64_t newstate[mwc256_MP_SIZE] = { state[0], state[1], state[2], state[3] };
823 mpc_mul (newstate, jump192, mwc256_mod);
824 Mwc256 gen (0, 0, 0, 1);
825 gen.state[0] = newstate[0];
826 gen.state[1] = newstate[1];
827 gen.state[2] = newstate[2];
828 gen.state[3] = newstate[3];
829 return gen;
830}
831
832} // Ase
833
834#include "testing.hh"
835
836namespace { // Anon
837using namespace Ase;
838
839
840TEST_INTEGRITY (randomhash_tests);
841static void
842randomhash_tests()
843{
844 String s;
845 uint64 w, v;
846 s = "HUHUhaha";
847 w = fnv1a_consthash64 (s.c_str()); v = fnv1a_consthash64 (s.data(), s.size()); TASSERT (w == v);
848
849 FastRng a, b = a;
850 TASSERT (a.next() == b.next());
851 TASSERT (a.next() == b.next());
852 TASSERT (a.next() == b.next());
853 TASSERT (a.next() == b.next());
854 FastRng c = a.clone128();
855 FastRng d = a.clone192();
856 TASSERT (c.next() != d.next());
857 TASSERT (c.next() != d.next());
858 TASSERT (c.next() != d.next());
859 TASSERT (c.next() != d.next());
860 c = c.clone192();
861 d = d.clone128();
862 TASSERT (c.next() == d.next());
863 TASSERT (c.next() == d.next());
864 TASSERT (c.next() == d.next());
865 TASSERT (c.next() == d.next());
866 a = a.clone128().clone192();
867 TASSERT (a.next() != a.next());
868 TASSERT (a.next() != a.next());
869 TASSERT (a.next() != a.next());
870 TASSERT (a.next() != a.next());
871 TASSERT (a.next() == c.next()); d.next();
872 TASSERT (a.next() == d.next()); c.next();
873}
874
875} // Anon
T c_str(T... args)
AutoSeeder provides non-deterministic seeding entropy.
uint64_t random()
void auto_seed()
Seed the generator from a system specific nondeterministic random source.
void discard(unsigned long long count)
void seed(uint64_t seed_value=1)
Reinitialize the generator state using a 64 bit seed_value.
size_t n_nums() const
Amount of 64 bit random numbers per generated block.
void xor_seed(const uint64_t *seeds, size_t n_seeds)
~KeccakRng()
The destructor resets the generator state to avoid leaving memory trails.
Marsaglia multiply-with-carry generator, period ca 2^255.
Definition randomhash.hh:37
void auto_seed()
Seed the generator from a system specific nondeterministic random source.
Pcg32Rng()
Initialize and seed the generator from a system specific nondeterministic random source.
void seed(uint64_t offset, uint64_t sequence)
Seed by seeking to position offset within stream sequence.
size_t get_hash(uint8_t hashvalue[HASHBITS/8])
Switch from absorbing into squeezing mode and return digest.
void absorb_padding(size_t offset, uint8_t trail=0x01)
void squeeze_digest(uint8_t *output, size_t n_out)
Read out the current Keccak state and permute as needed.
size_t xor_state(size_t offset, const uint8_t *input, size_t n_in)
Add stream data up to block size into Keccak state via XOR.
T count(T... args)
#define ASE_ASSERT_RETURN(expr,...)
Return from the current function if expr evaluates to false and issue an assertion warning.
Definition cxxaux.hh:82
#define ASE_UNLIKELY(expr)
Compiler hint to optimize for expr evaluating to false.
Definition cxxaux.hh:46
T data(T... args)
T fill(T... args)
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
Definition internal.hh:71
#define ARRAY_SIZE(array)
Yield the number of C array elements.
Definition internal.hh:26
#define UNLIKELY(cond)
Hint to the compiler to optimize for cond == FALSE.
Definition internal.hh:63
#define TEST_INTEGRITY(FUNC)
Register func as an integrity test.
Definition internal.hh:77
memcpy
T min(T... args)
The Anklang C++ API namespace.
Definition api.hh:9
void sha3_224_hash(const void *data, size_t data_length, uint8_t hashvalue[28])
Calculate 224 bit SHA3 digest from data, see also class SHA3_224.
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
Definition cxxaux.hh:25
void collect_runtime_entropy(uint64 *data, size_t n)
Collect entropy from the current process, usually quicker than collect_system_entropy().
Definition entropy.cc:408
void shake256_hash(const void *data, size_t data_length, uint8_t *hashvalues, size_t n)
Calculate SHA3 extendable output digest for 256 bit security strength, see also class SHAKE256.
void sha3_384_hash(const void *data, size_t data_length, uint8_t hashvalue[48])
Calculate 384 bit SHA3 digest from data, see also class SHA3_384.
uint64_t cached_hash_secret
Use hash_secret() for access.
void sha3_256_hash(const void *data, size_t data_length, uint8_t hashvalue[32])
Calculate 256 bit SHA3 digest from data, see also class SHA3_256.
int64_t random_irange(int64_t begin, int64_t end)
void sha3_512_hash(const void *data, size_t data_length, uint8_t hashvalue[64])
Calculate 512 bit SHA3 digest from data, see also class SHA3_512.
uint64_t random_nonce()
Provide a unique 64 bit identifier that is not 0, see also random_int64().
void shake128_hash(const void *data, size_t data_length, uint8_t *hashvalues, size_t n)
Calculate SHA3 extendable output digest for 128 bit security strength, see also class SHAKE128.
double random_float()
uint32_t uint32
A 32-bit unsigned integer.
Definition cxxaux.hh:24
uint32_t uint
Provide 'uint' as convenience type.
Definition cxxaux.hh:18
double random_frange(double begin, double end)
uint64_t random_int64()
void memset4(uint32 *mem, uint32 filler, uint length)
Fill a memory area with a 32-bit quantitiy.
Definition strings.cc:1221
void random_secret(uint64_t *secret_var)
Generate a secret non-zero nonce in secret_var, unless it has already been assigned.
T rotl(T... args)
T size(T... args)
typedef uint8_t
SHA3_224()
Create context to calculate a 224 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void digest(uint8_t hashvalue[28])
Retrieve the resulting hash value.
void reset()
Reset state to feed and retrieve a new hash value.
SHA3_256()
Create context to calculate a 256 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void digest(uint8_t hashvalue[32])
Retrieve the resulting hash value.
void reset()
Reset state to feed and retrieve a new hash value.
void reset()
Reset state to feed and retrieve a new hash value.
SHA3_384()
Create context to calculate a 384 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void digest(uint8_t hashvalue[48])
Retrieve the resulting hash value.
void digest(uint8_t hashvalue[64])
Retrieve the resulting hash value.
SHA3_512()
Create context to calculate a 512 bit SHA3 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void reset()
Reset state to feed and retrieve a new hash value.
SHAKE128()
Create context to calculate an unbounded SHAKE128 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void reset()
Reset state to feed and retrieve a new hash value.
void squeeze_digest(uint8_t *hashvalues, size_t n)
Retrieve an arbitrary number of hash value bytes.
void reset()
Reset state to feed and retrieve a new hash value.
SHAKE256()
Create context to calculate an unbounded SHAKE256 hash digest.
void update(const uint8_t *data, size_t length)
Feed data to be hashed.
void squeeze_digest(uint8_t *hashvalues, size_t n)
Retrieve an arbitrary number of hash value bytes.
#define TASSERT(cond)
Unconditional test assertion, enters breakpoint if not fullfilled.
Definition testing.hh:24