In che modo node.bcrypt.js confronta le password con hash e quelle in chiaro senza il sale?


95

Da GitHub :

Per hash una password:

var bcrypt = require('bcrypt');
bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash("B4c0/\/", salt, function(err, hash) {
        // Store hash in your password DB.
    });
});

Per controllare una password:

// Load hash from your password DB.
bcrypt.compare("B4c0/\/", hash, function(err, res) {
    // res == true
});
bcrypt.compare("not_bacon", hash, function(err, res) {
    // res = false
});

Dall'alto, come possono non esserci valori di sale coinvolti nei confronti? Cosa mi manca qui?

Risposte:


95

Il sale è incorporato nell'hash (come testo in chiaro). La funzione di confronto estrae semplicemente il sale dall'hash e quindi lo utilizza per l'hash della password ed eseguire il confronto.


1
Continuo a non capire. Durante il confronto, come fa a sapere quale parte dell'hashish è il sale se non gli dai il sale?
MondayPaper

6
bcrypt è uno standard e concatena sempre il sale con l'hash nello stesso formato. Fornisci il sale durante la crittografia e questo viene incorporato nell'hash. bcrypt sarà solo in grado di decrittografare i dati originariamente crittografati utilizzando bcrypt, altrimenti hai ragione: non ci sarebbe modo per sapere quale parte è l'hash e quale parte è il sale.
Bill

4
Ok, abbiamo capito: il sale viene conservato con l'hash. bcrypt è open source, quindi questo significa che tutti sanno esattamente come lo memorizza. Quindi sai come estrarlo o come generare hash da password in testo normale. In che modo questo aiuta a proteggere le password dalla scansione delle tabelle arcobaleno per gli hash, che è fondamentalmente l'idea principale alla base del sale?
Vitaliy Lebedev

13
Non importa se l'aggressore conosce il sale per un particolare hash, non è un segreto. L'uso di un salt diverso per ogni password significa che l'aggressore non può precalcolare gli hash utilizzando valori comuni. Con un sale diverso su ognuno, avrebbero bisogno di ricalcolare le tabelle per ogni password, il che le rende inutili.
Fattura

3
un'occhiata a questo modo, cosa importa se il sale attaccante sa con certezza utente nella banca dati in questo modo: column_password = hash, column_salt = saltvs column_password = hash_salt. l'attaccante ha ancora le stesse informazioni. Il punto di sale è rendere ogni password così casuale e più grande da rendere improbabile che qualcuno l'abbia precalcolata.
Muhammad Umer

27

Anch'io avevo la stessa domanda del poster originale e ci è voluto un po 'guardandomi intorno e provando cose diverse per capire il meccanismo. Come è già stato sottolineato da altri, il sale viene concatenato all'hash finale. Quindi questo significa un paio di cose:

  1. L'algoritmo deve conoscere la lunghezza del sale
  2. Deve anche conoscere la posizione del sale nella stringa finale. es. se spostato da un numero specifico da sinistra o destra.

Queste due cose sono solitamente codificate in modo rigido nell'implementazione, ad esempio la fonte di implementazione di bcrypt per bcryptjs definisce la lunghezza del sale come 16

/**
* @type {number}
* @const
* @private
*/

var BCRYPT_SALT_LEN = 16;

Quindi, per illustrare il concetto di base dietro l'idea, se si volesse farlo manualmente, sarebbe simile al seguente. Non consiglio di implementare cose come questa da soli quando ci sono librerie che puoi ottenere per farlo.

var salt_length = 16;
var salt_offset = 0;

var genSalt = function(callback)
{
    var alphaNum = '0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ';
    var salt = '';
    for (var i = 0; i < salt_length; i++) {
        var j = Math.floor(Math.random() * alphaNum.length);
        salt += alphaNum[j];
    }
    callback(salt);
}

// cryptographic hash function of your choice e.g. shar2
// preferably included from an External Library (dont reinvent the wheel)
var shar2 = function(str) {
    // shar2 logic here 
    // return hashed string;
}

var hash = function(passwordText, callback)
{
    var passwordHash = null;
    genSalt(function(salt){
        passwordHash = salt + shar2(passwordText + salt);
    });

    callback(null, passwordHash);
}

var compare = function(passwordText, passwordHash, callback)
{
    var salt = passwordHash.substr(salt_offset, salt_length);
    validatedHash = salt + shar2(passwordText + salt);

    callback(passwordHash === validatedHash);   
}

// sample usage
var encryptPassword = function(user)
{
    // user is an object with fields like username, pass, email
    hash(user.pass, function(err, passwordHash){
        // use the hashed password here
        user.pass = passwordHash;
    });

    return user;
}

var checkPassword = function(passwordText, user)
{
    // user has been returned from database with a hashed password
    compare(passwordText, user.pass, function(result){
        // result will be true if the two are equal
        if (result){
            // succeeded
            console.log('Correct Password');
        }
        else {
            // failed
            console.log('Incorrect Password');
        }
    });
}

0

Poiché anch'io ho fatto la stessa domanda, so esattamente a cosa stai pensando.

Hai un'idea sbagliata tra "Secret Key" che viene utilizzato negli algoritmi crittografici e "Salt" che viene utilizzato per rallentare il processo di crittografia e rendere più difficile per gli hacker usare la forza bruta.

Quando usi la semplice password e il salt per generare l'hash, questo hash usa come chiave segreta la password stessa ! Quindi la prossima volta che proverai a confrontarla con una semplice password, questa semplice password deve essere esattamente la stessa che hai usato per generare l'hash! Quindi questo è il motivo per cui non devi salvarlo da qualche altra parte perché è sempre fornito dall'utente sia nei passaggi di registrazione che di accesso!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.