[node.js] node.bcrypt.js는 솔트가없는 해시 된 암호와 일반 텍스트 암호를 어떻게 비교합니까?

에서 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
});

위에서 어떻게 비교에 소금 값이 없을 수 있습니까? 내가 여기서 무엇을 놓치고 있습니까?



답변

솔트는 해시에 통합됩니다 (일반 텍스트). 비교 기능은 단순히 해시에서 솔트를 가져온 다음이를 사용하여 암호를 해시하고 비교를 수행합니다.


답변

나도 원래 포스터와 같은 질문을했고 메커니즘을 이해하기 위해 주위를 둘러 보며 여러 가지 시도를했습니다. 다른 사람들이 이미 지적했듯이 솔트는 최종 해시에 연결됩니다. 따라서 이것은 몇 가지를 의미합니다.

  1. 알고리즘은 소금의 길이를 알아야합니다.
  2. 최종 문자열에서 소금의 위치도 알아야합니다. 예를 들어 왼쪽 또는 오른쪽에서 특정 숫자만큼 오프셋 된 경우.

이 두 가지가 일반적으로 하드 구현에 코딩 등의 bcrypt 구현 소스 bcryptjs는 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');
        }
    });
}


답변

Bcrypt는 해시 된 암호에 해시 할 때 생성 한 솔트 문자열이 포함되어 있기 때문에 솔트 문자열없이 해시 된 암호와 일반 텍스트 암호를 비교합니다.

예 :

이 일반 암호 사용 :

546456546456546456456546111

Bcrypt를 사용하는 위의 일반 텍스트의 해시 된 암호 :

$ 2b $ 10 $ uuIKmW3Pvme9tH8qOn / H7uZqlv9ENS7zlIbkMvCSDIv7aup3WNH9W

따라서 위의 해시 된 암호에는 $로 구분 된 세 개의 필드가 있습니다. 기호로 .

i) 첫 부분 $ 2b $ 는 사용 된 bcrypt 알고리즘 버전을 식별합니다.

ii) 두 번째 부분 $ 10 $ 10이 비용 요소입니다 (솔트 문자열을 만드는 동안 소금 라운드 만 발생합니다. 15 라운드를 수행하면 값은 $ 15 $가됩니다.

iii) 세 번째 부분은 처음 22 자입니다 (솔트 문자열 일뿐입니다).

uuIKmW3Pvme9tH8qOn / H7u

나머지 문자열은 해시 된 암호입니다. 따라서 기본적으로 saltedHash = salt string + hashedPassword는 레인보우 테이블 공격으로부터 보호합니다.


답변

저도 같은 질문을했기 때문에 당신이 무슨 생각을하는지 정확히 알고 있습니다.

암호화 알고리즘에 사용되는 “Secret Key” 와 암호화 프로세스를 늦추고 해커가 무차별 대입을 어렵게 만드는 데 사용되는 “Salt” 사이에 오해 가 있습니다.

당신이 사용하는 경우 일반 암호 해시를 생성하고 소금을이 해시는 비밀 키 암호 자체로 사용 ! 따라서 다음에 일반 암호와 비교하려고 할 때이 일반 암호는 해시를 생성하는 데 사용한 것과 동일해야합니다! 따라서 등록 및 로그인 단계에서 항상 사용자가 제공하므로 다른 곳에 저장할 필요가 없습니다!


답변

소금은 해시에 통합됩니다. 비교 기능은 단순히 해시에서 솔트를 가져온 다음이를 사용하여 암호를 해시하고 비교를 수행합니다.

사용자가 시스템에 로그인 할 때 입력 한 암호가 올바른지 확인해야합니다. 데이터베이스에서 암호를 해독하고 (암호화 된 경우) 사용자가 입력 한 암호와 비교하는 다른 시스템과 달리 bcrypt로 수행하는 작업 (단방향 해싱을 구현하는 경우)은 암호를 암호화하는 것입니다. 사용자. 이를 위해 암호를 bcrypt에 전달하여 해시를 계산할뿐만 아니라 사용자 (해시)와 관련된 데이터베이스에 저장된 암호도 계산합니다. 이는 앞에서 언급했듯이 bcrypt 알고리즘이 임의 세그먼트 (salt)를 사용하여 pasword와 관련된 해시를 생성하기 때문입니다. 이것은 암호와 함께 저장되었으며 사용자가 입력 한 암호의 해시를 다시 계산하고 마지막으로 등록 할 때 입력 한 것과 비교하여 일치하는지 확인하는 데 필요합니다.


답변

고정 된 길이의 문자열입니다.

console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);

console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);

console.log("");
var salt = bcrypt.genSaltSync(10);
console.log(salt);
hash = bcrypt.hashSync("foobar", salt);
console.log(hash);
$2a$10$onmcKV.USxnoQAsQwBFB3e
$2a$10$onmcKV.USxnoQAsQwBFB3eytL3UZvZ5v/SudaWyaB9Vuq9buUqGO2

$2a$10$mwQfdyVS9dsO4SuxoR5Ime
$2a$10$mwQfdyVS9dsO4SuxoR5ImeG7atz7RXGRXb.c0VHp5zSn1N2VOA.Vq

$2a$10$uVUuJr6LryjchhKEg6PH7u
$2a$10$uVUuJr6LryjchhKEg6PH7unTw8aJGK0i3266c5kqDBLJkf80RHEpq

$2a$10$Y.upG5/54zvJyZacRxP17O
$2a$10$Y.upG5/54zvJyZacRxP17OH60BC0hQRMNfQjJxSWE77fyBrbzalmS


답변