Skip to content

Commit 15a1a53

Browse files
committed
prg documentation
1 parent ce470c9 commit 15a1a53

File tree

2 files changed

+33
-55
lines changed

2 files changed

+33
-55
lines changed

include/scl/primitives/prg.h

Lines changed: 31 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -20,45 +20,43 @@
2020

2121
#include <array>
2222
#include <cstddef>
23-
#include <memory>
2423
#include <stdexcept>
2524
#include <string>
2625
#include <vector>
2726

2827
#include <emmintrin.h>
2928

30-
/**
31-
* @brief 64 bit nonce which is prepended to the counter in the PRG.
32-
*/
33-
#ifndef PRG_NONCE
34-
#define PRG_NONCE 0x0123456789ABCDEF
35-
#endif
36-
37-
/**
38-
* @brief The initial value of the PRG counter.
39-
*/
40-
#ifndef PRG_INITIAL_COUNTER
41-
#define PRG_INITIAL_COUNTER 0
42-
#endif
43-
4429
namespace scl {
4530

4631
/**
47-
* @brief Pseudorandom generator based on AES-CTR.
32+
* @brief Pseudorandom generator.
33+
*
34+
* @code
35+
* auto prg = PRG::create();
4836
*
49-
* The <code>PRG</code> class implements a pseudorandom generator based on
50-
* AES-CTR where the n'th block of output is generated by encrypting a
51-
* counter. A block of random data is generated by computing
37+
* std::array<unsigned char, 10> buffer;
38+
* prg.next(buffer); // buffer is filled with random bytes
5239
*
53-
* <code>block := AES(seed, counter)</code>
40+
* std::vector<unsigned char> rands = prg.next(42);
41+
* assert(rands.size() == 42);
5442
*
55-
* where <code>seed</code> is either all 0s or a user supplied value, and
56-
* <code>counter</code> is a 128-bit counter initialized to be
43+
* auto prg1 = PRG::create("seed1");
44+
* auto prg2 = PRG::create("seed2");
5745
*
58-
* <code>counter_init := PRG_NONCE || 0 ... 0</code>
46+
* assert(prg1.next(42) != prg2.next(42));
47+
* @endcode
5948
*
60-
* where each half is 64 bits. The value of PRG_NONCE can be set by defining it
61-
* as a macro. It defaults to <code>0x0123456789ABCDEF</code>.
49+
* The underlying implementation of PRG is based on AES128 in counter mode.
50+
* When supplying an explicit seed, only the first PRG::seedSize() bytes are
51+
* used. For the current implementation this means only the first 16 bytes are
52+
* counted.
53+
*
54+
* @code
55+
* auto prg1 = PRG::create("abcdef0123456789abc");
56+
* auto prg2 = PRG::create("abcdef0123456789xyz");
57+
*
58+
* assert(prg1.next(42) == prg2.next(42));
59+
* @endcode
6260
*/
6361
class PRG {
6462
private:
@@ -80,60 +78,41 @@ class PRG {
8078

8179
/**
8280
* @brief Create a new PRG with a provided seed.
83-
* @param seed the seed.
84-
* @param seed_len length of the seed
8581
*/
8682
static PRG create(const unsigned char* seed, std::size_t seed_len);
8783

8884
/**
8985
* @brief Create a new PRG from a provided seed.
90-
* @param seed the seed.
9186
*/
9287
static PRG create(const std::string& seed);
9388

9489
/**
9590
* @brief Reset the PRG.
96-
*
97-
* This method allows resetting a PRG object to its initial state.
9891
*/
9992
void reset();
10093

10194
/**
10295
* @brief Generate random data and store it in a supplied buffer.
103-
* @param buffer the buffer
104-
* @param n how many bytes of random data to generate
10596
*/
10697
void next(unsigned char* buffer, std::size_t n);
10798

10899
/**
109100
* @brief Generate random data and store it in a supplied buffer.
110-
* @param buffer the buffer with space pre-allocated
111-
*
112-
* How many bytes of random data to generate is decided based on the output of
113-
* <code>buffer.size()</code>.
114101
*/
115102
void next(std::vector<unsigned char>& buffer) {
116103
next(buffer.data(), buffer.size());
117104
}
118105

119106
/**
120107
* @brief Generate random data and store it in a supplied buffer.
121-
* @param buffer the buffer.
122108
*/
123109
template <std::size_t N>
124110
void next(std::array<unsigned char, N>& buffer) {
125-
Next(buffer.data(), N);
111+
next(buffer.data(), N);
126112
}
127113

128114
/**
129115
* @brief Generate random data and store in in a supplied buffer.
130-
* @param buffer the buffer
131-
* @param n how many random bytes to generate
132-
* @throws std::invalid_argument if \p n is greater than
133-
* <code>buffer.size()</code>.
134-
*
135-
* The capacity of \p buffer is not affected in any way by this method and it
136-
* requires that it has room for at least \p n elements.
137116
*/
138117
void next(std::vector<unsigned char>& buffer, std::size_t n) {
139118
if (buffer.size() < n) {
@@ -144,13 +123,12 @@ class PRG {
144123

145124
/**
146125
* @brief Generate and return random data.
147-
* @param n the number of random bytes to generate
148-
* @return the random bytes.
149126
*/
150127
std::vector<unsigned char> next(std::size_t n) {
151-
auto buffer = std::make_unique<unsigned char[]>(n);
152-
next(buffer.get(), n);
153-
return std::vector<unsigned char>(buffer.get(), buffer.get() + n);
128+
std::vector<unsigned char> buffer;
129+
buffer.reserve(n);
130+
next(buffer);
131+
return buffer;
154132
}
155133

156134
/**
@@ -161,12 +139,12 @@ class PRG {
161139
}
162140

163141
private:
164-
PRG(std::array<unsigned char, BLOCK_SIZE> seed) : m_seed(seed) {};
165-
166142
std::array<unsigned char, BLOCK_SIZE> m_seed = {0};
167-
long m_counter = PRG_INITIAL_COUNTER;
143+
long m_counter = 0;
168144
BlockType m_state[11];
169145

146+
PRG(std::array<unsigned char, BLOCK_SIZE> seed) : m_seed(seed) {};
147+
170148
void update();
171149
void init();
172150
};

src/scl/primitives/prg.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void aes128Enc(const __m128i* key_schedule, __m128i m, unsigned char* ct) {
8080
}
8181

8282
auto createMask(long counter) {
83-
return _mm_set_epi64x(PRG_NONCE, counter);
83+
return _mm_set_epi64x(0x0123456789ABCDEF, counter);
8484
}
8585

8686
} // namespace
@@ -117,7 +117,7 @@ void scl::PRG::init() {
117117

118118
void scl::PRG::reset() {
119119
init();
120-
m_counter = PRG_INITIAL_COUNTER;
120+
m_counter = 0;
121121
}
122122

123123
void scl::PRG::next(unsigned char* buffer, size_t n) {

0 commit comments

Comments
 (0)