Suppose I have an array of bytes from a secure PRNG, and I need to generate a number between 1 and 10 using that data, how would I do that correctly?
- 
                    6Don't get me wrong, but the answer is `by writing a piece of code.` :-) – Sourav Ghosh Mar 18 '15 at 12:30
- 
                    BTW, are you looking for [modulus operator](http://www.cprogramming.com/tutorial/modulus.html)? – Sourav Ghosh Mar 18 '15 at 12:32
- 
                    @SouravGhosh Yes it could be done using modulus, if you make the comment an answer I accept it. – Maestro Mar 18 '15 at 12:35
- 
                    1If you go for `%`, then you also might want to read about the [modulo bias](https://zuttobenkyou.wordpress.com/2012/10/18/generating-random-numbers-without-modulo-bias/). – cremno Mar 18 '15 at 12:41
- 
                    Personally I would look up a piece of code (usually called something like `getInt(int max)`) and integrate that. Otherwise it's pretty easy to create bias. Related [JavaCard code](http://stackoverflow.com/a/17309537/589259) . Mind the remarks. – Maarten Bodewes Mar 18 '15 at 13:53
- 
                    I presume you mean `1 <= x <= 10` here :) – Maarten Bodewes Mar 18 '15 at 15:19
- 
                    I think the [first paragraph of this answer](http://crypto.stackexchange.com/a/5721/1172) tells you all you need to know. – Maarten Bodewes Mar 18 '15 at 15:28
4 Answers
As per the comments follow-up, it seems what you need is modulus operator [%].
You may also need to check the related wiki.
Note: Every time we use the modulo operator on a random number, there is a probability that we'll be running into modulo bias, which ends up in disbalancing the fair distribution of random numbers. You've to take care of that.
For a detailed discussion on this, please see this question and related answers.
 
    
    - 1
- 1
 
    
    - 133,132
- 16
- 183
- 261
- 
                    Please add some information about bias to make this answer complete. – Maarten Bodewes Mar 18 '15 at 13:58
- 
                    
- 
                    Much better. Unfortunately the answers in the link are pretty poor. Maybe try [this](http://crypto.stackexchange.com/q/7996/1172) instead. You could of course use 8 bit number for a range 0..10 - depends if you want to change to a larger range and how much data you want to extract from the random pool (you would be OK with just 4 bits, but you would have a reject 6 times out of 16, which is rather poor). – Maarten Bodewes Mar 18 '15 at 15:15
Think of the array as one big unsigned integer. Then the answer is simple:
(Big_Number % 10) + 1
So all that is needed is a method to find the modulus 10 of big integers. Using modular exponentiation:
#include <limits.h>
#include <stdlib.h>
int ArrayMod10(const unsigned char *a, size_t n) {
  int mod10 = 0;
  int base = (UCHAR_MAX + 1) % 10;
  for (size_t i = n; i-- > 0;  ) {
    mod10 = (base*mod10 + a[i]) % 10;
    base = (base * base) % 10;
  }
  return mod10;
}
void test10(size_t n) {
  unsigned char a[n];
  // fill array with your secure PRNG
  for (size_t i = 0; i<n; i++) a[i] = rand();
  return ArrayMod10(a, n) + 1;
}
There will be a slight bias as 256^n is not a power of 10.  With large n, this will rapidly decrease in significance.
Untested code: Detect if a biased result occurred.  Calling code could repeatedly call this function with new a array values to get an unbiased result on the rare occasions when bias occurs.
int ArrayMod10BiasDetect(const unsigned char *a, size_t n, bool *biasptr) {
  bool bias = true;
  int mod10 = 0;
  int base = (UCHAR_MAX + 1) % 10;  // Note base is usually 6: 256%10, 65536%10, etc.
  for (size_t i = n; i-- > 0;  ) {
    mod10 = (base*mod10 + a[i]) % 10;
    if (n > 0) {
      if (a[i] < UCHAR_MAX) bias = false;
    } else {
      if (a[i] < UCHAR_MAX + 1 - base) bias = false;
    }
    base = (base * base) % 10;
  }
  *biaseptr = bias;
  return mod10;
}
 
    
    - 143,097
- 13
- 135
- 256
- 
                    @Maarten Bodewes Given OP is using a "secure PRNG", certainly of reasonable length, so agree, no practical need for bias concerns. – chux - Reinstate Monica Mar 18 '15 at 17:44
- 
                    I want to use this code, but in reality I dont need to pick between 1 and 10, it needs to be variabele. Can I just safely replace every occurence of 1 and 10 in your code with a upper/lower bound variabele? – Maestro Mar 18 '15 at 18:33
- 
                    @Muis Almost. Let `ArrayModX()` return the range [0...X-1], then add lower bound with`X = upper-lower+1`. If the number is outside the range 255, use larger objects than `unsigned char *a` like `uint32_t *a` and then the "10" can be replaced. Some additional concerns come in if your "10" is larger than `INT_MAX`. IOWs saying "code with a upper/lower bound variable" is too vague. Better to say the type or range of the number like: `0 <= lower_bound <= upper_bound <= INT_MAX` or something like that. – chux - Reinstate Monica Mar 18 '15 at 19:08
- 
                    This answer does still have bias, where no bias is really required. – Maarten Bodewes Mar 18 '15 at 21:41
- 
                    @Maarten Bodewes `ArrayMod10BiasDetect()` detects and reports the bias that occurs with modulo `10` on a binary number. Do you refer to some other bias? – chux - Reinstate Monica Mar 18 '15 at 22:42
It depends on a bunch of things. Secure PRNG sometimes makes long byte arrays instead of integers, let's say it is 16 bytes long array, then extract 32 bit integer like so: buf[0]*0x1000000+buf[1]*0x10000+buf[2]*0x100+buf[3] or use shift operator. This is random so big-endian/little-endian doesn't matter. 
char randbytes[16];
//...
const char *p = randbytes;
//assumes size of int is 4
unsigned int rand1 = p[0] << 24 + p[1] << 16 + p[2] << 8 + p[3]; p += 4;
unsigned int rand2 = p[0] << 24 + p[1] << 16 + p[2] << 8 + p[3]; p += 4;
unsigned int rand3 = p[0] << 24 + p[1] << 16 + p[2] << 8 + p[3]; p += 4;
unsigned int rand4 = p[0] << 24 + p[1] << 16 + p[2] << 8 + p[3];
Then use % on the integer
ps, I think that's a long answer. If you want number between 1 and 10 then just use % on first byte.
 
    
    - 30,904
- 6
- 40
- 77
- 
                    This will leave you with a small but detectable bias Why would you need 16 bytes to generate an integer of 32 bits???. – Maarten Bodewes Mar 18 '15 at 17:21
- 
                    It's 4 different integers extracted from 16 bytes, it's typical output of secure PRNG. I changed my mind after typing it, I don't think the question has anything to do with secure PRNG – Barmak Shemirani Mar 18 '15 at 19:22
OK, so this answer is in Java until I get to my Eclipse C/C++ IDE:
public final static int simpleBound(Random rbg, int n) {
    final int BYTE_VALUES = 256;
    // sanity check, only return positive numbers
    if (n <= 0) {
        throw new IllegalArgumentException("Oops");
    }
    // sanity check: choice of value 0 or 0...
    if (n == 1) {
        return 0;
    }
    // sanity check: does not fit in byte
    if (n > BYTE_VALUES) {
        throw new IllegalArgumentException("Oops");
    }
    // optimization for n = 2^y
    if (Integer.bitCount(n) == 1) {
        final int mask = n - 1;
        return retrieveRandomByte(rbg) & mask;
    }
    // you can skip to this if you are sure n = 10
    // z is upper bound, and contains floor(z / n) blocks of n values
    final int z = (BYTE_VALUES / n) * n;
    int x;
    do {
        x = retrieveRandomByte(rbg);
    } while (x >= z);
    return x % n;
}
So n is the maximum value in a range [0..n), i.e. n is exclusive. For a range [1..10] simply increase the result with 1.
 
    
    - 90,524
- 13
- 150
- 263
- 
                    Note that you need a maximum of 24 bytes to generate a number between 1 and 10 (after that the chance of not generating a number between 1 and 10 becomes smaller than 1 / 2 ^ 128 :P ) – Maarten Bodewes Mar 18 '15 at 16:56
- 
                    Note too that it would be recommended to use a 16 bit number if you want to bring down the maximum number of bytes required (in this case to 20 bytes). – Maarten Bodewes Mar 18 '15 at 17:16
- 
                    I dont know how to translate (Integer.bitCount(n) == 1) to C, so I cannot use this function. – Maestro Mar 18 '15 at 18:36
- 
                    You can simply leave it out, that's required for optimization only. However, [this is stackoverflow](http://stackoverflow.com/q/109023/589259). If you need a link on how to convert `unsigned char` to a 32 bit value, just scream :) – Maarten Bodewes Mar 18 '15 at 18:39
