Base64 an toàn URL

Mã hóa và giải mã Base64 an toàn URL (Base64url)

Văn bản thuần

Base64

Chạy cục bộ · An toàn để dán thông tin bí mật
Đầu ra Base64...

Base64url Encoding là gì?

Base64url là một biến thể của mã hóa Base64, được thiết kế đặc biệt để sử dụng trong URL, tên tệp và các ngữ cảnh khác mà các ký tự Base64 tiêu chuẩn + và / gây ra sự cố. Được định nghĩa trong RFC 4648 Mục 5, Base64url thay thế + bằng - (gạch ngang) và / bằng _ (gạch dưới), đồng thời bỏ qua các ký tự padding = ở cuối. Kết quả là một chuỗi có thể nhúng trực tiếp vào tham số truy vấn URL, tên tệp hoặc HTTP header mà không cần mã hóa phần trăm bổ sung.

Base64 tiêu chuẩn (RFC 4648 Mục 4) sử dụng 64 ký tự: A-Z, a-z, 0-9, + và /. Các ký tự + và / được dành riêng trong URL: + được hiểu là dấu cách trong query string (application/x-www-form-urlencoded), và / là dấu phân cách đường dẫn. Do đó, việc sử dụng Base64 tiêu chuẩn bên trong URL đòi hỏi phải mã hóa phần trăm các ký tự này (%2B, %2F), làm tăng độ dài chuỗi và khó đọc hơn. Base64url loại bỏ hoàn toàn vấn đề này bằng cách sử dụng các ký tự an toàn cho URL ngay từ đầu.

Ứng dụng nổi bật nhất của Base64url là trong JSON Web Token (JWT). Cả ba phần của JWT — header, payload và signature — đều được mã hóa Base64url. PKCE code verifier của OAuth 2.0, giá trị challenge của WebAuthn và nhiều sơ đồ API token cũng dựa vào Base64url. Hiểu rõ mã hóa này là thiết yếu với bất kỳ nhà phát triển nào làm việc với xác thực, phân quyền hoặc trao đổi dữ liệu mật mã.

Tại sao dùng công cụ Base64url này?

Chuyển đổi giữa Base64url và dữ liệu văn bản hoặc nhị phân trực tiếp trong trình duyệt. Hỗ trợ cả mã hóa lẫn giải mã, với xử lý tự động padding và thay thế ký tự.

Chuyển đổi tức thì
Kết quả cập nhật ngay khi bạn gõ. Mã hóa văn bản sang Base64url hoặc giải mã Base64url trở lại văn bản mà không có độ trễ — không cần gửi form hay tải lại trang.
🔗
Đầu ra an toàn cho URL
Đầu ra chỉ sử dụng các ký tự an toàn trong URL, tên tệp và HTTP header: A-Z, a-z, 0-9, gạch ngang và gạch dưới. Không cần mã hóa phần trăm.
🔒
Xử lý ưu tiên quyền riêng tư
Toàn bộ mã hóa và giải mã chạy cục bộ trong trình duyệt của bạn. JWT token, OAuth secret và API key bạn dán vào đây không bao giờ được truyền tới bất kỳ máy chủ nào.
🏛️
Tuân thủ tiêu chuẩn
Triển khai chính xác RFC 4648 Mục 5: - và _ thay thế + và /, padding được bỏ qua. Tương thích với các thư viện JWT, OAuth 2.0 PKCE và các triển khai WebAuthn.

Các trường hợp sử dụng Base64url

