Cách xác minh chữ ký JWT: HS256, RS256 và ES256
Cách xác minh chữ ký JWT
Một JWT mang các claim của nó ở dạng văn bản thuần túy. Điều duy nhất ngăn chặn việc giả mạo là chữ ký. Nếu không xác minh, kẻ tấn công có thể tạo ra các token tùy ý và mạo danh bất kỳ người dùng nào. Hướng dẫn này đề cập đến ba thuật toán ký JWT phổ biến nhất và cách xác minh từng thuật toán.
Quy trình xác minh
Bất kể thuật toán nào, việc xác minh chữ ký JWT đều tuân theo các bước giống nhau:
- Tách token theo dấu
.để trích xuất header, payload và signature. - Giải mã base64url header để đọc trường
alg. - Tính toán lại chữ ký từ header và payload bằng thuật toán và khóa.
- So sánh chữ ký tính toán lại với chữ ký của token.
- Nếu chúng khớp, token là xác thực.
HS256 (HMAC-SHA256)
HS256 là thuật toán đối xứng — cùng một secret key tạo và xác minh chữ ký.
signature = HMACSHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
secret
)
Để xác minh, hãy tính toán lại HMAC bằng secret dùng chung và so sánh:
Token: header.payload.sig
Secret: "my-shared-secret"
1. Compute: HMACSHA256("header.payload", "my-shared-secret")
2. Compare: computedSignature === sig
Lưu ý bảo mật: Secret phải được giữ bí mật, được xoay vòng định kỳ và có ít nhất 256 bit entropy. HS256 không lý tưởng cho các kiến trúc microservice, nơi nhiều dịch vụ cần dùng chung secret.
RS256 (RSA-SHA256)
RS256 là bất đối xứng. Bên phát hành ký bằng private key; các bên xác minh kiểm tra bằng public key tương ứng.
signature = RSASHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
privateKey
)
Để xác minh, hãy sử dụng public key:
Token: header.payload.sig
Public: "-----BEGIN PUBLIC KEY-----..."
1. Load the RSA public key
2. Verify: RSA_SHA256_verify("header.payload", sig, publicKey)
Ưu điểm: Khóa ký và khóa xác minh là riêng biệt. Bất kỳ dịch vụ nào cũng có thể xác minh mà không cần giữ secret. Public key có thể được phục vụ từ một JWKS endpoint để dễ dàng xoay vòng.
ES256 (ECDSA-SHA256)
ES256 sử dụng ECDSA với đường cong P-256. Giống như RS256, nó là bất đối xứng.
signature = ECDSA_SHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
privateKey
)
Việc xác minh sử dụng public key ECDSA P-256. ES256 tạo ra chữ ký nhỏ hơn nhiều (64 byte so với 256 byte của RSA-2048) và có tốc độ xác minh nhanh hơn.
So sánh các thuật toán
| Thuộc tính | HS256 | RS256 | ES256 | |----------|-------|-------|-------| | Loại khóa | Đối xứng (secret dùng chung) | Bất đối xứng (cặp RSA) | Bất đối xứng (cặp EC) | | Kích thước chữ ký | 32 byte | 256 byte | 64 byte | | Phân phối khóa | Chia sẻ bí mật | Public key là công khai | Public key là công khai | | Xoay vòng | Trung bình | Dễ dàng (JWKS) | Dễ dàng (JWKS) | | Trường hợp sử dụng | Hệ thống nội bộ đáng tin cậy | API phân tán | Di động, IoT |
Các lỗi thường gặp khi xác minh
- Tấn công nhầm lẫn thuật toán. Nếu mã của bạn đọc
algtừ token mà không kiểm soát, kẻ tấn công có thể thay đổi thuật toán. Luôn xác thực rằng thuật toán khớp với giá trị dự kiến. - Chấp nhận
alg: "none". Một số thư viện chấp nhận token không có chữ ký. Hãy từ chốialg: "none"một cách rõ ràng. - Cắt ngắn chữ ký. So sánh không theo thời gian hằng định có thể rò rỉ thông tin qua các tấn công timing. Hãy sử dụng hàm so sánh tích hợp sẵn của thư viện JWT của bạn.
Xác minh token JWT trực tuyến
Sử dụng công cụ JWT decoder để giải mã và xác thực bất kỳ token nào. Dán token, xem header và payload, rồi xác minh chữ ký bằng cách cung cấp secret hoặc public key tương ứng. Toàn bộ quá trình xử lý diễn ra trong trình duyệt của bạn.