Hash della Password in C#? Bcrypt/PBKDF2

Ho guardato su msdn e altre risorse su come fare questo, ma io non arrivò soluzioni chiare. Questo è il migliore che ho trovato http://blogs.msdn.com/b/shawnfa/archive/2004/04/14/generating-a-key-from-a-password.aspx?Redirected=true

Vorrei hash delle password in C# utilizzando bcrypt o PBKDF2 (che sembra essere bcrypt correlati). Mi piace sperimentare con quanti giri prende per il mio computer per l’hash di una password. Tuttavia, tutto sembra essere sulla crittografia, mentre tutti parlano di hashing. Non riesco a capire. Come faccio a hash di una password? Sembra più simile a PBKDF2 (Rfc2898?) è un generatore di numero casuale e lo uso GetBytes(quantità) di scegliere quanto è grande il mio hash di dimensione.

Sono confuso. Esattamente come faccio hash di una password con bcrypt/PBKDF?

  • Che l’articolo parla di generazione di una chiave da una password da utilizzare per la crittografia qualcosa. Che è molto diverso argomento di hashing delle password.
  • esattamente e che è stato il meglio che ho potuto bene.
  • Se si vuole realmente hash delle password, si dovrebbe guardare a System.Security.Cryptography.SHA256Managed
  • vedere stackoverflow.com/questions/481160/… per alcune risorse. Se google hash passwords salt .net si otterrà un sacco di adeguati riscontri.
  • …in particolare Chris Marisic la risposta
  • Perché dovrebbe? Poi avrei bisogno di implementare un rallentamento e la salatura del regime stesso, invece di usare la build in PBKDF2 attuazione.
  • In pratica si utilizza gli stessi algoritmi per derivare una chiave da una password, e per memorizzare le password criptate. Cioè bcrypt, scrypt e PBKDF2.
  • Sì, ma nessuno di loro spiega COME farlo in C#. Dicono semplicemente, usare…. che sto CERCANDO di fare (correttamente)
  • C’è un semplice esempio nella mia risposta qui: stackoverflow.com/a/4330586/55847
  • Ho scritto anche un po ‘ su come gestire questo qui: davismj.mi/blog/bcrypt

InformationsquelleAutor | 2012-07-10



