3
votes

The documentation for GMP seems to list only the following algorithms for random number generation:

  • gmp_randinit_mt, the Mersenne Twister;
  • gmp_randinit_lc_2exp and gmp_randinit_lc_2exp_size, linear congruential.

There is also gmp_randinit_default, but it points to gmp_randinit_mt.

Neither the Mersenne Twister nor linear congruential generators should be used for Cryptography. What do people usually do, then, when they want to use the GMP to build some cryptographic code?

(Using a cryptographic API for encrypting/decrypting/etc doesn't help, because I'd actually implement a new algorithm, which crypto libraries do not have).

1
Implementing new crypto and not knowing what generator to use brings bad karma. Very bad karma!! security.stackexchange.com/questions/2202/… - Luka Rahne
See lysator.liu.se/~nisse/nettle/nettle.html#Randomness for a crypto library written by one of GMP's maintainers. - Marc Glisse

1 Answers

0
votes

Disclaimer: I have only "tinkered" with RNGs, and that was over a year ago.

If you are on a linux box, the solution is relatively simple and non-deterministic. Just open and read a desired number of bits from /dev/urandom. If you need a large number of random bits for your program however, then you might want to use a smaller number of bits from /dev/urandom as seeds for a PRNG.

boost offers a number of PRNGs and a non-deterministic RNG, random_device. random_device uses the very same /dev/urandom on linux and a similar(IIRC) function on windows, so if you need windows or x-platform.

Of course, you just might want/need to write a function based on your favored RNG using GMP's types and functions.


Edit:

#include<stdio.h>
#include<gmp.h>
#include<boost/random/random_device.hpp>

int main( int argc, char *argv[]){

    unsigned min_digits = 30;
    unsigned max_digits = 50;
    unsigned quantity = 1000;   // How many numbers do you want?
    unsigned sequence = 10;     // How many numbers before reseeding?

    mpz_t rmin;
    mpz_init(rmin);
    mpz_ui_pow_ui(rmin, 10, min_digits-1);

    mpz_t rmax;
    mpz_init(rmax);
    mpz_ui_pow_ui(rmax, 10, max_digits);

    gmp_randstate_t rstate;
    gmp_randinit_mt(rstate);

    mpz_t rnum;
    mpz_init(rnum);

    boost::random::random_device rdev;

    for( unsigned i = 0; i < quantity; i++){

        if(!(i % sequence)) 
            gmp_randseed_ui(rstate, rdev.operator ()());

        do{
            mpz_urandomm(rnum, rstate, rmax);
        }while(mpz_cmp(rnum, rmin) < 0);

        gmp_printf("%Zd\n", rnum);
    }

    return 0;
}