← Tất cả bài viết

Base64 là gì? Khi nào dùng và cách encode/decode

19/07/2026

Nếu bạn từng mở một file HTML và thấy ảnh được nhúng dưới dạng một chuỗi ký tự dài loằng ngoằng bắt đầu bằng data:image/png;base64,..., hoặc từng nhìn vào phần header của một JWT, thì bạn đã gặp Base64 rồi. Base64 xuất hiện ở khắp nơi trong lập trình web và backend, nhưng nó cũng là một trong những khái niệm bị hiểu lầm nhiều nhất. Bài viết này giải thích Base64 thật sự là gì, nó hoạt động ra sao, khi nào nên dùng, và một hiểu lầm tai hại mà bạn phải tránh.

Base64 là gì?

Base64 là một phương pháp mã hoá (encoding) giúp biểu diễn dữ liệu nhị phân (binary) dưới dạng chuỗi văn bản ASCII chỉ gồm các ký tự an toàn. Tên gọi "Base64" đến từ việc nó sử dụng một bảng gồm 64 ký tự để biểu diễn dữ liệu.

Vì sao cần một thứ như vậy? Rất nhiều kênh truyền và định dạng lưu trữ dữ liệu ban đầu chỉ được thiết kế để xử lý văn bản, không phải dữ liệu nhị phân thô. Ví dụ điển hình là email (giao thức SMTP), URL, JSON, hay các file cấu hình. Nếu bạn nhét thẳng byte nhị phân của một tấm ảnh vào những kênh này, các byte "đặc biệt" (như ký tự null, ký tự điều khiển, hoặc byte không hợp lệ trong bảng mã) có thể bị hỏng, bị cắt, hoặc bị hiểu sai. Base64 giải quyết vấn đề đó bằng cách chuyển mọi dữ liệu nhị phân thành một tập ký tự "trung tính" mà hầu như mọi hệ thống text đều xử lý được an toàn.

Cảnh báo quan trọng: Base64 KHÔNG phải là mã hoá bảo mật

Đây là hiểu lầm phổ biến nhất và cũng nguy hiểm nhất. Base64 không phải là encryption (mã hoá bảo mật). Nó không có khoá bí mật, không bảo vệ dữ liệu, và bất kỳ ai cũng có thể decode ngược lại chỉ trong một giây.

Hãy phân biệt rõ:

  • Encoding (Base64): chỉ là đổi cách biểu diễn dữ liệu để truyền/lưu trữ. Hoàn toàn thuận nghịch, không cần khoá. Mục đích là tương thích, không phải bảo mật.
  • Encryption (AES, RSA...): biến dữ liệu thành dạng không đọc được nếu không có khoá. Mục đích là bảo mật.
  • Hashing (SHA-256, bcrypt...): hàm một chiều, không thể đảo ngược. Dùng để kiểm tra toàn vẹn hoặc lưu mật khẩu.

Đừng bao giờ dùng Base64 để "giấu" mật khẩu, token, hay dữ liệu nhạy cảm và nghĩ rằng nó an toàn. Một chuỗi Base64 giống như viết chữ lên tấm kính trong suốt: ai nhìn cũng đọc được. Nếu cần bảo mật, bạn phải mã hoá thật (encryption) trước, rồi mới có thể Base64 phần dữ liệu đã mã hoá đó để truyền đi.

Base64 hoạt động như thế nào?

Nguyên lý cốt lõi khá đơn giản và dựa trên việc chia nhỏ dữ liệu theo bit:

  1. Lấy dữ liệu đầu vào và nhóm lại thành từng khối 3 byte. Vì mỗi byte có 8 bit, một khối 3 byte tương đương 24 bit.
  2. Chia 24 bit đó thành 4 nhóm 6 bit.
  3. Mỗi nhóm 6 bit có giá trị từ 0 đến 63 (vì 2⁶ = 64). Dùng giá trị này để tra vào bảng 64 ký tự và lấy ra một ký tự tương ứng.

Như vậy cứ 3 byte đầu vào sẽ tạo ra 4 ký tự đầu ra. Bảng 64 ký tự chuẩn gồm: chữ hoa A-Z (26 ký tự), chữ thường a-z (26 ký tự), chữ số 0-9 (10 ký tự), cộng với hai ký tự +/. Tổng cộng đúng 64 ký tự.

Padding và ký tự "="

Điều gì xảy ra khi độ dài dữ liệu không chia hết cho 3? Lúc này Base64 dùng ký tự = để "đệm" (padding) cho đủ khối 4 ký tự đầu ra:

  • Nếu dư 1 byte (8 bit): tạo ra 2 ký tự Base64 + ==.
  • Nếu dư 2 byte (16 bit): tạo ra 3 ký tự Base64 + =.

Ký tự = không mang dữ liệu, nó chỉ báo cho bộ giải mã biết rằng phần cuối đã được đệm.

Ví dụ cụ thể: encode chuỗi "Hello"

Chuỗi Hello gồm 5 byte, không chia hết cho 3 nên sẽ có padding. Kết quả cuối cùng là:

"Hello"  →  "SGVsbG8="

Bạn có thể tự kiểm chứng ngay bằng công cụ Base64 Encode / Decode của DevToolHub — dán chuỗi vào và xem kết quả encode/decode tức thì, không cần cài đặt gì.

Vì sao chuỗi Base64 dài hơn khoảng 33%?

