Comment node.bcrypt.js compare-t-il les mots de passe hachés et en clair sans le sel?

95

Depuis github :

Pour hacher un mot de passe:

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

Pour vérifier un mot de passe:

// 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
});

D'en haut, comment peut-il y avoir aucune valeur de sel impliquée dans les comparaisons? Qu'est-ce que j'oublie ici?

SChang
la source

Réponses:

95

Le sel est incorporé dans le hachage (en clair). La fonction de comparaison extrait simplement le sel du hachage, puis l'utilise pour hacher le mot de passe et effectuer la comparaison.

Facture
la source
1
Je ne comprends toujours pas. Pendant la comparaison, comment sait-il quelle partie du hasch est le sel si vous ne lui fournissez pas le sel?
Lundi
6
bcrypt est un standard et concatène toujours le sel avec le hachage dans le même format. Vous fournissez le sel lorsque vous cryptez et cela est incorporé dans le hachage. bcrypt ne pourra déchiffrer que les données initialement cryptées à l'aide de bcrypt, sinon, vous avez raison - il n'y aurait aucun moyen de savoir quelle partie est le hachage et quelle partie est le sel.
Projet de loi
4
Ok, on comprend: le sel est stocké avec le hash. bcrypt est open source, cela signifie que tout le monde sait exactement comment il le stocke. Vous savez donc comment l'extraire ou comment générer un hachage à partir d'un mot de passe en texte brut. Comment cela aide-t-il à protéger les mots de passe contre l'analyse des tables arc-en-ciel pour les hachages, qui est essentiellement l'idée principale derrière le sel?
Vitaliy Lebedev
13
Peu importe que l'attaquant connaisse le sel d'un hachage particulier, ce n'est pas un secret. L'utilisation d'un sel différent pour chaque mot de passe signifie que l'attaquant ne peut pas précalculer les hachages en utilisant des valeurs communes. Avec un sel différent sur chacun d'eux, ils auraient besoin de recalculer toutes les tables pour chaque mot de passe, ce qui les rend inutiles.
Bill
3
regarder cette façon, peu importe - t - il si l' attaquant connaît le sel pour certains utilisateurs dans la base de données comme ceci: column_password = hash, column_salt = saltvs column_password = hash_salt. l'attaquant a toujours les mêmes informations. Le point essentiel est de rendre chaque mot de passe si aléatoire et plus grand qu'il devient peu probable que quelqu'un l'ait précalculé.
Muhammad Umer
27

J'avais aussi la même question que l'affiche originale et il a fallu regarder un peu autour et essayer différentes choses pour comprendre le mécanisme. Comme d'autres l'ont déjà souligné, le sel est concaténé au hachage final. Cela signifie donc plusieurs choses:

  1. L'algorithme doit connaître la longueur du sel
  2. Doit également connaître la position du sel dans la chaîne finale. par exemple, si compensé par un nombre spécifique de gauche ou de droite.

Ces deux choses sont généralement codées en dur dans l'implémentation, par exemple la source d'implémentation bcrypt pour bcryptjs définit la longueur du sel comme 16

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

var BCRYPT_SALT_LEN = 16;

Donc, pour illustrer le concept de base derrière l'idée si l'on voulait le faire manuellement, cela ressemblerait à celui ci-dessous. Je ne recommande pas d'implémenter ce genre de choses vous-même quand il y a des bibliothèques que vous pouvez obtenir pour le faire.

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');
        }
    });
}
Alappin
la source
0

Parce que j'avais moi-même la même question, je sais exactement à quoi vous pensez.

Vous avez une idée fausse entre "Secret Key" qui est utilisé dans les algorithmes cryptographiques et "Salt" qui est utilisé pour ralentir le processus de cryptage et rendre plus difficile pour les pirates d'utiliser la force brute.

Lorsque vous utilisez le mot de passe simple et le sel pour générer le hachage, ce hachage utilise comme clé secrète le mot de passe lui-même ! Donc, la prochaine fois que vous essaierez de le comparer avec un mot de passe simple, ce mot de passe simple doit être exactement le même que celui que vous avez utilisé pour générer le hachage! C'est pourquoi vous n'avez pas à le stocker ailleurs car il est toujours fourni par l'utilisateur lors des étapes d'enregistrement et de connexion!

babaliaris
la source