Lập trình NodeJS phần nhiều chúng ta sẽ làm việc ở phần BackEnd vậy nên sẽ không thể tránh khỏi việc sẽ có lúc chúng ta phải sử dụng đến các thuật toán mã hoá để mã hoá dữ liệu phục vụ cho bảo mật thông tin. Trong bài này chúng ta sẽ cùng nhau tìm hiểu về các thuật toán băm nhé.

Các nhánh của các thuật toán mã hoá

Có thể tách các thuật toán mã hoá thành các nhánh như sau:

  1. Nhánh các thuật toán băm: Dùng để mã hoá mật khẩu, mã hoá dữ liệu lớn thành một đoạn dữ liệu nhỏ hơn và không thể dịch ngược lại được, một số thuật toán phổ biến là: MD5, SHA256, BCrypt.
  2. Nhánh các thuật toán mã hoá đối xứng: Dùng để mã hoá dữ liệu thông qua một khoá bí mật. Một số thuật toán phổ biến là: AES, DES.
  3. Nhánh thuật toán mã hoá bất đối xứng: Dùng để mã hoá dữ liệu thông qua một cặp khoá bí mật và công khai. Thuật toán hay được sử dụng là RSA.

Khởi tạo dự án

Chúng ta sẽ khởi tạo thư mục có tên security-example và một tập tin có tên main.js

MD5

Đây là thuật toán khá lâu đời, được sử dụng để mã hoá mật khẩu, băm tập tin để phục vụ cho mục đích kiểm tra tính toán vẹn của thông tin.
Mô tả cho việc mã hoá mật khẩu:

  1. Mật khẩu rõ ví dụ “Techmaster” thông qua MD5 sẽ bị biến thành một chuỗi hoàn toàn khác: c07d29d0dcfb5fa6c0adfc1737d955f0 khiến cho ngay cả người quản lý cơ sở dữ liệu cũng không biết được mật khâu của người dùng là gì.
  2. Khi người dùng gửi mật khẩu để đăng nhập thì mật khẩu sẽ được mã hoá và so sánh với mật khẩu đã được mã hoá lưu trong cơ sở dữ liệu.
    Mô tả cho việc băm tập tin để phục vụ cho mục đích kiểm tra tính toàn vẹn của dữ liệu:
  1. A sẽ gửi cho B văn bản thông qua 1 kênh đồng thời gửi chuỗi Hash được băm từ văn bản cho B qua một kênh khác.
  2. B nhận được văn bản sẽ băm văn bản bằng MD5 để nhận được chuỗi hash, so sánh với chuỗi Hash đã nhận được từ A nếu giống nhau tức là văn bản toàn vẹn, ngược lại thì không.
    Mã nguồn sử dụng MD5 trong NodeJS sẽ như sau:
const crypto = require('crypto');

var md5Hash = crypto
    .createHash('md5')
    .update('Techmaster')
    .digest('hex');

console.log('md5Hash: ', md5Hash);

SHA256

Chuỗi MD5 có vẻ ngắn với 128 bit dữ liệu, nên có thể bị va chạm kẻ tấn công vẫn có thể tấn công thông qua hình thức brute-force . Vậy nên chúng ta có thể một chuối hash dài hơn với 256 với thuật toán mã hoá SHA256. Mã nguồn sử dụng SHA256 với NodeJS sẽ như sau:

const crypto = require('crypto');

var sha256Hash = crypto
    .createHash('sha256')
    .update("Techmaster")
    .digest('hex');

console.log('sha256Hash: ', sha256Hash);

BCrypt

MD5 và SHA256 đều tương đối mạnh mẽ, tuy nhiên để sử dụng cho việc mã hoá mật khẩu vẫn chưa thực sự tốt, vì với cùng một chuỗi thì MD5 và SHA256 sẽ cho ra các chuỗi cố định, như vậy kẻ tấn công có thể tạo ra một cơ sở dữ liệu chứa các chuỗi và mã hoá, như vậy thì kẻ tấn công có được chuỗi mã hoá của người dùng thì vẫn có thể tìm ra được mật khẩu rõ của người dùng.
Để khắc phục vấn đề này chúng ta có thể sử dụng thuật toán BCrypt. Thuật toán này cho phép chúng ta bổ sung một chút “muối” để băm mật khấu, nếu chúng ta chọn một chút muối này khác biệt thì chuỗi hash tạo ra cũng khác dẫn đến kẻ tấn công sẽ khó lòng tạo ra được một cơ sở dữ liệu chính xác được.
Ví dụ sử dụng BCrypt với NodeJS sẽ như sau:

const bcrypt = require('bcrypt');

async function bcryptHashPassword(plainTextPassword) {
    const saltRounds = 10;
    const hashedPassword = await bcrypt.hash(plainTextPassword, saltRounds);
    return hashedPassword;
}

async function bcryptComparePasswords(plainTextPassword, hashedPassword) {
    const match = await bcrypt.compare(plainTextPassword, hashedPassword);
    return match;
}

(async () => {
    const password = 'Techmaster';
    const hashedPassword = await bcryptHashPassword(password);
    console.log(`Bcrypt Hash Password: ${hashedPassword}`);

    const isMatch = await bcryptComparePasswords(password, hashedPassword);
    console.log(`Bcrypt Password match: ${isMatch}`);
})();

Ở đây chúng ta đang sử dụng saltRounds = 10, nghĩa là số vòng xử lý muối trong quá trình tạo chuỗi hash là 10, kết quả chúng ta nhận được khi chạy chương trình là:

Bcrypt Hash Password: $2b$10$0BBdcgHFbQUrkXT6sak7F.v6lgD01M4jWXc43MBFz8DKpZHc2zoPK
Bcrypt Password match: true

Bây giờ khi chúng ta thay đổi saltRounds = 9 kết quả nhận được sẽ khác:

Bcrypt Hash Password: $2b$09$vprkZ3onCzLZh30M5Hl0FeJz1gmjf1hf8rHKi2sLRe2sJNtiwqgJa
Bcrypt Password match: true

Tổng kết

Như vậy chúng ta đã cùng nhau tạo tìm hiểu về một số thuật toán mã hoá băm với NodeJS.


Cám ơn bạn đã quan tâm đến bài viết|video này. Để nhận được thêm các kiến thức bổ ích bạn có thể:

  1. Đọc các bài viết của TechMaster trên facebook: https://www.facebook.com/techmastervn
  2. Xem các video của TechMaster qua Youtube: https://www.youtube.com/@TechMasterVietnam nếu bạn thấy video/bài viết hay bạn có thể theo dõi kênh của TechMaster để nhận được thông báo về các video mới nhất nhé.
  3. Chat với techmaster qua Discord: https://discord.gg/yQjRTFXb7a