Maison >développement back-end >C++ >Comment amorcer de manière robuste le PRNG mt19937 pour une meilleure génération de nombres aléatoires ?

Comment amorcer de manière robuste le PRNG mt19937 pour une meilleure génération de nombres aléatoires ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-02 12:05:18570parcourir

How to Robustly Seed the mt19937 PRNG for Better Random Number Generation?

Comment amorcer le PRNG mt19937 de manière robuste

Bien que cela soit généralement suggéré, l'utilisation de std::random_device pour amorcer un PRNG mt19937 présente de nombreuses lacunes, notamment entropie insuffisante et non-uniformité potentielle. Cet article présente une solution qui résout ces problèmes :

Amorçage portable et approfondi

L'approche suivante utilise une source spécifique à la plate-forme d'octets aléatoires de force cryptographique (sysrandom) pour amorcer le PRNG :

std::uint_least32_t seed;
sysrandom(&seed, sizeof(seed));
std::mt19937 gen(seed);

sysrandom est une fonction wrapper qui récupère des octets aléatoires à partir d'une source appropriée, en fonction sur la plateforme :

Windows :

  • CryptGenRandom (fournisseur : PROV_RSA_FULL)

Unix-Like :

  • /dev/urandom (repli : std::random_device si indisponible)

Autre :

  • std::random_device (il est recommandé d'éviter si possible)

En s'appuyant sur des sources de qualité cryptographique, cette solution garantit une entropie suffisante et une seeding.

Comparaison avec Boost

Le random_device de Boost utilise des techniques similaires (par exemple, MS_DEF_PROV sur Windows, /dev/urandom sur *Nix), rendant l'approche présentée comparable dans portabilité et qualité.

Linux Spécialisation

Pour plus de sécurité sous Linux 3.17, getrandom (qui bloque si CSPRNG n'est pas initialisé) peut être utilisé à la place de /dev/urandom :

#if defined(__linux__)...
size_t sysrandom(void* dst, size_t dstlen)
{
    int bytes = syscall(SYS_getrandom, dst, dstlen, 0);
    if (bytes != dstlen) { throw std::runtime_error(...); }
    return dstlen;
}
#elif defined(_WIN32)...
#else...
#endif

OpenBSD Attention

OpenBSD moderne ne dispose pas de /dev/urandom. Utilisez plutôt getentropy :

#if defined(__OpenBSD__)...
size_t sysrandom(void* dst, size_t dstlen)
{
    int bytes = getentropy(dst, dstlen);
    if (bytes != dstlen) { throw std::runtime_error(...); }
    return dstlen;
}
#endif

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn