Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Mã hóa AES trong JavaScript là gì?

AES (Advanced Encryption Standard) là tiêu chuẩn mã hóa đối xứng (symmetric encryption) phổ biến nhất hiện nay. JavaScript thực hiện AES qua Web Crypto API (trình duyệt) hoặc thư viện như Forge, crypto-js, Node.js crypto.

Cài đặt Forge (Node.js)

npm install node-forge

Ví dụ: AES-CBC 128-bit với Forge

const forge = require('node-forge');

// Tạo key 16 bytes (128-bit) ngẫu nhiên
const key = forge.random.getBytesSync(16);
// Tạo IV 16 bytes ngẫu nhiên
const iv = forge.random.getBytesSync(16);

// Mã hóa
function encrypt(plaintext, key, iv) {
  const cipher = forge.cipher.createCipher('AES-CBC', key);
  cipher.start({ iv: iv });
  cipher.update(forge.util.createBuffer(plaintext, 'utf8'));
  cipher.finish();
  return cipher.output.getBytes(); // Binary string
}

// Giải mã
function decrypt(ciphertext, key, iv) {
  const decipher = forge.cipher.createDecipher('AES-CBC', key);
  decipher.start({ iv: iv });
  decipher.update(forge.util.createBuffer(ciphertext));
  decipher.finish();
  return decipher.output.toString('utf8');
}

// Sử dụng
const plaintext = 'Dữ liệu bí mật cần bảo vệ';
const encrypted = encrypt(plaintext, key, iv);
const decrypted = decrypt(encrypted, key, iv);
console.log('Decrypted:', decrypted); // Dữ liệu bí mật cần bảo vệ

Lưu ý bảo mật quan trọng

  • Không hardcode key/IV trong code. Dùng KMS, env vars, key derivation (PBKDF2, scrypt, argon2).
  • IV phải duy nhất cho mỗi lần mã hóa cùng key (random 16 bytes).
  • Authentication: AES-CBC không cung cấp integrity. Dùng AES-GCM (authenticated encryption) hoặc thêm HMAC.
  • Web Crypto API (browser native): crypto.subtle.encrypt() – không cần thư viện ngoài.

Web Crypto API (Browser) – AES-GCM khuyến nghị

async function encryptAESGCM(plaintext, password) {
  const encoder = new TextEncoder();
  const keyMaterial = await crypto.subtle.importKey(
    'raw', encoder.encode(password), 'PBKDF2', false, ['deriveKey']
  );
  const key = await crypto.subtle.deriveKey(
    { name: 'PBKDF2', salt: crypto.getRandomValues(new Uint8Array(16)), iterations: 100000, hash: 'SHA-256' },
    keyMaterial, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']
  );
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, encoder.encode(plaintext));
  return { ciphertext: new Uint8Array(ciphertext), iv, salt }; // Lưu iv, salt để decrypt
}