Base91 là gì?
Base91 là cách viết các byte tùy ý chỉ bằng ký tự ASCII in được, cùng việc mà Base64 làm, nhưng nó nhét nhiều bit hơn vào mỗi ký tự. Thay vì cắt đầu vào thành các nhóm 6 bit và in một ký tự cho mỗi nhóm, nó gom bit cho đến khi có ít nhất 13 bit, rồi in hai ký tự cùng biểu thị giá trị của 13 (hoặc 14) bit đó.
Hai ký tự trong bảng chữ cái 91 ký tự có thể biểu thị 91 × 91 = 8281 giá trị khác nhau, và 213 = 8192, nên hai ký tự luôn đủ chỗ cho 13 bit — còn dư 89 giá trị. Đó là toàn bộ mẹo: 13 bit cho mỗi 2 ký tự tương đương 6.5 bit mỗi ký tự, so với 6 bit của Base64, và giảm chi phí khoảng 23% thay vì 33%.
Phiên bản 30 giây: test thành fPNKd, và Hello, World! thành >OwJh>}AQ;r@@Y?F. Giải mã là phép đảo ngược chính xác, và cần đúng bảng chữ cái 91 ký tự này — một bảng chữ cái khác sẽ cho đầu ra khác từ cùng các byte.
Số 13 và 14 bit đến từ đâu
91 × 91 = 8281 giá trị có thể được biểu thị bằng một cặp ký tự, nhiều hơn 213 = 8192 nhưng ít hơn 214 = 16384. Vì vậy một cặp ký tự luôn có thể mang 13 bit, và đôi khi mang 14 bit. Bộ mã hóa thử 13 bit trước: nếu giá trị 13 bit lớn hơn 88 thì nó in giá trị đó thành hai ký tự; nếu không thì nó lấy thêm một bit thứ 14 và in giá trị 14 bit thu được.
Ngưỡng 88 không phải là ngẫu nhiên. Giá trị lớn nhất mà hai ký tự có thể biểu thị là 90 + 91 × 90 = 8280, và 8192 + 89 = 8281 đã vượt quá nó. Vì vậy không nhóm 14 bit nào có cửa sổ 13 bit thấp từ 89 trở lên, nghĩa là bộ giải mã có thể phân biệt hai trường hợp chỉ bằng cách nhìn vào chính giá trị:
| Bộ giải mã thấy gì | Số bit đã tiêu thụ | Vì sao |
| value & 8191 là 89 đến 8191 | 13 bit | Giá trị từ 89 trở lên chỉ có thể đến từ nhánh 13 bit, vì một nhóm 14 bit có cửa sổ 13 bit thấp cao như vậy sẽ phải ít nhất là 8281 — mà không cặp ký tự nào có thể biểu thị. |
| value & 8191 là 0 đến 88 | 14 bit | Bộ mã hóa chỉ dự phòng sang 14 bit khi cách đọc 13 bit là 88 hoặc nhỏ hơn, nên nhánh này chỉ là phương án dự phòng và không có gì khác. |
Phần còn lại ở cuối — từ 1 đến 13 bit — được in thành một ký tự, cộng thêm ký tự thứ hai khi phần còn lại thực sự cần hơn 7 bit. Đó là lý do độ dài mã hóa tăng theo từng bước hai ký tự và đôi khi kết thúc ở một số lẻ.
Bảng chữ cái, và ba ký tự nó bỏ đi
ASCII in được có 94 ký tự, từ ! (0x21) đến ~ (0x7E). Base91 dùng 91 trong số đó, và ba ký tự bị bỏ là dấu gạch nối -, dấu nháy đơn ' và dấu gạch chéo ngược \. Chữ cái, chữ số và hầu hết dấu câu đều có trong bảng chữ cái đúng một lần, theo thứ tự trong bảng ở trên; ký tự in được thứ 92 đến 94 đơn giản là không thể được đánh địa chỉ.
Vì bảng chữ cái có thứ tự cố định, ký tự cho một giá trị là một phép tra cứu chứ không phải công thức. Hai triển khai sắp xếp bảng chữ cái khác nhau vẫn đều gọi là "Base91" nhưng không đọc được đầu ra của nhau, và đây là nguồn gây kết quả khó hiểu phổ biến nhất. Trang này in bảng chữ cái của mình ra để đầu ra luôn truy ngược được về nó.
Base91 so với các mã hóa in được khác
| Mã hóa | Bit mỗi ký tự | Kích thước so với đầu vào | Ghi chú |
| Base16 (hex) | 4 | 200% | Hai ký tự cho mỗi byte, đọc được ngay, không cần tra bảng chữ cái. |
| Base32 | 5 | 160% | Không phân biệt hoa thường và dễ đọc khi đọc chính tả, nhưng là mã lãng phí nhất trong nhóm. |
| Base58 | ~5.86 | ~137% | Được chọn cho địa chỉ, không phải vì mật độ: nó tránh các ký tự dễ nhầm. |
| Base64 | 6 | 133% | Mặc định ở khắp nơi: 4 ký tự cho 3 byte, với 6 bit không dùng của ký tự cuối bị lãng phí. |
| Ascii85 / Base85 | 6.4 | 125% | 5 ký tự cho 4 byte, không cần bảng tra, nhưng chia cho 85 — xem Công cụ chuyển Ascii85. |
| Base91 | ~6.5 | ~123% | Dày đặc nhất trong các mã này: 13 bit cho mỗi 2 ký tự, đổi lại thỉnh thoảng có nhóm 14 bit. |
Các tỷ lệ phần trăm là chi phí tiệm cận của mỗi mã hóa, đã làm tròn; số ký tự đo được cho một đầu vào 92 byte thực tế nằm trong bảng phía trên trang này. Base91 gần với mức tốt nhất mà mọi mã hóa có thể đạt được với ASCII in được: 7 bit mỗi ký tự sẽ cần 128 ký tự khác nhau, mà dải in được không thể cung cấp.
Base91 không phải là gì
- Không phải tiêu chuẩn. Không có RFC. Triển khai tham chiếu là basE91 0.6.0 của Joachim Henke, phát hành theo giấy phép BSD 3 điều khoản; "Base91" cũng được dùng cho những bảng chữ cái khác không phải bảng này.
- Không phải mã hóa. Mỗi ký tự chỉ là một phép định hình lại trực tiếp các bit đầu vào, và ai có bảng chữ cái cũng có thể đảo ngược trong một lượt.
- Không an toàn cho URL. Bảng chữ cái chứa
#, %, &, /, ? và ", tất cả đều đổi nghĩa trong URL, nên đầu ra Base91 phải được mã hóa phần trăm trước khi đưa vào chuỗi truy vấn. - Không an toàn cho HTML. Nó cũng chứa
<, >, & và ", nên chuỗi Base91 đặt vào markup phải được escape bằng Công cụ chuyển thực thể HTML. - Không có độ dài cố định. Độ dài đầu ra phụ thuộc vào mẫu bit, không chỉ số byte, nên hai đầu vào cùng kích thước có thể in lệch nhau một ký tự.
Những cái bẫy thực sự gây hại
- Bảng chữ cái trong trang này là bảng tham chiếu. Nếu công cụ khác cho đầu ra khác với cùng đầu vào, hãy so sánh bảng chữ cái của nó trước khi cho rằng một bên bị lỗi. 91 ký tự phải xuất hiện theo cùng thứ tự.
- Một ký tự sai có thể làm thay đổi cả phần đuôi. Ranh giới nhóm được quyết định bởi các giá trị đứng trước, nên một chỉnh sửa sớm trong chuỗi làm dịch chuyển mọi thứ sau nó, và phần đuôi chỉ được giải mã bằng các bit thừa của nhóm cuối.
- Độ dài đầu ra lẻ là bình thường. Điều đó không có nghĩa là chuỗi bị cắt ngắn; nhóm cuối in một ký tự khi giá trị thừa của nó vừa trong 7 bit trở xuống.
- Một ví dụ đã công bố có thể chứa một ký tự xuống dòng mà bạn không hề gõ. Lệnh shell thêm ký tự kết thúc dòng là lý do thường gặp nhất khiến một giá trị Base91 nổi tiếng dài hơn văn bản tương ứng một ký tự khi mã hóa ở đây:
echo "Hello, World!" đưa cho bộ mã hóa 14 byte và in ra >OwJh>}AQ;r@@Y?FF, trong khi 13 byte của riêng văn bản in ra >OwJh>}AQ;r@@Y?F. Cả hai đều đúng, ứng với số byte khác nhau, và số đếm dưới ô đầu ra cho biết bạn đang giữ cái nào. - Giải mã dữ liệu nhị phân thành văn bản sẽ không hoạt động. Nếu các byte đã giải mã không phải UTF-8 hợp lệ thì không có văn bản hợp lý nào để hiển thị, và đó là lúc chế độ đầu ra thập lục phân được dùng.
Trả lời nhanh
“Vì sao trang này hiển thị một giá trị khác một ký tự so với công cụ Base91 khác?”
Hầu như luôn là do một bảng chữ cái khác. Nguyên nhân phổ biến thứ hai là một công cụ chỉ dùng nhánh 13 bit mà không bao giờ dùng phương án dự phòng 14 bit; biến thể này gọn hơn trong mã nhưng cho đầu ra khác với thuật toán tham chiếu được dùng ở đây.
Cũng có một trường hợp chính xác có thể xác định bằng cách đếm byte, và nó giải thích ví dụ được trích dẫn rộng rãi nhất: một ký tự xuống dòng ở cuối. Hầu hết các vector đã công bố được tạo bởi một lệnh shell, và shell thêm ký tự kết thúc dòng. 13 byte của Hello, World! in ra 16 ký tự ở đây, còn 14 byte của Hello, World! theo sau bởi một ký tự xuống dòng in ra 17 ký tự >OwJh>}AQ;r@@Y?FF. Dán một trong hai giá trị vào Giải mã: trang này báo số byte, nên có thể phân biệt hai cách đọc thay vì phải tranh cãi. Nút Mẫu tải giá trị phù hợp với người đọc bạn đang dùng, và nó theo công tắc Mã hóa / Giải mã cùng bộ chọn Đầu vào là / Đầu ra dạng: người đọc văn bản nhận giá trị 16 ký tự, người đọc thập lục phân nhận giá trị 17 ký tự với byte 0A cuối cùng hiện rõ, còn bộ mã hóa nhận văn bản cần mã hóa thay vì một chuỗi Base91.
“Base91 có nhỏ hơn Base64 không?”
Có, khoảng 8% về kích thước mã hóa: 13 bit cho mỗi 2 ký tự so với 6 bit cho mỗi ký tự. Với 92 byte văn bản, Base64 in 124 ký tự còn Base91 in 114.
“Tôi có thể giải mã cái này bằng bộ giải mã Base64, hoặc ngược lại không?”
Không. Hai bảng chữ cái trùng nhau ở chữ cái và chữ số, nên bộ giải mã Base64 sẽ chấp nhận một chuỗi Base91 như các ký tự "hợp lệ" và cho ra rác mà không báo lỗi. Hai mã chỉ thống nhất ở hình dạng của sơ đồ.
“Đầu ra có kết thúc bằng phần đệm như Base64 không?”
Không. Base91 không có ký tự đệm nào: các bit thừa ở cuối được in thành nhóm cuối cùng, nên không cần thêm hay bớt gì.
“Làm sao tôi biết kết quả trên trang này là đúng?”
Nhấn Tự kiểm tra 0 đến 64 byte. Công cụ này mã hóa và giải mã 130 mẫu byte bao phủ mọi độ dài mà chỗ tách 13 và 14 bit thay đổi, rồi so sánh các byte trả về với các byte đã đưa vào. Các vector trên nút Mẫu còn được đối chiếu với một triển khai thứ hai được viết cho bộ công cụ kiểm thử của trang này.
Tiêu chuẩn và ghi công
Trang này triển khai thuật toán của bản tham chiếu basE91 (phiên bản 0.6.0) của Joachim Henke, phân phối theo giấy phép BSD 3 điều khoản, với bảng chữ cái đã in ở trên. Giải mã chấp nhận và bỏ qua khoảng trắng, giống như công cụ tham chiếu.
Nội dung trang này được viết riêng cho trang web; thuật toán không được sao chép từ đâu cả. Các giá trị của nút Mẫu là ví dụ duy nhất đi kèm gói tham chiếu (được đánh dấu "ví dụ tham chiếu") cộng với các giá trị do một triển khai thứ hai, độc lập, lưu trong bộ công cụ kiểm thử của trang này tạo ra (được đánh dấu "đối chiếu").