node.bcrypt.jsは、ソルトなしでハッシュされたパスワードとプレーンテキストのパスワードをどのように比較しますか?


95

githubから:

パスワードをハッシュするには:

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

パスワードを確認するには:

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

上から、どのように比較に含まれるソルト値がないのでしょうか?ここで何が欠けていますか?

回答:


95

ソルトはハッシュに組み込まれます(プレーンテキストとして)。比較機能は単純にハッシュからソルトを引き出し、それを使用してパスワードをハッシュし、比較を実行します。


1
まだわかりません。比較時に、ソルトを提供しない場合、ハッシュのどの部分がソルトであるかをどのようにして知るのですか?
月曜日の紙2014年

6
bcryptは標準で、常にソルトとハッシュを同じ形式で連結します。暗号化するときにソルトを提供すると、これがハッシュに組み込まれます。bcryptは、bcryptを使用して最初に暗号化されたデータのみを復号化できます。それ以外の場合、そのとおりです。どの部分がハッシュで、どの部分がソルトであるかを知る方法はありません。
ビル

4
わかりました。saltはハッシュとともに保存されます。bcryptはオープンソースであるため、誰もがbcryptを正確に格納する方法を知っています。だから、それを抽出する方法、またはプレーンテキストのパスワードからハッシュを生成する方法を知っています。これは、レインボーテーブルのハッシュをスキャンすることからパスワードを保護するのにどのように役立ちますか?
Vitaliy Lebedev

13
攻撃者が特定のハッシュのソルトを知っているかどうかは関係ありません。秘密ではありません。パスワードごとに異なるソルトを使用することは、攻撃者が一般的な値を使用してハッシュを事前計算できないことを意味します。それぞれに異なるソルトがあると、パスワードごとにテーブルを再計算する必要があり、役に立たなくなります。
ビル

3
このように見て、攻撃者がデータベース内の特定のユーザーのソルトを次のように知っているかどうかは重要ですか?column_password = hash, column_salt = saltvs column_password = hash_salt。攻撃者はまだ同じ情報を持っています。要点は、すべてのパスワードを非常にランダムで大きくして、誰かが事前に計算した可能性が低くなるようにすることです。
Muhammad Umer 2017年

27

私も元のポスターと同じ質問をしましたが、メカニズムを理解するために周りを見回してさまざまなことを試みたように見えました。他の人がすでに指摘しているように、ソルトは最終ハッシュに連結されます。つまり、これはいくつかのことを意味します。

  1. アルゴリズムはソルトの長さを知っている必要があります
  2. 最後の文字列におけるソルトの位置も知っている必要があります。たとえば、左または右から特定の数だけオフセットする場合。

これら2つは通常、実装でハードコードされています。たとえば、bcryptjsの bcrypt実装ソースはソルトの長さを16と定義しています。

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

var BCRYPT_SALT_LEN = 16;

したがって、手動で実行したい場合のアイデアの背後にある基本的な概念を説明するには、以下のようになります。実現できるライブラリがある場合は、このようなものを自分で実装することはお勧めしません。

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

私も同じ質問をしたので、あなたが何を考えているのか正確にわかっています。

暗号化アルゴリズムで使用される「秘密鍵」と、暗号化プロセスを遅くし、ハッカーがブルートフォースを使用するのを困難にするために使用される「ソルト」との間で誤解があります。

あなたが使用している場合、プレーンパスワードハッシュを生成し、塩を、このハッシュは秘密鍵としてパスワードそのものを使用しています!したがって、次回、プレーンなパスワードと比較する場合、このプレーンなパスワードは、ハッシュの生成に使用したものとまったく同じである必要があります。したがって、ユーザーが登録とログインの両方のステップで常に提供するため、他の場所に保存する必要がないのはこのためです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.