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 <assert.h>
#include <stdio.h>
#include <limits.h>
#include "crypto.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;
crypto_pseudo_rand(sizeof(val), (unsigned char*) &val);
/* Bug: Low values are _slightly_ favored over high values because
* ((unsigned)-1)%max != max-1 . This shouldn't matter if max is
* significantly smaller than ((unsigned)-1).
**/
return val % max;
unsigned int cutoff;
assert(max < UINT_MAX);
/* We ignore any values that are >= 'cutoff,' to avoid biasing the
* distribution with clipping at the upper end of unsigned int's
* range.
*/
cutoff = UINT_MAX - (UINT_MAX%max);
while(1) {
crypto_pseudo_rand(sizeof(val), (unsigned char*) &val);
if (val < cutoff)
return val % max;
}
}
/* 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_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 */
char *crypto_perror();