La lunghezza di un "sale" è un fattore di sicurezza?

1

Sto cercando di sviluppare una piccola soluzione con la possibilità di autenticazione dell'utente. Poiché questo sarà in seguito consegnato ad altri sviluppatori, voglio che la prima iterazione della soluzione sia la più sicura possibile per i dati degli utenti.

Dopo aver letto alcune cose sulla sicurezza e l'hashing, ho deciso di memorizzare hash + salt in un singolo campo nel database. Il più delle volte salt negli esempi è lungo 16 byte. Ma tecnici avrebbero potuto avere qualsiasi dimensione.

Questo porta alla mia domanda:

  • Se non è pubblico per quanto tempo il mio sale e il mio hash sono e li ho impostati su un valore "casuale", si tratta di un ulteriore passo per proteggere i dati degli utenti?

Se in qualche modo il database finisce in mani sbagliate, l'attaccante non saprebbe a che punto finisce il sale e inizia l'hash.

Dato un esempio in .net Core 2.0 che mi permette di impostare la lunghezza di sale e hash:

static Dictionary<string,string> _memDict = new Dictionary<string,string>() {{"username","password"}};

static int _amountOfHashBytes = 32;
static int _amountOfSaltBytes = 16;
static int _amountOfIterations = 10000;

static void Main(string[] args) 
{
    string passphrase = "passphrase"; 
    string usrName = "dotnetcoreuser";

    // 1) Create the salt value with a cryptographic 
    byte[] salt; 
    RandomNumberGenerator.Create().GetBytes(salt = new byte[_amountOfSaltBytes]); 
    Console.WriteLine("Salt: " + Convert.ToBase64String(salt)); 

    // 2) Create the Rfc2898DeriveBytes and get the hash value
    var pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, _amountOfIterations); 
    byte[] hash = pbkdf2.GetBytes(_amountOfHashBytes); 
    Console.WriteLine("Hash: " + Convert.ToBase64String(hash)); 

    // 3) Combine the salt and password bytes for later use
    byte[] hashBytes = new byte[_amountOfSaltBytes + _amountOfHashBytes]; 
    Array.Copy(salt, 0, hashBytes, 0, _amountOfSaltBytes); 
    Array.Copy(hash, 0, hashBytes, _amountOfSaltBytes, _amountOfHashBytes); 

    // 4) Turn the combined salt + hash into a string for storage
    string savedPasswordHash = Convert.ToBase64String(hashBytes); 
    Console.WriteLine("Combine: " + savedPasswordHash); 
    _memDict.Add(usrName, savedPasswordHash);

    // 5) Verify the user-entered password against a stored password.
    string tryInput = "1234";
    Console.WriteLine("Try: {0} Result: {1}", tryInput, IsValidPassword(tryInput, usrName));
    tryInput = "password";
    Console.WriteLine("Try: {0} Result: {1}", tryInput, IsValidPassword(tryInput, usrName));
    tryInput = "passphrase";
    Console.WriteLine("Try: {0} Result: {1}", tryInput, IsValidPassword(tryInput, usrName));
}

static bool IsValidPassword(string userInput, string userName)
{
    string savedPasswordHash = _memDict[userName];
    byte[] hashBytes = Convert.FromBase64String(savedPasswordHash);
    byte[] salt = new byte[_amountOfSaltBytes];
    Array.Copy(hashBytes, 0, salt, 0, _amountOfSaltBytes);
    var pbkdf2 = new Rfc2898DeriveBytes(userInput, salt, _amountOfIterations);
    byte[] hash = pbkdf2.GetBytes(_amountOfHashBytes);
    for (int i=0; i < _amountOfHashBytes; i++)
    {
        if (hashBytes[i+_amountOfSaltBytes] != hash[i]) { return false; }
    }
    return true;
}
    
posta Smartis 10.10.2017 - 12:47
fonte

2 risposte

8

If it isn't public how long my salt and my hash are and i set them to a 'random' value, is this an extra step for protecting user data?

If somehow the database gets in wrong hands, the attacker wouldn't know at which point the salt ends and the hash starts.

No. È un tentativo completamente inutile di sicurezza attraverso l'oscurità.

L'unica cosa importante è che il tuo sale (e ovviamente l'hash) sono abbastanza lunghi, 16 byte sono sufficienti, 8 sarebbe troppo piccolo.

    
risposta data 10.10.2017 - 12:57
fonte
1

Il valore dell'utilizzo di sale è che con il sale, non ci sono due utenti che hanno la stessa password. Lo stesso sforzo che un utente malintenzionato userebbe per attaccare il database completo senza password è ora necessario per attaccare una singola password.

Dovresti dare per scontato che un attaccante possa scoprire che sale stai usando. Va bene. Fintanto che nessun utente o pochissimi utenti ha lo stesso sale.

La raccomandazione di 8 byte significa che con un miliardo di database di utilizzo c'è solo una possibilità su 39 che ci siano due utenti con lo stesso sale. E anche allora è innocuo.

    
risposta data 10.10.2017 - 21:50
fonte

Leggi altre domande sui tag