Bagaimana node.bcrypt.js membandingkan kata sandi hash dan teks biasa tanpa salt?


96

Dari github :

Untuk mencirikan kata sandi:

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

Untuk memeriksa kata sandi:

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

Dari atas, bagaimana mungkin tidak ada nilai garam yang terlibat dalam perbandingan? Apa yang kulewatkan di sini?

Jawaban:


99

Garam dimasukkan ke dalam hash (sebagai teks biasa). Fungsi bandingkan hanya menarik salt keluar dari hash dan kemudian menggunakannya untuk hash kata sandi dan melakukan perbandingan.


1
Saya masih belum mengerti. Saat membandingkan, bagaimana cara mengetahui bagian mana dari hash yang merupakan garam jika Anda tidak memberikannya dengan garam?
MondayPaper

7
bcrypt adalah standar dan selalu menggabungkan salt dengan hash dalam format yang sama. Anda memberikan garam saat mengenkripsi dan ini dimasukkan ke dalam hash. bcrypt hanya akan dapat mendekripsi data yang awalnya dienkripsi menggunakan bcrypt, jika tidak, Anda benar - tidak akan ada cara untuk mengetahui bagian mana yang merupakan hash dan bagian mana yang merupakan garam.
Tagihan

6
Oke, kami mengerti: garam disimpan dengan hash. bcrypt adalah open source, jadi ini berarti semua orang tahu bagaimana tepatnya menyimpannya. Jadi Anda tahu cara mengekstraknya, atau cara membuat hash dari kata sandi teks biasa. Bagaimana ini membantu melindungi kata sandi dari pemindaian tabel pelangi untuk mencari hash, yang pada dasarnya merupakan ide utama di balik garam?
Vitaliy Lebedev

13
Tidak masalah jika penyerang mengetahui garam untuk hash tertentu, itu bukan rahasia. Menggunakan garam yang berbeda untuk setiap sandi berarti penyerang tidak dapat menghitung hash sebelumnya menggunakan nilai umum. Dengan salt yang berbeda pada masing-masing, mereka perlu menghitung ulang tabel apa pun untuk setiap kata sandi yang membuatnya tidak berguna.
Bill

3
lihat cara ini, bedanya jika penyerang tahu garam bagi pengguna tertentu dalam data base seperti ini: column_password = hash, column_salt = saltvs column_password = hash_salt. penyerang masih memiliki informasi yang sama. Titik garam adalah membuat setiap kata sandi begitu acak dan lebih besar sehingga menjadi tidak mungkin seseorang telah menghitungnya sebelumnya.
Muhammad Umer

27

Saya juga memiliki pertanyaan yang sama seperti poster asli dan perlu melihat-lihat dan mencoba berbagai hal untuk memahami mekanismenya. Seperti yang telah ditunjukkan oleh orang lain, garam digabungkan ke hash terakhir. Jadi ini berarti beberapa hal:

  1. Algoritma harus mengetahui panjang garam
  2. Harus juga mengetahui posisi garam di string terakhir. misal jika diimbangi dengan angka tertentu dari kiri atau kanan.

Kedua hal ini biasanya dikodekan dengan keras dalam implementasinya, misalnya sumber implementasi bcrypt untuk bcryptjs mendefinisikan panjang garam sebagai 16

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

var BCRYPT_SALT_LEN = 16;

Jadi untuk mengilustrasikan konsep dasar di balik ide jika seseorang ingin melakukannya secara manual, akan terlihat seperti di bawah ini. Saya tidak menyarankan menerapkan hal-hal seperti ini sendiri ketika ada perpustakaan yang bisa Anda lakukan.

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

1

Karena saya sendiri memiliki pertanyaan yang sama, saya tahu persis apa yang Anda pikirkan.

Anda memiliki kesalahpahaman antara "Kunci Rahasia" yang digunakan dalam algoritme Kriptografi dan "Garam" yang digunakan untuk memperlambat proses enkripsi dan mempersulit peretas untuk menggunakan kekerasan.

Saat Anda menggunakan kata sandi biasa dan salt untuk menghasilkan hash, hash ini menggunakan kunci rahasia dari kata sandi itu sendiri ! Jadi lain kali Anda akan mencoba membandingkannya dengan kata sandi biasa, kata sandi biasa ini harus sama persis dengan yang Anda gunakan untuk membuat hash! Jadi inilah mengapa Anda tidak perlu menyimpannya di tempat lain karena selalu disediakan oleh pengguna pada langkah mendaftar dan masuk!


1

Bcrypt membandingkan kata sandi hash dan teks biasa tanpa string garam karena kata sandi hash berisi string garam yang kami buat saat melakukan hashing.

Sebagai contoh :

Ambil Kata Sandi Biasa ini:

546456546456546456456546111

Sandi yang di-hash dari teks biasa di atas menggunakan Bcrypt:

$ 2b $ 10 $ uuIKmW3Pvme9tH8qOn / H7uZqlv9ENS7zlIbkMvCSDIv7aup3WNH9W

Jadi dalam kata sandi hash di atas, Ada tiga bidang yang dipisahkan oleh simbol $ .

i) Bagian Pertama $ 2b $ mengidentifikasi versi algoritma bcrypt yang digunakan.

ii) Bagian Kedua $ 10 $ 10 adalah faktor biaya (tidak ada apa-apa selain putaran garam saat kita membuat string garam. Jika kita melakukan 15 putaran, maka nilainya akan menjadi $ 15 $

iii) Bagian Ketiga adalah 22 karakter pertama (yang tidak lain adalah string garam) Dalam hal ini adalah

uuIKmW3Pvme9tH8qOn / H7u

String yang tersisa adalah kata sandi berciri. Jadi pada dasarnya, saltedHash = salt string + hashedPassword untuk melindungi dari serangan tabel pelangi.


1

Itu hanya string dengan panjang tetap.

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

0

Garam dimasukkan ke dalam hash. Fungsi bandingkan hanya menarik salt keluar dari hash dan kemudian menggunakannya untuk hash kata sandi dan melakukan perbandingan.

Ketika seorang pengguna akan masuk ke sistem kami, kami harus memeriksa kata sandi yang dimasukkan benar atau tidak. Tidak seperti sistem lain yang akan mendekripsi kata sandi dalam database (jika dienkripsi), dan membandingkannya dengan yang dimasukkan oleh pengguna, apa yang saya lakukan dengan bcrypt (mengingat itu mengimplementasikan hashing satu arah) adalah mengenkripsi yang dimasukkan oleh pengguna. Untuk melakukan ini, saya akan meneruskan kata sandi ke bcrypt untuk menghitung hash, tetapi juga kata sandi yang disimpan dalam database yang terkait dengan pengguna (hash). Ini karena, seperti yang disebutkan sebelumnya, algoritme bcrypt menggunakan segmen acak (garam) untuk menghasilkan hash yang terkait dengan kata sandi. Ini disimpan bersama dengan kata sandi, dan Anda membutuhkannya untuk menghitung ulang hash kata sandi yang dimasukkan oleh pengguna dan akhirnya membandingkan dengan yang dimasukkan saat mendaftar dan melihat apakah cocok.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.