Kiểm tra JWT Token
Giải mã từng phần JWT (header, payload) để kiểm tra các claim, thời gian hết hạn và thuật toán ký mà không cần nhập thư viện JWT hoặc xác minh chữ ký.
Luồng OAuth 2.0 PKCE
Tạo và xác minh các giá trị code_verifier và code_challenge của PKCE. Phương thức code_challenge_method S256 yêu cầu hash SHA-256 được mã hóa Base64url của code_verifier.
Tích hợp WebAuthn / FIDO2
Challenge, credential ID và dữ liệu attestation của WebAuthn được truyền dưới dạng chuỗi Base64url giữa trình duyệt và máy chủ relying party. Giải mã chúng để gỡ lỗi luồng đăng ký và xác thực.
Tạo API Token
Tạo token an toàn cho URL từ các byte ngẫu nhiên cho liên kết đặt lại mật khẩu, xác minh email và định danh phiên. Base64url tạo ra các chuỗi ngắn gọn hoạt động trong URL mà không cần escape.
Pipeline DevOps và CI/CD
Lưu trữ các giá trị cấu hình nhị phân (chứng chỉ, khóa) dưới dạng chuỗi Base64url trong biến môi trường hoặc tệp YAML. Không giống Base64 tiêu chuẩn, đầu ra không chứa ký tự xung đột với shell expansion hoặc cú pháp YAML.
Kỹ thuật dữ liệu
Mã hóa các định danh nhị phân, hash hoặc checksum dưới dạng Base64url để dùng trong tên tệp, khóa cơ sở dữ liệu hoặc cột CSV nơi các ký tự + và / sẽ làm hỏng quá trình phân tích cú pháp hoặc yêu cầu escape.

So sánh Base64 tiêu chuẩn và Base64url

Base64url khác Base64 tiêu chuẩn ở đúng ba điểm. Thuật toán mã hóa hoàn toàn giống nhau — chỉ bảng chữ cái và hành vi padding thay đổi:

Tính năngTiêu chuẩn (RFC 4648 §4)Base64url (RFC 4648 §5)
Index 62+-
Index 63/_
Padding= (required)Omitted

Ba sự khác biệt này có nghĩa là việc chuyển đổi giữa Base64 tiêu chuẩn và Base64url rất đơn giản: thay + bằng -, / bằng _, và loại bỏ các ký tự = ở cuối. Chiều ngược lại: thay - bằng +, _ bằng /, và thêm lại padding để độ dài là bội số của 4. Hầu hết các ngôn ngữ cung cấp hỗ trợ Base64url gốc, khiến việc chuyển đổi thủ công là không cần thiết.

Bảng so sánh mã hóa

Bảng dưới đây hiển thị cùng một đầu vào được mã hóa bằng Base64 tiêu chuẩn và Base64url. Chú ý cách các ký tự padding (=) bị loại bỏ và + / / được thay thế bằng - / _ trong biến thể an toàn URL:

Đầu vàoBase64 tiêu chuẩnBase64url (không padding)
HelloSGVsbG8=SGVsbG8
AQQ==QQ
1+1=2MSsxPTI=MSsxPTI
subject?ref=1c3ViamVjdD9yZWY9MQ==c3ViamVjdD9yZWY9MQ
👍 (thumbs up)8J+RjQ==8J-RjQ

Ví dụ mã

Cách mã hóa và giải mã chuỗi Base64url trong các ngôn ngữ phổ biến. Mọi ví dụ đều tạo ra đầu ra an toàn để dùng trong URL, tên tệp và HTTP header:

JavaScript (browser)
// Encode to Base64url
function toBase64url(str) {
  return btoa(unescape(encodeURIComponent(str)))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '')
}
toBase64url('Hello!') // → "SGVsbG8h"

// Decode from Base64url
function fromBase64url(b64url) {
  const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/')
  const pad = (4 - b64.length % 4) % 4
  return decodeURIComponent(escape(atob(b64 + '='.repeat(pad))))
}
fromBase64url('SGVsbG8h') // → "Hello!"
Node.js
// Native base64url support since Node 15.7
const encoded = Buffer.from('Hello!').toString('base64url')
// → "SGVsbG8h"

const decoded = Buffer.from('SGVsbG8h', 'base64url').toString()
// → "Hello!"

// Decode a JWT payload
const jwt = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0...'
const payload = JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString())
// → { sub: "1234567890" }
Python
import base64

# Encode to Base64url (no padding)
encoded = base64.urlsafe_b64encode(b'Hello!').rstrip(b'=').decode()
# → "SGVsbG8h"

# Decode from Base64url (re-add padding)
def b64url_decode(s: str) -> bytes:
    s += '=' * (4 - len(s) % 4)  # restore padding
    return base64.urlsafe_b64decode(s)

