Base91 エンコード / デコード
仕組み:
入力はバイト列に変換され、13 ビットごとのグループにパックされて各 2 文字になります。短い形式が曖昧になる箇所だけ 14 ビットグループになります。
入力:
仕組み:
空白は無視され、各文字はこのページの下の方に表示されたアルファベットで検索されます。未知の文字は位置付きで報告されます。
出力形式:
入力欄で Ctrl+Enter を押すと現在のモードを実行します。
エンコードまたはデコードを選んで操作ボタンをクリックしてください。セルフテストは 130 回のエンコード/デコード往復を実行し、ここに件数を報告します。
アルファベット、全文字を印字: Base91 には標準化団体がなく、アルファベットは実装間で同一である保証がありません。このページはリファレンス実装のアルファベットを使い、以下のすべての値は表に載っている正確に 91 文字で生成しています。
緑のセルは HTML テキストや URL クエリーに安全に置ける文字、オレンジはエスケープまたはパーセントエンコードが必要な文字です(表の下の注記を参照)。
緑のセルは HTML テキストや URL クエリに安全に置ける文字、オレンジのセルはエスケープまたはパーセントエンコードが必要な文字です(表の下の注記を参照)。
Base91 とは何か?
Base91 は、任意のバイトを表示可能 ASCII 文字だけで書く方法です。Base64 と同じ仕事をしますが、1 文字あたりより多くのビットを詰め込みます。入力を 6 ビットグループに切ってグループごとに 1 文字を出力する代わりに、13 ビット以上溜まるまでビットを集め、それら 13(または 14)ビットの値を表す2 文字を出力します。
91 文字のアルファベットからの 2 文字は 91 × 91 = 8281 通りの値を表せ、213 = 8192 なので、2 文字は常に 13 ビットの余地を持ちます — 89 値のおまけつき。これがトリックのすべてです:2 文字あたり 13 ビットは 1 文字あたり 6.5 ビットで、Base64 の 6 に対し、オーバーヘッドは 33% ではなく約 23% になります。
30 秒版:test は fPNKd に、Hello, World! は >OwJh>}AQ;r@@Y?F になります。デコードは正確な逆で、同じ 91 文字のアルファベットを必要とします — 異なるアルファベットは同じバイトから異なる出力を生みます。
13 と 14 ビットの由来
91 × 91 = 8281 値を文字ペアで表せます。これは 213 = 8192 より多く、214 = 16384 より少ない。だから文字ペアは常に 13 ビットを運べ、ときに 14 ビットを運べます。エンコーダーはまず 13 ビットを試します:13 ビット値が 88 より大きければその値を 2 文字で出力し、そうでなければ 14 ビット目を取って、結果の 14 ビット値を出力します。
88 という境界は任意ではありません。2 文字が表せる最大値は 90 + 91 × 90 = 8280 で、8192 + 89 = 8281 はすでにそれを超えています。だから 14 ビットグループの下位 13 ビット窓が 89 以上になることは決してなく、デコーダーは値そのものだけを見て 2 つの場合を区別できます:
| デコーダーが見るもの | 消費ビット | 理由 |
| value & 8191 が 89〜8191 | 13 ビット | 89 以上の値は 13 ビット分岐からしか来られません。そんなに高い下位 13 ビット窓を持つ 14 ビットグループは少なくとも 8281 である必要があり、どんな文字ペアもそれを表せないからです。 |
| value & 8191 が 0〜88 | 14 ビット | エンコーダーは 13 ビット読み取りが 88 以下のときだけ 14 ビットにフォールバックするので、この分岐はフォールバック以外の何ものでもありません。 |
末尾に残ったもの — 1〜13 ビット — は 1 文字として出力され、残りが実際に 7 ビット超を必要とする場合は 2 文字目が付きます。だからエンコード長は 2 文字刻みで増え、ときどき奇数で終わります。
アルファベットと、除外される 3 文字
表示可能 ASCII は !(0x21)から ~(0x7E)まで 94 文字あります。Base91 はそのうち 91 文字を使い、除外される 3 つはハイフン -、アポストロフィ '、バックスラッシュ \ です。英字・数字・ほぼすべての句読点が、上の表に示す順序でちょうど 1 回ずつアルファベットに含まれ、92〜94 番目の表示可能文字は単にアドレス不可能です。
アルファベットは固定順序なので、値に対応する文字は数式ではなく検索です。アルファベットの順序が異なる 2 つの実装は、どちらも「Base91」でありながら互いの出力を読めません。これが紛らわしい結果の最大の発生源です。このページはアルファベットを掲載しているので、出力を常にそれまで遡れます。
他の表示可能エンコーディングとの比較
| エンコーディング | 1 文字あたりビット | 入力に対するサイズ | 備考 |
| Base16(16 進) | 4 | 200% | 1 バイト 2 文字。自明に読め、検索表が不要。 |
| Base32 | 5 | 160% | 大文字小文字を区別せず口述にも安全だが、この群では最も無駄が多い。 |
| Base58 | ~5.86 | ~137% | 密度ではなくアドレス用に選ばれた:紛らわしい文字を避けている。 |
| Base64 | 6 | 133% | あらゆる場所のデフォルト:3 バイト 4 文字。最後の文字の未使用 6 ビットが無駄になる。 |
| Ascii85 / Base85 | 6.4 | 125% | 4 バイト 5 文字。検索表不要だが 85 で除算する — Ascii85 コンバーターを参照。 |
| Base91 | ~6.5 | ~123% | この群で最密:2 文字 13 ビット。随所の 14 ビットグループが代償。 |
パーセンテージは各エンコーディングの漸近コスト(丸め)。実際の 92 バイト入力での実測文字数はこのページの上の表にあります。Base91 は表示可能 ASCII で達成できるほぼ最良です:1 文字 7 ビットは 128 個の異なる文字を意味し、表示可能範囲はそれを提供できません。
Base91 が「ではない」もの
- 標準ではない。RFC はありません。リファレンス実装は Joachim Henke による basE91 0.6.0(BSD 3 条項ライセンス)で、"Base91" はこのものでないアルファベットにも使われる名前です。
- 暗号化ではない。各文字は入力ビットの素直な再成形であり、アルファベットを持つ誰でも一晩で…ではなく一パスで元に戻せます。
- URL セーフではない。アルファベットは
#、%、&、/、?、" を含み、これらはすべて URL で意味が変わるため、Base91 出力はクエリ文字列に入れる前にパーセントエンコードが必要です。
- HTML セーフではない。
<、>、&、" も含むため、マークアップに入れる Base91 文字列はHTML エンティティコンバーターでエスケープする必要があります。
- 固定長ではない。出力長はバイト数だけでなくビットパターンにも依存するため、同じサイズの 2 つの入力が 1 文字違う出力になりえます。
実際に効く落とし穴
- このページのアルファベットはリファレンス版。他のツールが同じ入力で異なる出力を出す場合、どちらかが壊れていると決めつける前にアルファベットを比較してください。91 文字が同じ順序で並んでいなければなりません。
- 1 文字の誤りが末尾全体を変えうる。グループ境界はそれ以前の値で決まるため、文字列の早い位置の編集は以降すべてをずらし、末尾は最終グループの余りビットだけで復号されます。
- 奇数の出力長は正常。文字列が途中で切れたことを意味しません。最終グループは、余り値が 7 ビット以下に収まるとき 1 文字を出力します。
- 公開されている例は、タイプしていない改行を運んでいることがある。行末を追加するシェルコマンドが、有名な Base91 値がここの同じテキストより 1 文字長い一般的な理由です:
echo "Hello, World!" はエンコーダーに 14 バイトを渡して >OwJh>}AQ;r@@Y?FF を出力し、テキストのみの 13 バイトは >OwJh>}AQ;r@@Y?F を出力します。どちらも正しく、バイト数が違うだけです。出力ボックスの下のカウントが、どちらを持っているかを示します。
- バイナリデータをテキストとしてデコードしても動かない。復号されたバイトが有効な UTF-8 でない場合、表示すべきまともなテキストがありません。それが 16 進出力モードの用途です。
クイック回答
「このページの値が他の Base91 ツールと 1 文字違うのはなぜ?」
ほぼ常にアルファベットの違いです。二番目に多い原因は、13 ビット分岐だけを使い 14 ビットフォールバックを一切使わないツールです。その亜種はコードは小さくなりますが、ここで使っているリファレンスアルゴリズムと異なる出力を生成します。
1 つだけ、バイト数を数えれば決まる厳密なケースがあり、最もよく引用される例を説明します:末尾の改行です。公表されているベクトルの多くはシェルコマンドで生成され、シェルが行末の改行を追加します。Hello, World! の 13 バイトはここでは 16 文字になり、改行を伴う 14 バイトの Hello, World! は 17 文字の >OwJh>}AQ;r@@Y?FF になります。どちらの値もデコード欄に貼り付けてください:このページはバイト数を報告するので、2 つの読み方を議論するのではなく区別できます。サンプルボタンは、使用している読み手に合った方を読み込み、エンコード/デコードの切り替えと 入力形式 / 出力形式 の選択に従います:テキスト読み手は 16 文字の値を、16 進の読み手は末尾に 0A バイトが見える 17 文字の値を受け取り、エンコーダーは Base91 文字列ではなくエンコードするテキストを受け取ります。
「Base91 は Base64 より小さい?」
はい、エンコード後サイズの約 8% 小さくなります:1 文字 6 ビットに対し 2 文字 13 ビット。92 バイトのテキストで、Base64 は 124 文字、Base91 は 114 文字を出力します。
「Base64 デコーダーで復号できる?逆は?」
いいえ。アルファベットは英字と数字で重なるため、Base64 デコーダーは Base91 文字列を「有効」として受け入れ、黙ってゴミを生成します。2 つが一致するのは方式の輪郭だけです。
「出力は Base64 のようにパディングで終わる?」
いいえ。Base91 にはパディング文字がまったくありません:末尾の余りビットは最終グループとして出力されるため、追加も除去も何もいりません。
「このページの結果が正しいとどうやってわかる?」
セルフテスト 0〜64 バイトを押してください。13/14 ビット分割が変わるすべての長さをカバーする 130 個のバイトパターンをエンコード・デコードし、戻ってきたバイトと入力バイトを比較します。サンプルボタンのベクトルはさらに、このサイトのテストツール用に書かれた第二実装とも相互照合されています。
規格とクレジット
このページは Joachim Henke による basE91 リファレンス実装(バージョン 0.6.0、BSD 3 条項ライセンス)のアルゴリズムを、上に表示したアルファベットとともに実装しています。デコードはリファレンスツールと同様に空白を受け入れて無視します。
ページの文章はこのサイトのために書かれたもので、アルゴリズムはどこからもコピーされていません。サンプルボタンの値は、リファレンスパッケージ付属の唯一の例(「リファレンス例」と表示)と、このサイトのテストツールに保管されている独立した第二実装が生成した値(「相互照合」と表示)です。