Câu trả lời nằm ngay trong nguyên lý: cứ 3 byte đầu vào (24 bit) biến thành 4 ký tự đầu ra, mà mỗi ký tự lại chiếm 1 byte khi lưu dưới dạng text. Tức là 3 byte gốc trở thành 4 byte sau khi encode — tăng thêm 1/3, tương đương khoảng 33%. Nếu tính cả padding và ký tự xuống dòng (một số định dạng như MIME chèn newline sau mỗi 76 ký tự), chi phí có thể còn cao hơn chút ít.

Đây là cái giá phải trả cho tính tương thích: bạn đánh đổi kích thước lớn hơn để lấy khả năng truyền dữ liệu an toàn qua các kênh chỉ chấp nhận text. Vì vậy đừng lạm dụng Base64 cho file lớn khi không cần thiết.

Ứng dụng thực tế của Base64

Base64 có mặt ở rất nhiều nơi trong công việc hằng ngày của developer:

  • Data URI: nhúng thẳng ảnh, font, hoặc file nhỏ vào HTML/CSS dưới dạng data:image/png;base64,.... Giúp giảm số HTTP request, hữu ích cho icon nhỏ hoặc email HTML.
  • HTTP Basic Auth: header Authorization mang chuỗi Basic base64(username:password). Lưu ý đây chính là ví dụ điển hình cho việc Base64 KHÔNG bảo mật — Basic Auth bắt buộc phải đi kèm HTTPS.
  • JWT (JSON Web Token): mỗi phần trong ba phần của token (header, payload, signature) đều được mã hoá bằng Base64URL. Đó là lý do bạn có thể decode payload của JWT và đọc được nội dung mà không cần khoá.
  • Email (MIME): file đính kèm nhị phân trong email được Base64 hoá để truyền qua SMTP vốn chỉ hỗ trợ text.
  • Lưu dữ liệu nhị phân trong JSON/XML: khi API cần trả về hoặc nhận một blob nhỏ (chữ ký số, ảnh thumbnail...), Base64 là cách phổ biến để đặt nó vào một trường string.

Base64 vs Base64URL

Bảng Base64 chuẩn dùng hai ký tự +/. Vấn đề là cả hai đều có ý nghĩa đặc biệt trong URL: / phân tách đường dẫn, còn + thường bị hiểu thành dấu cách. Nếu nhét chuỗi Base64 thô vào URL, dữ liệu có thể bị hỏng.

Base64URL là biến thể "an toàn cho URL", giải quyết bằng cách:

Đặc điểm Base64 chuẩn Base64URL
Ký tự thứ 63 + - (dấu gạch ngang)
Ký tự thứ 64 / _ (gạch dưới)
Padding "=" Thường bỏ đi

Đây là lý do các phần của JWT trông không có dấu +, / hay = — chúng dùng Base64URL để token có thể đặt an toàn trong URL, cookie, hoặc header.

Encode/decode bằng code

Trong trình duyệt (JavaScript), hai hàm có sẵn là btoa() (encode) và atob() (decode):

// Encode
const encoded = btoa("Hello");
console.log(encoded); // "SGVsbG8="

// Decode
const decoded = atob("SGVsbG8=");
console.log(decoded); // "Hello"

Cảnh báo về Unicode: btoa() chỉ hoạt động với ký tự trong khoảng Latin1 (mỗi ký tự ≤ 1 byte). Nếu bạn truyền chuỗi có tiếng Việt có dấu hoặc emoji, nó sẽ ném lỗi InvalidCharacterError. Cách xử lý đúng là chuyển chuỗi sang byte UTF-8 trước:

// Encode chuỗi Unicode an toàn
function encodeUtf8Base64(str) {
  const bytes = new TextEncoder().encode(str);
  const bin = String.fromCharCode(...bytes);
  return btoa(bin);
}

// Decode ngược lại
function decodeUtf8Base64(b64) {
  const bin = atob(b64);
  const bytes = Uint8Array.from(bin, c => c.charCodeAt(0));
  return new TextDecoder().decode(bytes);
}

console.log(encodeUtf8Base64("Xin chào")); // hoạt động đúng với dấu

Trong Node.js thì đơn giản hơn nhờ Buffer:

const encoded = Buffer.from("Xin chào", "utf-8").toString("base64");
const decoded = Buffer.from(encoded, "base64").toString("utf-8");

// Cho Base64URL:
const urlSafe = Buffer.from("data").toString("base64url");

Tóm tắt

Base64 là công cụ nền tảng để biểu diễn dữ liệu nhị phân dưới dạng text an toàn cho việc truyền và lưu trữ. Những điểm cần nhớ:

  • Base64 là encoding, không phải encryption — không bảo mật gì cả, ai cũng decode được.
  • Nguyên lý: 3 byte (24 bit) → 4 ký tự 6-bit, dùng bảng 64 ký tự, đệm bằng =.
  • Chuỗi kết quả dài hơn khoảng 33% so với dữ liệu gốc.
  • Base64URL thay +/ bằng -_ và bỏ padding — bắt buộc cho URL và JWT.
  • Trong JS, cẩn thận với Unicode khi dùng btoa()/atob().

Muốn thử ngay? Dùng công cụ Base64 Encode / Decode của DevToolHub để encode và decode trực tiếp trên trình duyệt — nhanh, miễn phí, và dữ liệu của bạn không bao giờ rời khỏi máy.