Sembrando un generador de números aleatorios de C # de forma segura

4

Estoy tratando de descubrir la mejor manera de sembrar de forma segura un rng en C #.

La clase que estoy usando actualmente es la clase Random

enlace

Después de revisar la documentación, puede agregarlo utilizando Int32 , sin embargo, y puedo estar equivocado al suponer esto, un Int32 tendría esencialmente solo 32 bits de entropía, que es mucho menor que el recomendado. o 256 bits de entropía.

¿Alguien sabe de un mejor C # RNG o cómo establecer una propiedad y sembrarlo de forma segura con 128 bits en la entropía? No he podido encontrar nada

Gracias por toda la ayuda.

EDIT

Estoy tratando de generar de forma segura números aleatorios que puedan repetirse en diferentes máquinas. Básicamente, estoy tratando de encontrar un CSRNG que se pueda sembrar con un valor de hash o algo similar y si ejecuto esa pieza de software en una máquina diferente con ese hash como semilla, produciría los mismos números.

    
pregunta CBaker 18.07.2016 - 18:52
fuente

2 respuestas

0

En gran medida, esto depende de la cantidad de salida aleatoria que necesite. Supongo que bastante, ya que estamos hablando de que ya tienen 128 o 256 bytes de datos aleatorios para sembrar, y tiene razón en que System.Random no es lo suficientemente bueno para esto.

Dudo en recomendar opciones, porque todo este patrón de diseño está lleno de peligros. Pequeños errores podrían dejarte con un sistema irremediablemente roto, independientemente de lo bueno que sea el CSPRNG y de lo fuerte y largo que sea tu semilla. Esta es probablemente una de las razones por las que no puede generar el RNGCryptoServiceProvider ... Para evitar que las personas lo rompan con aplicaciones terribles.

Dicho esto, si tiene un sistema que lo requiere y está seguro de que está diseñado e implementado de manera segura, un enfoque que podría tomar sería construir un CSPRNG basado en AES. La salida de AES es aleatoria e impredecible, por lo que, dentro de restricciones razonables, puede usar de manera segura para generar números aleatorios, donde la clave (de 128, 192 o 256 bits) se usa efectivamente como su valor inicial, encripta un contador y El texto cifrado es su flujo aleatorio.

Esta es una construcción bastante común, por lo que hay bastante información sobre cómo construir algo como esto y, por supuesto, C # es compatible con AES para que tenga las primitivas que necesita. Sin embargo, incluso si logra que la implementación sea correcta, debe tener mucho cuidado con la forma en que diseña su uso, ya que no es aleatorio si existe un escenario que le permita a un atacante predecirlo, y en cualquier momento que tenga un controlador controlable. valor semilla reutilizable que es un escenario contra el que debe protegerse.

    
respondido por el Xander 19.07.2016 - 16:10
fuente
0

Para generar un número aleatorio seguro en .Net, debes usar system.security.cryptography.rngcryptoserviceprovider en lugar de system.random

La documentación para ello está aquí:

enlace

En caso de rotura de enlaces, aquí está la muestra de C # que Microsoft proporciona en ese enlace. La generación aleatoria se realiza mediante el método GetBytes .

//The following sample uses the Cryptography class to simulate the roll of a dice.

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

class RNGCSP
{
    private static RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
    // Main method.
    public static void Main()
    {
        const int totalRolls = 25000;
        int[] results = new int[6];

        // Roll the dice 25000 times and display
        // the results to the console.
        for (int x = 0; x < totalRolls; x++)
        {
            byte roll = RollDice((byte)results.Length);
            results[roll - 1]++;
        }
        for (int i = 0; i < results.Length; ++i)
        {
            Console.WriteLine("{0}: {1} ({2:p1})", i + 1, results[i], (double)results[i] / (double)totalRolls);
        }
        rngCsp.Dispose();
        Console.ReadLine();
    }

    // This method simulates a roll of the dice. The input parameter is the
    // number of sides of the dice.

    public static byte RollDice(byte numberSides)
    {
        if (numberSides <= 0)
            throw new ArgumentOutOfRangeException("numberSides");

        // Create a byte array to hold the random value.
        byte[] randomNumber = new byte[1];
        do
        {
            // Fill the array with a random value.
            rngCsp.GetBytes(randomNumber);
        }
        while (!IsFairRoll(randomNumber[0], numberSides));
        // Return the random number mod the number
        // of sides.  The possible values are zero-
        // based, so we add one.
        return (byte)((randomNumber[0] % numberSides) + 1);
    }

    private static bool IsFairRoll(byte roll, byte numSides)
    {
        // There are MaxValue / numSides full sets of numbers that can come up
        // in a single byte.  For instance, if we have a 6 sided die, there are
        // 42 full sets of 1-6 that come up.  The 43rd set is incomplete.
        int fullSetsOfValues = Byte.MaxValue / numSides;

        // If the roll is within this range of fair values, then we let it continue.
        // In the 6 sided die case, a roll between 0 and 251 is allowed.  (We use
        // < rather than <= since the = portion allows through an extra 0 value).
        // 252 through 255 would provide an extra 0, 1, 2, 3 so they are not fair
        // to use.
        return roll < numSides * fullSetsOfValues;
    }
}
    
respondido por el Mike Goodwin 18.07.2016 - 19:00
fuente

Lea otras preguntas en las etiquetas