-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprng.hpp
64 lines (54 loc) · 1.74 KB
/
prng.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#pragma once
#include "shake128.hpp"
#include <array>
#include <random>
#include <span>
// Pseudo Random Number Generator
namespace prng {
// Pseudo Random Number Generator s.t. N (>0) -many random bytes are read
// from SHAKE128 XOF state, by squeezing it arbitrary many times, s.t. SHAKE128
// state is obtained by
//
// - either absorbing 32 -bytes, sampled using std::random_device ( default )
// - or absorbing M(>0) -bytes, supplied as argument ( explicit )
//
// Note, std::random_device's behaviour is implementation defined feature, so
// this PRNG implementation doesn't guarantee that it'll generate cryptographic
// secure random bytes if you opt for using default constructor of this struct.
//
// I suggest you read
// https://en.cppreference.com/w/cpp/numeric/random/random_device/random_device
// before using default constructor. When using explicit constructor, it's
// your responsibility to supply M -many random seed bytes.
//
// This implementation is taken from
// https://github.com/itzmeanjan/dilithium/blob/6ac5eee0/include/prng.hpp
struct prng_t
{
private:
shake128::shake128_t state;
public:
inline prng_t()
{
std::array<uint8_t, 32> seed{};
auto _seed = std::span(seed);
// Read more @
// https://en.cppreference.com/w/cpp/numeric/random/random_device/random_device
std::random_device rd{};
size_t off = 0;
while (off < sizeof(seed)) {
const uint32_t v = rd();
std::memcpy(_seed.subspan(off, sizeof(v)).data(), &v, sizeof(v));
off += sizeof(v);
}
state.absorb(_seed);
state.finalize();
}
inline explicit prng_t(std::span<const uint8_t> seed)
{
state.absorb(seed);
state.finalize();
}
inline void read(std::span<uint8_t> bytes) { state.squeeze(bytes); }
};
}