mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Add secure_rand_below function
It works by masking the numbers and the using rejection sampling to ensure a uniform generation.
This commit is contained in:
parent
22ef342ffc
commit
782c826381
|
@ -2203,6 +2203,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST)
|
||||||
netaddr.cpp
|
netaddr.cpp
|
||||||
packer.cpp
|
packer.cpp
|
||||||
prng.cpp
|
prng.cpp
|
||||||
|
secure_random.cpp
|
||||||
sorted_array.cpp
|
sorted_array.cpp
|
||||||
str.cpp
|
str.cpp
|
||||||
strip_path_and_extension.cpp
|
strip_path_and_extension.cpp
|
||||||
|
|
|
@ -3608,6 +3608,34 @@ int secure_rand(void)
|
||||||
return (int)(i % RAND_MAX);
|
return (int)(i % RAND_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2.
|
||||||
|
static unsigned int find_next_power_of_two_minus_one(unsigned int n)
|
||||||
|
{
|
||||||
|
n--;
|
||||||
|
n |= n >> 1;
|
||||||
|
n |= n >> 2;
|
||||||
|
n |= n >> 4;
|
||||||
|
n |= n >> 4;
|
||||||
|
n |= n >> 16;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int secure_rand_below(int below)
|
||||||
|
{
|
||||||
|
unsigned int mask = find_next_power_of_two_minus_one(below);
|
||||||
|
dbg_assert(below > 0, "below must be positive");
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
unsigned int n;
|
||||||
|
secure_random_fill(&n, sizeof(n));
|
||||||
|
n &= mask;
|
||||||
|
if((int)n < below)
|
||||||
|
{
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2193,6 +2193,16 @@ void secure_random_fill(void *bytes, unsigned length);
|
||||||
*/
|
*/
|
||||||
int secure_rand(void);
|
int secure_rand(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: secure_rand_below
|
||||||
|
Returns a random nonnegative integer below the given number,
|
||||||
|
with a uniform distribution.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
below - Upper limit (exclusive) of integers to return.
|
||||||
|
*/
|
||||||
|
int secure_rand_below(int below);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
35
src/test/secure_random.cpp
Normal file
35
src/test/secure_random.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include "test.h"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <base/system.h>
|
||||||
|
|
||||||
|
TEST(SecureRandom, Fill)
|
||||||
|
{
|
||||||
|
unsigned int Bits = 0;
|
||||||
|
while(~Bits)
|
||||||
|
{
|
||||||
|
unsigned int Random;
|
||||||
|
secure_random_fill(&Random, sizeof(Random));
|
||||||
|
Bits |= Random;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SecureRandom, Below1)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(secure_rand_below(1), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SecureRandom, Below)
|
||||||
|
{
|
||||||
|
int BOUNDS[] = {2, 3, 4, 5, 10, 100, 127, 128, 129};
|
||||||
|
for(int i = 0; i < sizeof(BOUNDS) / sizeof(BOUNDS[0]); i++)
|
||||||
|
{
|
||||||
|
int Below = BOUNDS[i];
|
||||||
|
for(int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
int Random = secure_rand_below(Below);
|
||||||
|
EXPECT_GE(Random, 0);
|
||||||
|
EXPECT_LT(Random, Below);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,5 +15,10 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
net_init();
|
net_init();
|
||||||
|
if(secure_random_init())
|
||||||
|
{
|
||||||
|
fprintf(stderr, "random init failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue