Remove minor biasing problem from crypto_pseudo_rand_int

svn:r799
This commit is contained in:
Nick Mathewson 2003-11-12 04:28:30 +00:00
parent 7e4cb9a750
commit 5e4b9c6b61
2 changed files with 16 additions and 8 deletions

View File

@ -16,6 +16,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h>
#include "crypto.h" #include "crypto.h"
#include "../or/or.h" #include "../or/or.h"
@ -1008,14 +1009,21 @@ void crypto_pseudo_rand(unsigned int n, unsigned char *to)
} }
} }
int crypto_pseudo_rand_int(int max) { int crypto_pseudo_rand_int(unsigned int max) {
unsigned int val; unsigned int val;
crypto_pseudo_rand(sizeof(val), (unsigned char*) &val); unsigned int cutoff;
/* Bug: Low values are _slightly_ favored over high values because assert(max < UINT_MAX);
* ((unsigned)-1)%max != max-1 . This shouldn't matter if max is
* significantly smaller than ((unsigned)-1). /* We ignore any values that are >= 'cutoff,' to avoid biasing the
**/ * distribution with clipping at the upper end of unsigned int's
return val % max; * range.
*/
cutoff = UINT_MAX - (UINT_MAX%max);
while(1) {
crypto_pseudo_rand(sizeof(val), (unsigned char*) &val);
if (val < cutoff)
return val % max;
}
} }
/* errors */ /* errors */

View File

@ -101,7 +101,7 @@ int crypto_SHA_digest(unsigned char *m, int len, unsigned char *digest);
int crypto_seed_rng(); int crypto_seed_rng();
int crypto_rand(unsigned int n, unsigned char *to); int crypto_rand(unsigned int n, unsigned char *to);
void crypto_pseudo_rand(unsigned int n, unsigned char *to); void crypto_pseudo_rand(unsigned int n, unsigned char *to);
int crypto_pseudo_rand_int(int max); int crypto_pseudo_rand_int(unsigned int max);
/* errors */ /* errors */
char *crypto_perror(); char *crypto_perror();