4

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).

Jay
  • 9,585
  • 6
  • 49
  • 72
  • 1
    Implementing new crypto and not knowing what generator to use brings bad karma. Very bad karma!! http://security.stackexchange.com/questions/2202/lessons-learned-and-misconceptions-regarding-encryption-and-cryptology – Luka Rahne Aug 22 '14 at 20:32
  • 1
    See http://www.lysator.liu.se/~nisse/nettle/nettle.html#Randomness for a crypto library written by one of GMP's maintainers. – Marc Glisse Aug 23 '14 at 07:48

1 Answers1

0

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;
}
dB8
  • 176
  • 5
  • Hm, I see. I can get bits from `/dev/urandom` (or `/dev/random`) and use `mpz_import` to turn them into a GMP number. I was wondering if this is really the usual way to deal with this (because it feels kind of awkward -- I have arbitrary precision math library, so I'd expect it to give me crypto-safe random numbers!) – Jay Mar 23 '12 at 22:01
  • 1
    Well, it is an arbitrary(multiple) precision library, not necessarily an RNG library. The devs work toward making using very large numbers as fast as possible, and they included a few RNGs for fun. I am going to take back my suggestion on using /dev/urandom and suggest using boost::random::random_device which is now in the standard library, though your compiler might not support it yet.Also, I will put some code in my original post that might make it seem much less awkward, though it uses Merseene Twister (for very short sequences). Otherwise, you will have to code Blum Blum Shub, or similar – dB8 Mar 25 '12 at 23:47
  • Thank you -- but I'll have to stick to plain C... Anyway -- is there any advantage in reseeding the RNG with a totally randm seed for _each new number_ and using `mpz_urandom` instead of using random bits and `mpz_import`? – Jay Mar 27 '12 at 18:16
  • 1
    I am not entirely qualified to speak to the finer points of the particular problem, but it pertains to the amount of random bits you can read from /dev/random or /dev/urandom before emptying the entropy pool. Reading the man page on /dev/random will give you better insight than I could. /random is blocking and will stop providing bits until more are generated (from network, keyboard, mouse, and disk activity) whereas /urandom will reuse bits. Safe bet when using either, in order to avoid each one's limitation, is to use smaller number of bits as seeds to a PRNG for limited sequences. – dB8 Mar 30 '12 at 22:34
  • @dB8 It is much much better to use /dev/urandom than /dev/random to feeds your own random generator, because /dev/urandom does just that, but using best and state of the art approach to generate data that can be used as crypto secure PRNG (CSPRNG). – Luka Rahne Aug 22 '14 at 20:44
  • `gmp_randinit_mt`is **not suitable for cryptography**. For an RNG to be secure, you need to both seed it properly and use a proper algorithm afterwards. Your answer shows how to seed properly, but it is ruined by then using a PRNG whose state can be reconstructed from outputs. Looking at the [GMP documentation](https://gmplib.org/manual/Random-State-Initialization.html#Random-State-Initialization), I don't see any RNG that's suitable for cryptography, so you need to use some other library (and then you might as well use its own bignum implementation). – Gilles 'SO- stop being evil' Sep 23 '17 at 12:53