Skip to content

Make all non-test randomness user-provided #95

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions include/minisketch.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,19 @@ MINISKETCH_API uint32_t minisketch_implementation_max(void);
*/
MINISKETCH_API int minisketch_implementation_supported(uint32_t bits, uint32_t implementation);

/** Construct a sketch for a given element size, implementation and capacity.
/** Construct a sketch for a given element size, implementation, capacity, and RNG seed.
*
* If the combination of `bits` and `implementation` is unavailable, or when
* OOM occurs, NULL is returned. If minisketch_implementation_supported
* returns 1 for the specified bits and implementation, this will always succeed
* (except when allocation fails).
*
* To protect against bad performance on maliciously-created sketches, it is
* to use strong randomness for the provided seed value.
*
* If the result is not NULL, it must be destroyed using minisketch_destroy.
*/
MINISKETCH_API minisketch* minisketch_create(uint32_t bits, uint32_t implementation, size_t capacity);
MINISKETCH_API minisketch* minisketch_create(uint32_t bits, uint32_t implementation, size_t capacity, uint64_t seed);

/** Get the element size of a sketch in bits. */
MINISKETCH_API uint32_t minisketch_bits(const minisketch* sketch);
Expand All @@ -82,14 +85,11 @@ MINISKETCH_API uint32_t minisketch_implementation(const minisketch* sketch);

/** Set the seed for randomizing algorithm choices to a fixed value.
*
* By default, sketches are initialized with a random seed. This is important
* to avoid scenarios where an attacker could force worst-case behavior.
*
* This function initializes the seed to a user-provided value (any 64-bit
* integer is acceptable, regardless of field size).
* This is equivalent to recreating the sketch with a different RNG seed.
*
* When seed is -1, a fixed internal value with predictable behavior is
* used. It is only intended for testing.
* used. It is only intended for testing. Note that minisketch_create does
* assign special meaning to seed = -1.
*/
MINISKETCH_API void minisketch_set_seed(minisketch* sketch, uint64_t seed);

Expand Down Expand Up @@ -263,16 +263,16 @@ class Minisketch
* ImplementationSupported(), or OOM occurs internally, an invalid Minisketch
* object will be constructed. Use operator bool() to check that this isn't the
* case before performing any other operations. */
Minisketch(uint32_t bits, uint32_t implementation, size_t capacity) noexcept
Minisketch(uint32_t bits, uint32_t implementation, size_t capacity, uint64_t seed) noexcept
{
m_minisketch = std::unique_ptr<minisketch, Deleter>(minisketch_create(bits, implementation, capacity));
m_minisketch = std::unique_ptr<minisketch, Deleter>(minisketch_create(bits, implementation, capacity, seed));
}

/** Create a Minisketch object sufficiently large for the specified number of elements at given fpbits.
* It may construct an invalid object, which you may need to check for. */
static Minisketch CreateFP(uint32_t bits, uint32_t implementation, size_t max_elements, uint32_t fpbits) noexcept
static Minisketch CreateFP(uint32_t bits, uint32_t implementation, size_t max_elements, uint32_t fpbits, uint64_t seed) noexcept
{
return Minisketch(bits, implementation, ComputeCapacity(bits, max_elements, fpbits));
return Minisketch(bits, implementation, ComputeCapacity(bits, max_elements, fpbits), seed);
}

