Использование GMP для криптографии: как получить случайные числа?

Кажется, что в документации по GMP перечислены только следующие алгоритмы. для генерации случайных чисел:

  • gmp_randinit_mt, Мерсенн Твистер;
  • gmp_randinit_lc_2exp и gmp_randinit_lc_2exp_size, линейные конгруэнтные.

Также есть gmp_randinit_default, но он указывает на gmp_randinit_mt.

Ни Mersenne Twister, ни линейные конгруэнтные генераторы не должны использоваться для криптографии. Что же тогда обычно делают люди, когда хотят использовать GMP для создания некоторого криптографического кода?

(Использование криптографического API для шифрования / дешифрования и т.д. не помогает, потому что я бы фактически реализовал новый алгоритм, которого нет в криптографических библиотеках).


person Jay    schedule 20.03.2012    source источник
comment
Внедрение новой криптовалюты и незнание, какой генератор использовать, приносит плохую карму. Очень плохая карма !! безопасности. stackexchange.com/questions/2202/   -  person Luka Rahne    schedule 23.08.2014
comment
См. lysator.liu.se/~nisse/nettle/nettle.html # Случайность для криптографической библиотеки, написанной одним из специалистов по сопровождению GMP.   -  person Marc Glisse    schedule 23.08.2014


Ответы (1)


Отказ от ответственности: я только «возился» с ГСЧ, и это было больше года назад.

Если вы используете Linux, решение относительно простое и недетерминированное. Просто откройте и прочтите желаемое количество бит из /dev/urandom. Однако, если вам нужно большое количество случайных битов для вашей программы, вы можете использовать меньшее количество битов из /dev/urandom в качестве начальных значений для ГПСЧ.

boost предлагает количество ГПСЧ и недетерминированный ГСЧ random_device. random_device использует ту же самую /dev/urandom в Linux и аналогичную (IIRC) функцию в Windows, поэтому, если вам нужны окна или x-платформа.

Конечно, вам просто может потребоваться написать функцию на основе вашего любимого ГСЧ с использованием типов и функций GMP.


Редактировать:

#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;
}
person dB8    schedule 23.03.2012
comment
Хм, понятно. Я могу получить биты из /dev/urandom (или /dev/random) и использовать mpz_import, чтобы преобразовать их в число GMP. Мне было интересно, действительно ли это обычный способ справиться с этим (потому что это кажется немного неудобным - у меня есть математическая библиотека произвольной точности, поэтому я ожидал, что она выдаст мне крипто-безопасные случайные числа!) - person Jay; 24.03.2012
comment
Ну, это библиотека произвольной (множественной) точности, не обязательно библиотека ГСЧ. Разработчики работают над тем, чтобы максимально быстро использовать очень большие числа, и для развлечения они добавили несколько генераторов случайных чисел. Я собираюсь отозвать свое предложение об использовании / dev / urandom и предложить использовать boost :: random :: random_device, который сейчас находится в стандартной библиотеке, хотя ваш компилятор может еще не поддерживать его. Кроме того, я помещу некоторый код в свой оригинальный пост, который может сделать его менее неловким, хотя в нем используется Merseene Twister (для очень коротких эпизодов). В противном случае вам придется кодировать Blum Blum Shub или аналогичный - person dB8; 26.03.2012
comment
Спасибо - но мне придется придерживаться простого C ... В любом случае - есть ли какое-то преимущество в повторном заполнении RNG с полностью рандомным семенем для каждого нового числа и использованием mpz_urandom вместо использования случайные биты и mpz_import? - person Jay; 27.03.2012
comment
Я не совсем квалифицирован, чтобы говорить о тонкостях конкретной проблемы, но это относится к количеству случайных битов, которые вы можете прочитать из / dev / random или / dev / urandom перед опустошением пула энтропии. Чтение справочной страницы на / dev / random даст вам лучшее понимание, чем я. / random блокирует и перестанет предоставлять биты до тех пор, пока не будет сгенерировано больше (из-за активности сети, клавиатуры, мыши и диска), тогда как / urandom будет повторно использовать биты. Безопасная ставка при использовании любого из них, чтобы избежать ограничений каждого из них, заключается в использовании меньшего числа битов в качестве начальных значений для ГПСЧ для ограниченных последовательностей. - person dB8; 31.03.2012
comment
@ dB8 Намного лучше использовать / dev / urandom, чем / dev / random для подачи вашего собственного случайного генератора, потому что / dev / urandom делает именно это, но с использованием лучшего и современного подхода для генерации данных, которые можно использовать как криптозащищенный ГПСЧ (CSPRNG). - person Luka Rahne; 23.08.2014
comment
gmp_randinit_mt не подходит для криптографии. Чтобы ГСЧ был безопасным, вам необходимо как правильно его заполнить, так и впоследствии использовать соответствующий алгоритм. Ваш ответ показывает, как правильно засеять, но он разрушается из-за использования ГПСЧ, состояние которого может быть восстановлено из выходных данных. Глядя на документацию GMP, я не увидеть любой ГСЧ, подходящий для криптографии, поэтому вам нужно использовать какую-то другую библиотеку (и тогда вы также можете использовать его собственную реализацию bignum). - person Gilles 'SO- stop being evil'; 23.09.2017