b64url_decode('SGVsbG8h')  # → b'Hello!'
Go
package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    // Encode to Base64url (no padding)
    encoded := base64.RawURLEncoding.EncodeToString([]byte("Hello!"))
    fmt.Println(encoded) // → "SGVsbG8h"

    // Decode from Base64url
    decoded, _ := base64.RawURLEncoding.DecodeString("SGVsbG8h")
    fmt.Println(string(decoded)) // → "Hello!"
}

Câu hỏi thường gặp

Sự khác biệt giữa Base64 và Base64url là gì?
Base64url thay thế + bằng - và / bằng _ so với bảng chữ cái Base64 tiêu chuẩn, và bỏ qua các ký tự padding = ở cuối. Điều này làm cho đầu ra an toàn để dùng trong URL, tham số truy vấn, tên tệp và HTTP header mà không cần mã hóa bổ sung. Thuật toán cơ bản (chia byte thành các nhóm 6-bit ánh xạ tới ký tự ASCII) hoàn toàn giống nhau.
Tại sao JWT token dùng Base64url thay vì Base64 tiêu chuẩn?
JWT thường được truyền trong tham số truy vấn URL và HTTP Authorization header. Các ký tự + và / của Base64 tiêu chuẩn sẽ cần được mã hóa phần trăm trong URL, làm tăng độ dài và phá vỡ các phép so sánh chuỗi đơn giản. Đặc tả JWT (RFC 7519) bắt buộc sử dụng Base64url không có padding để đảm bảo token gọn gàng và an toàn cho URL theo mặc định.
Làm thế nào để chuyển đổi Base64 tiêu chuẩn sang Base64url?
Thay mỗi + bằng -, mỗi / bằng _, và xóa tất cả ký tự = ở cuối. Trong JavaScript: base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''). Trong Python: base64.urlsafe_b64encode(data).rstrip(b'='). Hầu hết các ngôn ngữ hiện đại cũng cung cấp hàm mã hóa Base64url chuyên dụng.
Mã hóa Base64url có thể đảo ngược không?
Có, Base64url hoàn toàn có thể đảo ngược. Để giải mã, thay - bằng + và _ bằng /, thêm lại ký tự padding = để độ dài là bội số của 4, sau đó giải mã như Base64 tiêu chuẩn. Đầu ra được giải mã giống hệt đầu vào ban đầu từng byte.
Tôi có thể dùng Base64url để mã hóa dữ liệu không?
Không. Base64url là mã hóa (encoding), không phải mã hóa bảo mật (encryption). Nó chuyển đổi dữ liệu nhị phân sang định dạng văn bản an toàn mà không có bất kỳ tính bí mật nào — bất kỳ ai cũng có thể giải mã nó. Nếu bạn cần bảo vệ dữ liệu, hãy mã hóa bảo mật trước bằng thuật toán phù hợp (AES, ChaCha20), sau đó mã hóa Base64url ciphertext để truyền tải.
Tại sao padding bị bỏ qua trong Base64url?
Các ký tự padding (=) không có mục đích khi bộ giải mã có thể tính toán số byte thiếu từ độ dài chuỗi: (4 - length % 4) % 4 cho biết padding cần thiết. Bỏ padding làm cho chuỗi ngắn hơn và tránh ký tự = vốn cần mã hóa phần trăm trong URL. RFC 4648 Mục 5 cho phép rõ ràng việc bỏ padding trong Base64url.
Làm thế nào để xử lý chuỗi Base64url có padding trong mã của tôi?
Một số hệ thống tạo ra chuỗi Base64url vẫn giữ padding =. Hầu hết bộ giải mã xử lý điều này đúng cách. Nếu bộ giải mã của bạn không xử lý được, hãy loại bỏ = ở cuối trước khi giải mã. Ngược lại, nếu thư viện yêu cầu padding, hãy tính và thêm vào: const padded = str + '='.repeat((4 - str.length % 4) % 4). Cách này hoạt động vì số lượng padding được xác định từ độ dài chuỗi.