Semina in modo sicuro un generatore di numeri casuali C #

4

Sto cercando di capire il modo migliore per seminare in modo sicuro un rng in C #.

La classe che sto attualmente utilizzando è la classe Random

link

Dopo aver esaminato la documentazione, è possibile inizializzarla usando Int32 , tuttavia, e potrei sbagliarmi nel modo in cui presumo ciò, un Int32 avrebbe essenzialmente solo 32 bit di entropia, che è molto meno del 128 raccomandato o 256 bit di entropia.

Qualcuno sa di un C # RNG migliore o di come proprietà e lo semina in modo sicuro con 128 bit su entropia? Non sono stato in grado di trovare nulla

Grazie per tutto l'aiuto.

Modifica

Sto provando a generare in modo sicuro numeri casuali che possono essere ripetibili su macchine diverse. Fondamentalmente sto cercando di trovare un CSRNG che può essere seminato con un valore hash o qualcosa di simile e se avessi eseguito quel pezzo di software su una macchina diversa con quell'hash come seme, avrebbe prodotto gli stessi numeri.

    
posta CBaker 18.07.2016 - 18:52
fonte

2 risposte

0

In larga misura, questo dipende dalla quantità di output casuale di cui hai bisogno. Sto assumendo parecchio, dal momento che stai parlando di avere già 128 o 256 byte di dati casuali per seminarlo, e sei corretto che System.Random non sia abbastanza buono per questo.

Sono riluttante a raccomandare le opzioni, perché l'intero schema di progettazione è irto di pericoli. Piccoli errori potrebbero lasciarti con un sistema irrimediabilmente rotto, indipendentemente da quanto sia buono il CSPRNG e quanto sia strong e lungo il tuo seme. Questo è probabilmente uno dei motivi per cui non è possibile effettuare il seeding di RNGCryptoServiceProvider ... Per impedire alle persone di infrangerlo con applicazioni terribili.

Detto questo, se si dispone di un sistema che lo richiede e si è certi che sia stato progettato e implementato in modo sicuro, un approccio da adottare potrebbe consistere nella creazione di un CSPRNG basato su AES. L'output di AES è casuale e imprevedibile, quindi entro limiti ragionevoli, è possibile utilizzarlo in modo sicuro per generare numeri casuali, in cui la chiave (di 128, 192 o 256 bit) viene effettivamente utilizzata come valore di inizializzazione, si cripta un contatore e il testo cifrato è il tuo flusso casuale.

Questa è una costruzione abbastanza comune, quindi ci sono un po 'di informazioni su come costruire qualcosa di simile, e naturalmente C # supporta AES in modo da avere le primitive di cui hai bisogno. Anche se l'implementazione è corretta, devi stare molto attento a come lo si progetta per essere utilizzato, perché non è casuale se c'è uno scenario che consente a un utente malintenzionato di prevederlo, e ogni volta che si ha un controllo, valore seme riutilizzabile che è uno scenario da proteggere contro.

    
risposta data 19.07.2016 - 16:10
fonte
0

Per generare un numero casuale sicuro in .Net dovresti usare system.security.cryptography.rngcryptoserviceprovider invece di system.random

La documentazione per questo è qui:

link

In caso di link put, ecco il campione C # fornito da Microsoft su quel link. La generazione casuale viene eseguita utilizzando il metodo 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;
    }
}
    
risposta data 18.07.2016 - 19:00
fonte

Leggi altre domande sui tag