/** Return the field size for a (valid) Minisketch object. */
Expand Down
8 changes: 4 additions & 4 deletions src/bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ int main(int argc, char** argv) {
printf("Usage: %s [syndromes=150] [errors=syndromes] [iters=10]\n", argv[0]);
return 1;
}
std::random_device rng;
std::uniform_int_distribution<uint64_t> dist;
int syndromes = argc > 1 ? strtoul(argv[1], NULL, 10) : 150;
int errors = argc > 2 ? strtoul(argv[2], NULL, 10) : syndromes;
int iters = argc > 3 ? strtoul(argv[3], NULL, 10) : 10;
Expand Down Expand Up @@ -47,7 +49,7 @@ int main(int argc, char** argv) {
std::vector<double> benches;
benches.reserve(iters);
for (int i = 0; i < iters; ++i) {
states[i] = minisketch_create(bits, impl, syndromes);
states[i] = minisketch_create(bits, impl, syndromes, dist(rng));
if (!states[i]) break;
std::set<uint64_t> done;
for (int j = 0; j < errors; ++j) {
Expand Down Expand Up @@ -80,15 +82,13 @@ int main(int argc, char** argv) {
printf("create[ns]\t% 3i\t", bits);
for (uint32_t impl = 0; impl <= max_impl; ++impl) {
std::vector<minisketch*> states;
std::random_device rng;
std::uniform_int_distribution<uint64_t> dist;
std::vector<uint64_t> data;
data.resize(errors * 10);
states.resize(iters);
std::vector<double> benches;
benches.reserve(iters);
for (int i = 0; i < iters; ++i) {
states[i] = minisketch_create(bits, impl, syndromes);
states[i] = minisketch_create(bits, impl, syndromes, dist(rng));
}
for (size_t i = 0; i < data.size(); ++i) {
data[i] = dist(rng);
Expand Down
20 changes: 10 additions & 10 deletions src/fields/clmul_1byte.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,37 +82,37 @@ typedef Field<uint8_t, 8, 27, StatTable8, &SQR_TABLE_8, &SQR2_TABLE_8, &QRT_TABL
#endif
}

Sketch* ConstructClMul1Byte(int bits, int implementation) {
Sketch* ConstructClMul1Byte(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_5
case 5: return new SketchImpl<Field5>(implementation, 5);
case 5: return new SketchImpl<Field5>(implementation, 5, seed);
#endif
#ifdef ENABLE_FIELD_INT_8
case 8: return new SketchImpl<Field8>(implementation, 8);
case 8: return new SketchImpl<Field8>(implementation, 8, seed);
#endif
}
return nullptr;
}

Sketch* ConstructClMulTri1Byte(int bits, int implementation) {
Sketch* ConstructClMulTri1Byte(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_2
case 2: return new SketchImpl<FieldTri2>(implementation, 2);
case 2: return new SketchImpl<FieldTri2>(implementation, 2, seed);
#endif
#ifdef ENABLE_FIELD_INT_3
case 3: return new SketchImpl<FieldTri3>(implementation, 3);
case 3: return new SketchImpl<FieldTri3>(implementation, 3, seed);
#endif
#ifdef ENABLE_FIELD_INT_4
case 4: return new SketchImpl<FieldTri4>(implementation, 4);
case 4: return new SketchImpl<FieldTri4>(implementation, 4, seed);
#endif
#ifdef ENABLE_FIELD_INT_5
case 5: return new SketchImpl<FieldTri5>(implementation, 5);
case 5: return new SketchImpl<FieldTri5>(implementation, 5, seed);
#endif
#ifdef ENABLE_FIELD_INT_6
case 6: return new SketchImpl<FieldTri6>(implementation, 6);
case 6: return new SketchImpl<FieldTri6>(implementation, 6, seed);
#endif
#ifdef ENABLE_FIELD_INT_7
case 7: return new SketchImpl<FieldTri7>(implementation, 7);
case 7: return new SketchImpl<FieldTri7>(implementation, 7, seed);
#endif
}
return nullptr;
Expand Down
28 changes: 14 additions & 14 deletions src/fields/clmul_2bytes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,49 +105,49 @@ typedef Field<uint16_t, 16, 43, StatTable16, &SQR_TABLE_16, &SQR2_TABLE_16, &SQR
#endif
}

Sketch* ConstructClMul2Bytes(int bits, int implementation) {
Sketch* ConstructClMul2Bytes(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_10
case 10: return new SketchImpl<Field10>(implementation, 10);
case 10: return new SketchImpl<Field10>(implementation, 10, seed);
#endif
#ifdef ENABLE_FIELD_INT_11
case 11: return new SketchImpl<Field11>(implementation, 11);
case 11: return new SketchImpl<Field11>(implementation, 11, seed);
#endif
#ifdef ENABLE_FIELD_INT_12
case 12: return new SketchImpl<Field12>(implementation, 12);
case 12: return new SketchImpl<Field12>(implementation, 12, seed);
#endif
#ifdef ENABLE_FIELD_INT_13
case 13: return new SketchImpl<Field13>(implementation, 13);
case 13: return new SketchImpl<Field13>(implementation, 13, seed);
#endif
#ifdef ENABLE_FIELD_INT_14
case 14: return new SketchImpl<Field14>(implementation, 14);
case 14: return new SketchImpl<Field14>(implementation, 14, seed);
#endif
#ifdef ENABLE_FIELD_INT_16
case 16: return new SketchImpl<Field16>(implementation, 16);
case 16: return new SketchImpl<Field16>(implementation, 16, seed);
#endif
}
return nullptr;
}

Sketch* ConstructClMulTri2Bytes(int bits, int implementation) {
Sketch* ConstructClMulTri2Bytes(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_9
case 9: return new SketchImpl<FieldTri9>(implementation, 9);
case 9: return new SketchImpl<FieldTri9>(implementation, 9, seed);
#endif
#ifdef ENABLE_FIELD_INT_10
case 10: return new SketchImpl<FieldTri10>(implementation, 10);
case 10: return new SketchImpl<FieldTri10>(implementation, 10, seed);
#endif
#ifdef ENABLE_FIELD_INT_11
case 11: return new SketchImpl<FieldTri11>(implementation, 11);
case 11: return new SketchImpl<FieldTri11>(implementation, 11, seed);
#endif
#ifdef ENABLE_FIELD_INT_12
case 12: return new SketchImpl<FieldTri12>(implementation, 12);
case 12: return new SketchImpl<FieldTri12>(implementation, 12, seed);
#endif
#ifdef ENABLE_FIELD_INT_14
case 14: return new SketchImpl<FieldTri14>(implementation, 14);
case 14: return new SketchImpl<FieldTri14>(implementation, 14, seed);
#endif
#ifdef ENABLE_FIELD_INT_15
case 15: return new SketchImpl<FieldTri15>(implementation, 15);
case 15: return new SketchImpl<FieldTri15>(implementation, 15, seed);
#endif
}
return nullptr;
Expand Down
30 changes: 15 additions & 15 deletions src/fields/clmul_3bytes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,52 +114,52 @@ typedef Field<uint32_t, 24, 27, StatTable24, &SQR_TABLE_24, &SQR2_TABLE_24, &SQR
#endif
}

Sketch* ConstructClMul3Bytes(int bits, int implementation) {
Sketch* ConstructClMul3Bytes(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_17
case 17: return new SketchImpl<Field17>(implementation, 17);
case 17: return new SketchImpl<Field17>(implementation, 17, seed);
#endif
#ifdef ENABLE_FIELD_INT_18
case 18: return new SketchImpl<Field18>(implementation, 18);
case 18: return new SketchImpl<Field18>(implementation, 18, seed);
#endif
#ifdef ENABLE_FIELD_INT_19
case 19: return new SketchImpl<Field19>(implementation, 19);
case 19: return new SketchImpl<Field19>(implementation, 19, seed);
#endif
#ifdef ENABLE_FIELD_INT_20
case 20: return new SketchImpl<Field20>(implementation, 20);
case 20: return new SketchImpl<Field20>(implementation, 20, seed);
#endif
#ifdef ENABLE_FIELD_INT_21
case 21: return new SketchImpl<Field21>(implementation, 21);
case 21: return new SketchImpl<Field21>(implementation, 21, seed);
#endif
#ifdef ENABLE_FIELD_INT_23
case 23: return new SketchImpl<Field23>(implementation, 23);
case 23: return new SketchImpl<Field23>(implementation, 23, seed);
#endif
#ifdef ENABLE_FIELD_INT_24
case 24: return new SketchImpl<Field24>(implementation, 24);
case 24: return new SketchImpl<Field24>(implementation, 24, seed);
#endif
}
return nullptr;
}

Sketch* ConstructClMulTri3Bytes(int bits, int implementation) {
Sketch* ConstructClMulTri3Bytes(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_17
case 17: return new SketchImpl<FieldTri17>(implementation, 17);
case 17: return new SketchImpl<FieldTri17>(implementation, 17, seed);
#endif
#ifdef ENABLE_FIELD_INT_18
case 18: return new SketchImpl<FieldTri18>(implementation, 18);
case 18: return new SketchImpl<FieldTri18>(implementation, 18, seed);
#endif
#ifdef ENABLE_FIELD_INT_20
case 20: return new SketchImpl<FieldTri20>(implementation, 20);
case 20: return new SketchImpl<FieldTri20>(implementation, 20, seed);
#endif
#ifdef ENABLE_FIELD_INT_21
case 21: return new SketchImpl<FieldTri21>(implementation, 21);
case 21: return new SketchImpl<FieldTri21>(implementation, 21, seed);
#endif
#ifdef ENABLE_FIELD_INT_22
case 22: return new SketchImpl<FieldTri22>(implementation, 22);
case 22: return new SketchImpl<FieldTri22>(implementation, 22, seed);
#endif
#ifdef ENABLE_FIELD_INT_23
case 23: return new SketchImpl<FieldTri23>(implementation, 23);
case 23: return new SketchImpl<FieldTri23>(implementation, 23, seed);
#endif
}
return nullptr;
Expand Down
26 changes: 13 additions & 13 deletions src/fields/clmul_4bytes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,46 +112,46 @@ typedef Field<uint32_t, 32, 141, StatTable32, &SQR_TABLE_32, &SQR2_TABLE_32, &SQ
#endif
}

Sketch* ConstructClMul4Bytes(int bits, int implementation) {
Sketch* ConstructClMul4Bytes(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_25
case 25: return new SketchImpl<Field25>(implementation, 25);
case 25: return new SketchImpl<Field25>(implementation, 25, seed);
#endif
#ifdef ENABLE_FIELD_INT_26
case 26: return new SketchImpl<Field26>(implementation, 26);
case 26: return new SketchImpl<Field26>(implementation, 26, seed);
#endif
#ifdef ENABLE_FIELD_INT_27
case 27: return new SketchImpl<Field27>(implementation, 27);
case 27: return new SketchImpl<Field27>(implementation, 27, seed);
#endif
#ifdef ENABLE_FIELD_INT_29
case 29: return new SketchImpl<Field29>(implementation, 29);
case 29: return new SketchImpl<Field29>(implementation, 29, seed);
#endif
#ifdef ENABLE_FIELD_INT_31
case 31: return new SketchImpl<Field31>(implementation, 31);
case 31: return new SketchImpl<Field31>(implementation, 31, seed);
#endif
#ifdef ENABLE_FIELD_INT_32
case 32: return new SketchImpl<Field32>(implementation, 32);
case 32: return new SketchImpl<Field32>(implementation, 32, seed);
#endif
}
return nullptr;
}

Sketch* ConstructClMulTri4Bytes(int bits, int implementation) {
Sketch* ConstructClMulTri4Bytes(int bits, int implementation, uint64_t seed) {
switch (bits) {
#ifdef ENABLE_FIELD_INT_25
case 25: return new SketchImpl<FieldTri25>(implementation, 25);
case 25: return new SketchImpl<FieldTri25>(implementation, 25, seed);
#endif
#ifdef ENABLE_FIELD_INT_28
case 28: return new SketchImpl<FieldTri28>(implementation, 28);
case 28: return new SketchImpl<FieldTri28>(implementation, 28, seed);
#endif
#ifdef ENABLE_FIELD_INT_29
case 29: return new SketchImpl<FieldTri29>(implementation, 29);
case 29: return new SketchImpl<FieldTri29>(implementation, 29, seed);
#endif
#ifdef ENABLE_FIELD_INT_30
case 30: return new SketchImpl<FieldTri30>(implementation, 30);
case 30: return new SketchImpl<FieldTri30>(implementation, 30, seed);
#endif
#ifdef ENABLE_FIELD_INT_31
case 31: return new SketchImpl<FieldTri31>(implementation, 31);
case 31: return new SketchImpl<FieldTri31>(implementation, 31, seed);
#endif
}
return nullptr;
Expand Down
Loading