-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprng.hpp
64 lines (54 loc) · 1.85 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, arbitrary many times s.t. SHAKE128 state is obtained by
//
// - either hashing 32 -bytes sampled using std::random_device ( default )
// - or hashing 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.
struct prng_t
{
private:
shake128::shake128_t state;
public:
// Default constructor which seeds PRNG with system randomness.
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();
}
// Explicit constructor which can be used for seeding PRNG.
inline explicit prng_t(std::span<const uint8_t> seed)
{
state.absorb(seed);
state.finalize();
}
// Once PRNG is seeded i.e. PRNG object is constructed, you can request
// arbitrary many pseudo-random bytes from PRNG.
inline void read(std::span<uint8_t> bytes) { state.squeeze(bytes); }
};
}