Mã hóa End-to-End bằng Public Key (RSA) trong JavaScript

Tạo mã hóa đầu cuối (End-to-End) bằng Private và Public Key trong JavaScript

End-to-end encryption

Mã hóa đầu cuối (End-to-end encryption) là một biện pháp bảo mật mạnh mẽ nhằm đảm bảo rằng chỉ người nhận dự định mới có thể truy cập dữ liệu. Đó là một hình thức mã hóa sử dụng hai khóa, khóa chung và khóa riêng (Private và Public Key) để mã hóa và giải mã dữ liệu. Trong bài viết này, chúng ta sẽ xem xét cách tạo mã hóa đầu cuối bằng khóa riêng và khóa chung trong JavaScript.

Các bước trong mã hóa JavaScript

Tạo khóa

Bước đầu tiên là tạo một cặp khóa. Điều này có thể được thực hiện bằng phương thức window.crypto.subtle.generateKey(). Phương thức này lấy một đối tượng chứa tên thuật toán, độ dài mô đun, số mũ công khai và thuật toán băm. Độ dài mô đun có thể là 1024, 2048 hoặc 4096 và thuật toán băm có thể là SHA-1, SHA-256, SHA-384 hoặc SHA-512.

const { publicKey, privateKey } = await window.crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048, // 1024, 2048, or 4096
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: { name: "SHA-256" }, // "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
  },
  true, // whether the key is extractable (i.e. can be used in exportKey)
  ["encrypt", "decrypt"]
);

Mã hóa

Khi cặp khóa được tạo, bước tiếp theo là mã hóa dữ liệu. Điều này có thể được thực hiện bằng phương thức window.crypto.subtle.encrypt(). Phương thức này lấy một đối tượng chứa tên thuật toán, khóa chung và dữ liệu cần mã hóa.

const encryptedData = await window.crypto.subtle.encrypt(
  {
    name: "RSA-OAEP",
  },
  publicKey, // from generateKey or importKey above
  data // ArrayBuffer of data you want to encrypt
);

Giải mã

Cuối cùng, dữ liệu được mã hóa có thể được giải mã bằng phương thức window.crypto.subtle.decrypt(). Phương thức này lấy một đối tượng chứa tên thuật toán, khóa riêng và dữ liệu được mã hóa.

const decryptedData = await window.crypto.subtle.decrypt(
  {
    name: "RSA-OAEP",
  },
  privateKey, // from generateKey or importKey above
  encryptedData // ArrayBuffer of the data
);

Kết

Trong bài viết này, chúng ta đã xem xét cách tạo mã hóa đầu cuối bằng khóa riêng và khóa chung trong JavaScript, kèm theo các ví dụ về mã. Chúng ta đã biết cách tạo cặp khóa, mã hóa dữ liệu và giải mã dữ liệu. Với kiến ​​thức này, giờ đây bạn có thể tạo mã hóa đầu cuối an toàn trong các ứng dụng JavaScript của mình.

Code ví dụ

const str2ab = (strt) => {
  const str = window.atob(strt);
  const buf = new ArrayBuffer(str.length);
  const bufView = new Uint8Array(buf);
  for (let i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
};
const ab2str = (buf) => {
  return window.btoa(
    String.fromCharCode.apply(null, new Uint8Array(buf))
  );
};

// tạo key
const key = await window.crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048, // 1024, 2048, or 4096
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
    hash: { name: "SHA-256" }, // "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
  },
  true,
  ["encrypt", "decrypt"]
);

var publicKey = key.publicKey;
var privateKey = key.privateKey;

// chuyển key thành string để tiện lưu trữ hoặc gửi đi
// publicKey = await window.crypto.subtle.exportKey("spki", publicKey);
// publicKey = ab2str(publicKey);
// console.log(publicKey);
// publicKey = str2ab(publicKey);
// publicKey = await window.crypto.subtle.importKey(
//   "spki",
//   publicKey,
//   { name: "RSA-OAEP", length: 2048, hash: "SHA-256" },
//   false,
//   ["encrypt"]
// );
// 
// privateKey = await window.crypto.subtle.exportKey("pkcs8", privateKey);
// privateKey = ab2str(privateKey);
// console.log(privateKey);
// privateKey = str2ab(privateKey);
// privateKey = await window.crypto.subtle.importKey(
//   "pkcs8",
//   privateKey,
//   { name: "RSA-OAEP", length: 2048, hash: "SHA-256" },
//   false,
//   ["decrypt"]
// );

// encrypt
var encryptedData = await window.crypto.subtle.encrypt(
  {
    name: "RSA-OAEP",
  },
  publicKey,
  new TextEncoder().encode("data content")
);

// Data encrypted thành string để tiện lưu trữ hoặc gửi đi
// encryptedData = ab2str(encryptedData);
// console.log(encryptedData);
// encryptedData = str2ab(encryptedData);

// decrypt
const decryptedData = await window.crypto.subtle.decrypt(
  {
    name: "RSA-OAEP",
  },
  privateKey,
  encryptedData
);

console.log(new TextDecoder().decode(decryptedData));

Tham khảo thêm:

Mã hóa đầu cuối End-to-End bằng trong JavaScript