Tiếng Việt

Công cụ dành cho nhà phát triển · Bộ mã hóa và giải mã Base64

Tại sao btoa() lại sử dụng biểu tượng cảm xúc và cách mã hóa Base64 UTF-8 trong JavaScript

· Cách thức hoạt động

base64 unicode mã hóa

Các ký tự Unicode được chuyển đổi thành UTF-8 byte trước khi mã hóa Base64
Hình minh họa vector ToolAcre gốc

btoa() chỉ chấp nhận các ký tự tối đa U+00FF, vì vậy văn bản có dấu CJK và biểu tượng cảm xúc. Bài đăng này cho biết hàm thực sự mong đợi điều gì và cách TextEncode cung cấp cho bạn chuỗi UTF-8 Base64 chính xác.

Tại sao btoa có thể sử dụng Unicode—và âm thầm mã hóa sai một dấu

Việc gọi btoa("😀") sẽ trả về InvalidCharacterError vì biểu tượng cảm xúc không thể vừa với một đơn vị mã có kích thước một byte. Một lỗi tinh vi hơn là btoa("é"): é được soạn sẵn là U+00E9, bên dưới 256, vì vậy btoa chấp nhận nó nhưng mã hóa Latin-1 byte E9, không phải UTF-8 byte C3 A9. Giọng có thể nhìn thấy tương tự được viết bằng e cộng với dấu kết hợp có thể bị loại vì dấu nằm ngoài phạm vi được chấp nhận. Viết tắt của sổ làm việc “một dấu nhấn” cần có tiêu chuẩn này: một chuỗi có thể bị lỗi lớn hoặc lặng lẽ tạo ra các byte sai.

btoa() thực sự mã hóa những gì: một chuỗi nhị phân gồm các đơn vị mã 0–255 — tại sao hàm này được thiết kế xoay quanh tiếng Latin-1 bytes thay vì văn bản Unicode

btoa sử dụng một “chuỗi nhị phân”: mỗi đơn vị mã ký tự JavaScript phải nằm trong phạm vi 0–255 và đại diện cho một byte. Nó không hiểu mã hóa văn bản Unicode, ngôn ngữ hoặc chuẩn hóa. Biểu tượng cảm xúc trung giới được biểu thị bằng hai đơn vị mã thay thế UTF-16, cả hai đều lớn hơn nhiều so với 255, do đó việc gửi trực tiếp chuỗi JavaScript thô không thể hoạt động. Hãy coi đầu ra là mã hóa byte chứ không phải ký tự trừu tượng.

UTF-8 đầu tiên, Base64 thứ hai - tại sao văn bản phải trở thành byte trước khi áp dụng bất kỳ bảng chữ cái Base64 nào

TextEncode trước tiên chuyển chuỗi JavaScript thành chuỗi byte UTF-8 của nó. Sau đó, biến từng byte thành ký tự chuỗi nhị phân và chuyển chuỗi nhị phân đó sang btoa hoặc sử dụng một API khác chấp nhận byte trực tiếp. Để giải mã, atob trả về chuỗi nhị phân; khôi phục các giá trị byte của nó và cung cấp chúng cho TextDecoding("utf-8"). ToolAcre sử dụng bộ giải mã nghiêm ngặt từ chối UTF-8 không đúng định dạng thay vì chèn các ký tự thay thế một cách âm thầm.

Ví dụ hoạt động: mã hóa 'café 😀' bằng TextEncoding và btoa — chuỗi byte, chuỗi nhị phân trung gian và đầu ra cuối cùng

Đối với quán cà phê văn bản theo nghĩa đen 😀, UTF-8 byte là 63 61 66 C3 A9 20 F0 9F 98 80 ở dạng thập lục phân: ASCII c-a-f, hai byte cho é, a dấu cách và bốn byte cho biểu tượng cảm xúc. Base64 của mười byte này là Y2Fmw6kg8J+YgA==. Phần đệm và bảng chữ cái chỉ mô tả các byte; họ không dán nhãn ngôn ngữ. So sánh lỗi btoa("café 😀") trực tiếp với chế độ UTF-8 của ToolAcre, sau đó giải mã kết quả và xác minh rằng giọng nói và biểu tượng cảm xúc có thể nhìn thấy giống nhau vẫn tồn tại.

Thủ thuật unescape(encodeURIComponent()) cũ và tại sao nó là một bản hack — nó thực hiện những gì và tại sao nó không được khuyến khích

Một cách giải quyết lịch sử là btoa(unescape(encodeURIComponent(text))). mã hóaURIComponent phần trăm mã hóa UTF-8 và unescape đóng gói lại phần trăm bộ ba dưới dạng đơn vị mã đơn, nhưng unescape không được dùng nữa, khó đọc và lúng túng khi sử dụng các đại diện đơn độc không đúng định dạng. Nó làm cho chuyển đổi trông giống như đang xử lý URL ngay cả khi không tồn tại URL. TextEncode nêu rõ ranh giới dự định: văn bản trở thành byte một lần và Base64 chỉ hoạt động sau đó.

Giải mã ở phía bên kia - ghép nối atob với TextDecoding để chuyến đi khứ hồi không bị mất

Sau atob, đừng gọi decodeURIComponent trên các byte nhị phân tùy ý và hy vọng chúng trở thành văn bản. Chuyển đổi mã ký tự thành Uint8Array và chuyển nó qua TextDecoding. Trong ví dụ về quán cà phê 😀, kết quả là chuỗi UTF-8 10 byte ban đầu, sau đó là chuỗi gốc. Nếu Base64 giải mã thành byte hình ảnh hoặc tệp nén thì nó có thể không đại diện cho văn bản UTF-8 hợp lệ nào cả; ToolAcre báo cáo rằng thay vì giả vờ dữ liệu nhị phân là văn xuôi có thể đọc được.

Điều này không bao gồm những gì - mã hóa tệp và blob nhị phân, các biến thể base64url và truyền phát đầu vào lớn

Giải thích này liên quan đến văn bản được mã hóa dưới dạng UTF-8. Tệp và Blob Base64, Base64url cho các phân đoạn JWT và mã hóa gia tăng dữ liệu nhiều gigabyte có các giao diện hoặc nhu cầu bộ nhớ khác nhau. Base64 cũng không mã hóa mã thông báo: bất kỳ ai nắm giữ nó đều có thể giải mã các byte. Bộ giải mã có thể chấp nhận phần đệm và khoảng trắng bị thiếu phổ biến, nhưng khả năng tương tác vẫn phụ thuộc vào việc biết tải trọng là văn bản hay dữ liệu nhị phân tùy ý.

Bài học rút ra: mã hóa byte chứ không phải chuỗi và kiểm tra hành trình khứ hồi — cách bộ mã hóa và giải mã Base64 thực hiện bước UTF-8 cho bạn để dấu, CJK và biểu tượng cảm xúc tồn tại

Mã hóa byte chứ không phải chuỗi JavaScript thô, sau đó kiểm tra chuyến đi khứ hồi. Bộ mã hóa và giải mã Base64 thực hiện các bước TextEncode và TextDecoding cho bạn trong khi vẫn giữ văn bản được dán trong trình duyệt. RFC 4648 chỉ định bảng chữ cái và phần đệm; UTF-8 cung cấp hợp đồng ký tự theo byte riêng biệt. Việc trộn lẫn hai lớp đó là gốc rễ của cả InvalidCharacterError và lỗi Latin-1 thầm lặng.