Làm cách nào để node.bcrypt.js so sánh mật khẩu băm và mật khẩu văn bản rõ mà không có muối?


95

Từ github :

Để băm mật khẩu:

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

Để kiểm tra mật khẩu:

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

Từ trên, làm thế nào để không có giá trị muối nào trong các phép so sánh? Tôi còn thiếu gì ở đây?

Câu trả lời:


95

Muối được đưa vào hàm băm (dưới dạng bản rõ). Hàm so sánh chỉ đơn giản là kéo muối ra khỏi hàm băm và sau đó sử dụng nó để băm mật khẩu và thực hiện so sánh.


1
Tôi vẫn không hiểu. Trong khi so sánh, làm thế nào nó biết phần nào của băm là muối nếu bạn không cung cấp muối?
Thứ Hai, tờ báo

6
bcrypt là một tiêu chuẩn và luôn nối muối với hàm băm ở cùng một định dạng. Bạn cung cấp muối khi mã hóa và điều này được kết hợp vào hàm băm. bcrypt sẽ chỉ có thể giải mã dữ liệu được mã hóa ban đầu bằng bcrypt, nếu không, bạn nói đúng - sẽ không có cách nào để nó biết phần nào là băm và phần nào là muối.
Hóa đơn

4
Được rồi, chúng tôi hiểu rồi: muối được lưu trữ với hàm băm. bcrypt là mã nguồn mở, vì vậy điều này có nghĩa là mọi người đều biết cách nó lưu trữ chính xác. Vì vậy, bạn đã biết cách giải nén nó hoặc cách tạo hàm băm từ mật khẩu văn bản thuần túy. Điều này giúp bảo vệ mật khẩu như thế nào để chống lại việc quét các bảng cầu vồng cho các hàm băm, về cơ bản đây là ý tưởng chính đằng sau muối?
Vitaliy Lebedev

13
Không quan trọng nếu kẻ tấn công biết muối cho bất kỳ băm cụ thể nào, đó không phải là một bí mật. Sử dụng một muối khác nhau cho mỗi mật khẩu có nghĩa là kẻ tấn công không thể tính toán trước các hàm băm bằng các giá trị chung. Với mỗi loại muối khác nhau, họ sẽ cần tính toán lại bất kỳ bảng nào cho mỗi mật khẩu khiến chúng trở nên vô dụng.
Hóa đơn

3
nhìn vào cách này, không vấn đề gì nếu kẻ tấn công biết muối cho người dùng nhất định trong cơ sở dữ liệu như thế này: column_password = hash, column_salt = saltvs column_password = hash_salt. kẻ tấn công vẫn có thông tin tương tự. Điểm mấu chốt là làm cho mọi mật khẩu trở nên ngẫu nhiên và lớn hơn đến mức khó có thể ai đó đã tính toán trước.
Muhammad Umer

27

Tôi cũng có câu hỏi tương tự như người đăng ban đầu và phải xem xét một chút xung quanh và thử những thứ khác nhau để hiểu cơ chế. Như đã được chỉ ra bởi những người khác, muối được nối với hàm băm cuối cùng. Vì vậy, điều này có nghĩa là một vài điều:

  1. Thuật toán phải biết độ dài của muối
  2. Cũng phải biết vị trí của muối trong chuỗi cuối cùng. ví dụ: nếu bù đắp bởi một số cụ thể từ trái hoặc phải.

Hai thứ này thường được mã hóa cứng trong quá trình triển khai, ví dụ như nguồn triển khai bcrypt cho bcryptjs định nghĩa độ dài muối là 16

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

var BCRYPT_SALT_LEN = 16;

Vì vậy, để minh họa khái niệm cơ bản đằng sau ý tưởng nếu một người muốn thực hiện nó theo cách thủ công, Nó sẽ trông tương tự như bên dưới. Tôi không khuyên bạn nên tự mình thực hiện những thứ như thế này khi có các thư viện mà bạn có thể thực hiện.

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

Vì bản thân tôi cũng có câu hỏi tương tự nên tôi biết chính xác bạn đang nghĩ gì.

Bạn có quan niệm sai lầm giữa "Khóa bí mật" được sử dụng trong thuật toán Mật mã và "Muối" được sử dụng để làm chậm quá trình mã hóa và khiến tin tặc khó sử dụng vũ lực hơn.

Khi bạn sử dụng mật khẩu đơn giản và muối để tạo hàm băm, hàm băm này sẽ sử dụng làm khóa bí mật của chính mật khẩu ! Vì vậy, lần sau, bạn sẽ thử so sánh nó với một mật khẩu thuần túy, mật khẩu thuần túy này phải giống hệt mật khẩu bạn đã sử dụng để tạo hàm băm! Vì vậy, đây là lý do tại sao bạn không phải lưu trữ nó ở một nơi khác vì nó luôn được cung cấp bởi người dùng ở cả hai bước đăng ký và đăng nhập!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.