9 Replies
  1. 33

    PBKDF2

    Sei stato davvero vicino, in realtà. Il link che hai dato mostra come si può chiamare il Rfc2898DeriveBytes funzione per ottenere PBKDF2 hash risultati. Tuttavia, non è stato buttato fuori dal fatto che l’esempio è stato utilizzando la chiave derivata per la criptazione (la motivazione originale per PBKDF1 e 2 era di creare il “tasto” funzioni di derivazione adatto per l’utilizzo come chiavi di crittografia). Naturalmente, non vogliamo utilizzare l’uscita per la crittografia, ma come un hash sul proprio.

    Si può provare il SimpleCrypto.Net libreria scritta esattamente per questo scopo, se si desidera PBKDF2. Se si all’attuazione, si può vedere che è in realtà solo un sottile involucro intorno (avete indovinato) Rfc2898DeriveBytes.

    BCrypt

    Si può provare l’implementazione di C# nome (che altro) BCrypt.NET se volete sperimentare questa variante.

    Disclaimer: non ho usato o testato una qualsiasi delle biblioteche che ho legato… YMMV

    • Sembra che lo calculateHash è semplicemente .GetBytes(64). Quindi… non Sono io a scegliere il mio hash bitsize e utilizzare GetBytes?
    • Dal momento che io non sono in confidenza con i dettagli della PBKDF2 algoritmo, io non voglio speculare. Tuttavia, sembra che, come hai detto, si può solo scegliere un sicuro avere una lunghezza sufficiente per il tuo hash e ottenere che il numero di byte dal metodo.
    • Alcune persone sembrano essere ancora raccomandando SHA1 e SHA256 invece di PBKDF2. È PBKDF2 meglio?
    • Non sono proprio la stessa cosa, davvero. PBKDF2 è Basata su Password Chiave di Derivazione della Funzione che prende una password e la deriva di un tasto. Questa chiave è pensato per essere utilizzato in operazioni di crittografia. OTOH, SHA è per l’hashing byte di input. Mentre si potrebbe utilizzare PBKDF2 per uno scopo simile, non credo che sarebbe bene utilizzare la chiave generata come un hash.
    • FWIW, SimpleCrypto.NET sembra avere alcuni problemi di sicurezza a causa della sua attuazione. Sicuramente check out GitHub Problemi per questi tipi di progetti prima di integrarli nel proprio progetto.
    • Devo creare una semplice libreria per .NET che utilizza Microsoft attuazione di PBKDF2 (Rfc2898DerivedBytes), ma fornisce un’interfaccia estremamente semplice, in cima a che, simile a BCrypt.NET così è in genere necessario chiamare Compute(), salva il risultato al db e poi verificare chiamando Verificare. Si chiama SimpleHashing.Net: github.com/ilya-git/SimpleHashing.Net, c’è anche un pacchetto Nuget con lo stesso nome. Ancora una volta, non è un auto di attuazione, ma un piccolo wrapper su MS attuazione per un facile utilizzo.

  2. 9

    Mi ha preso per sempre (giorni ci sono voluti giorni) per trovare ciò che realmente codice per ottenere l’hash della password al lavoro!! così l’ho messo qui per comodità.

    Devi leggere il documentazione e theory1 theory2 e quindi alcuni o si potrebbe essere aperta a falle di sicurezza. La sicurezza è un argomento molto grande! Acquirente Attenzione!

    Aggiungere il Pacchetto NuGet BCrypt.Net per la soluzione

    const int WorkFactor = 14;
    var HashedPassword = BCrypt.Net.BCrypt.HashPassword(Password, WorkFactor); 

    Si dovrebbe regolare il WorkFactor di ciò che è appropriato vedere discussioni. La sua una log2 funzione

    “Il numero è log2, così ogni volta che i computer a doppia velocità, aggiungere 1 al numero predefinito.”

    Quindi è memorizzare l’hash della password nel db come passwordFromLocalDB e per verificare l’arrivo di un password come questo:

    if (BCrypt.Net.BCrypt.Verify(password, passwordFromLocalDB) == true)

    Buona Fortuna!

  3. 3

    All’inizio di quest’anno cercavo la stessa cosa per la creazione di hash per il nostro ASP.NET Web Form progetto, ho voluto farlo allo stesso modo progetti di MVC farlo fuori dalla scatola.

    Mi sono imbattuto in questa domanda => ASP.NET Identità Password di default Hasher, come funziona ed è sicuro?
    Poi ho trovato la fonte con il ByteArraysEqual metodo qui => http://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.Core/2.0.0-rtm-140327/Release/Default/Microsoft.AspNet.Identity.Core/Microsoft.AspNet.Identity.Core/Crypto.cs?ImageName=Microsoft.AspNet.Identity.Core

    • Per qualsiasi altra ritardatari, di cui sopra, legato di essere stato utile alla vaniglia codice invece di decostruire l’attuazione. (Non so se è utile o politica per modificare / re-post, in MODO che il codice o l’altro codice, quindi..) Il 3 funzioni: HashPassword e VerifyHashedPassword un link 1, e quindi ByteArraysEqual link alternativo 2.
    • Molto utile. Un link alternativo sarebbe il mono codice sorgente (che dovrebbero essere identici, e un link stabile): github.com/mono/aspnetwebstack/blob/master/src/…
  4. 2

    Prima di tutto, esorto tutti a utilizzare un crittograficamente verificato riferimento algoritmo incluso con la stessa piattaforma.

    Non utilizzare 3rd party pacchetti e non verificato componenti OSS o qualsiasi altro codice solo copia-incollato da Internet.

    Per .NET utilizzare PBKDF2 e non bCrypt perché non c’è il certificato di attuazione di bCrypt per .NET

    Non mi riferisco a nessuna mancanza di rispetto per qualsiasi nobile open-source per sviluppatori (essendo uno io), ma non si può mai essere sicuri che il loro sito non sarà violato nel corso di 10 anni, e si finisce per ottenere un malware pacchetto Nuget/npm o altri gestori di pacchetti.

    Ulteriori informazioni sulla verifica può essere trovato in questo MODO di rispondere

    Ora, di nuovo al PBKDF2, ecco il semplice codice

    public static byte[] PBKDF2Hash(string input, byte[] salt)
    {
        //Generate the hash
        Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(input, salt, iterations: 5000);
        return pbkdf2.GetBytes(20); //20 bytes length is 160 bits
    }

    Se avete bisogno di una rappresentazione di stringa di hash (non byte array) – è possibile utilizzare questo superfast classe di conversione da questa risposta http://stackoverflow.com/a/624379/714733

  5. 1

    Per PBKDF2, si potrebbe essere in grado di utilizzare il Sistema.Di sicurezza.Crittografia.Rfc2898DeriveBytes.

    Vedi MSDN qui: http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

    • Ho e non mostra come hash di una password. Essa mostra come crittografare.
    • Le mie scuse, hai ragione, questo è circa la crittografia per la maggior parte, ma spero che possa essere in grado di sfruttare la classe per arrivare a ciò che è necessario. Dio lavoro da paracycle per trovare l’involucro intorno ad esso!
  6. 1

    PBKDF2 utilizza HMACSHA1, se si desidera una più moderna e personalizzabile soluzione si dovrebbe guardare a questa API utilizzando HMACSHA256 o 512 con chiave di stretching come PBKDF2

    https://sourceforge.net/projects/pwdtknet/

    Esempio di GUI incluso nel codice sorgente dimostrato come ottenere un hash di una password compresa la creazione di crypto casuale sale…..enjoy 🙂

  7. 1

    Microsoft ha una pagina con codice di esempio utilizza PBKDF2 per chiunque di utilizzare .Net Core:

    Hash delle password in ASP.NET Core

    Dall’articolo:

    using System;
    using System.Security.Cryptography;
    using Microsoft.AspNetCore.Cryptography.KeyDerivation;
    
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Write("Enter a password: ");
            string password = Console.ReadLine();
    
            //generate a 128-bit salt using a secure PRNG
            byte[] salt = new byte[128 / 8];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(salt);
            }
            Console.WriteLine($"Salt: {Convert.ToBase64String(salt)}");
    
            //derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
            string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
                password: password,
                salt: salt,
                prf: KeyDerivationPrf.HMACSHA1,
                iterationCount: 10000,
                numBytesRequested: 256 / 8));
            Console.WriteLine($"Hashed: {hashed}");
        }
    }
    
    /*
     * SAMPLE OUTPUT
     *
     * Enter a password: Xtw9NMgx
     * Salt: NZsP6NnmfBuYeJrrAKNuVQ==
     * Hashed: /OOoOer10+tGwTRDTrQSoeCxVTFr6dtYly7d0cPxIak=
     */
  8. 0

    PBKDF2

    Nell’esempio in http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx, quando si arriva alla linea “Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1, salt1,
    myIterations);”, k1 è l’hash. La ragione che l’esempio è per la crittografia è che Rfc2898DeriveBytes è stato originariamente progettato per creare le chiavi di crittografia.

    Se non si sale, Rfc2898DeriveBytes creerà il proprio, ma non so se RNGCryptoServiceProvider fa un lavoro migliore di crittografia casuale.

    Secondo OWASP (https://www.owasp.org/index.php/Using_Rfc2898DeriveBytes_for_PBKDF2), il sottostante uso SHA1 da Rfc2898DeriveBytes significa che è solo un bene per l’hash di 160 bit di lunghezza. Se si crea un più hash, un utente malintenzionato ancora dovrà preoccuparsi solo i primi 160 bit, ma hai fatto l’hashing delle password/autenticazione più costoso per te senza scopo di lucro.

    Ecco un esempio di codice per Rfc2898DeriveBytes di hashing della password (archivio di hash, sale e iterazioni nel DB):

    public class Rfc2898PasswordEncoder
    {
        private int _byteLength = 160 / 8; //160 bit hash length
    
        public class EncodedPassword
        {
            public byte[] Hash { get; set; }
            public byte[] Salt { get; set; }
            public int Iterations { get; set; }
        }
    
        public EncodedPassword EncodePassword(string password, int iterations)
        {
            var populatedPassword = new EncodedPassword
            {
                Salt = CreateSalt(),
                Iterations = iterations
            };
    
            //Add Hash
            populatedPassword.Hash = CreateHash(password, populatedPassword.Salt, iterations);
    
            return populatedPassword;
        }
    
        public bool ValidatePassword(string password, EncodedPassword encodedPassword)
        {
            //Create Hash
            var testHash = CreateHash(password, encodedPassword.Salt, encodedPassword.Iterations);
    
            return testHash == encodedPassword.Hash;
        }
    
        public byte[] CreateSalt()
        {
            var salt = new byte[_byteLength]; //Salt should be same length as hash
    
            using (var saltGenerator = new RNGCryptoServiceProvider())
            {
                saltGenerator.GetBytes(salt);
            }
    
            return salt;
        }
    
        private byte[] CreateHash(string password, byte[] salt, long iterations)
        {
            byte[] hash;
            using (var hashGenerator = new Rfc2898DeriveBytes(password, salt, (int)iterations))
            {
                hash = hashGenerator.GetBytes(_byteLength);
            }
    
            return hash;
        }
    } 
  9. 0

    ero interessato ad una delle risposte che non ha coinvolto tutte le librerie.

    Ho letto questo articolo https://crackstation.net/hashing-security.htm che collega un’implementazione in diversi linguaggi C#, fra di loro, che io link anche qui

    https://github.com/defuse/password-hashing/blob/master/PasswordStorage.cs

    è interessante notare che si utilizza Rfc2898DeriveBytes come detto un paio di volte qui.

    private static byte[] PBKDF2(string password, byte[] salt, int iterations, int outputBytes){
        using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt)) {
            pbkdf2.IterationCount = iterations;
            return pbkdf2.GetBytes(outputBytes);
        }
    }

Lascia un commento