base64 ウェブセーフ

Base64

[5] Base64 は、オクテット列を64種類の英数字などに転写する符号化方式の一種です。

[135] 一般に base 6464進数を意味します。特に大文字Base64 と書いた場合や、インターネットで言われる場合には、 MIMEBase64 を指します。

[196] 元々インターネットメールバイナリーデータを転送するための仕組みとして考案されました。 文字コードの異なる様々なシステム間で転送される電子メールでは、 任意のバイナリーデータを転送することができなかったため、 限られたASCII文字符号化する手段が必要でした。 その後徐々に適用範囲が拡大され多種多様な目的で使われるようになりました。

[58] いくつかのバリエーションがあり、どれを使うべきなのか注意が必要です。

仕様書

符号化方式の概要

[27] オクテット値3つ (8ビット×3 = 24ビット) を4文字 (6ビット×4) で表現します。ですからデータ量は3分の4倍、33%増加になります。

64文字 (と、特殊用途に使われる =) は、 ISO/IEC 646の版で全て共通に存在し、しかも EBCDIC の全ての版で使える文字から選ばれたそうです。

[116] Table 1: The Base 64 Alphabet
     Value Encoding  Value Encoding  Value Encoding  Value Encoding
         0 A            17 R            34 i            51 z
         1 B            18 S            35 j            52 0
         2 C            19 T            36 k            53 1
         3 D            20 U            37 l            54 2
         4 E            21 V            38 m            55 3
         5 F            22 W            39 n            56 4
         6 G            23 X            40 o            57 5
         7 H            24 Y            41 p            58 6
         8 I            25 Z            42 q            59 7
         9 J            26 a            43 r            60 8
        10 K            27 b            44 s            61 9
        11 L            28 c            45 t            62 +
        12 M            29 d            46 u            63 /
        13 N            30 e            47 v
        14 O            31 f            48 w         (pad) =
        15 P            32 g            49 x
        16 Q            33 h            50 y

[28] Base64 は6ビット単位になりますが、オクテット列の長さと必ずしも 一致する (6と8の公倍数の長さになる) とは限らないので、 = で埋めて調節します。この結果、 Base64 data は必ず 4の整数倍の長さになります。

符号化

[136] Base64 による符号化は、 任意のバイト列Base64ASCII文字列へと変換する処理です。

[89] forgiving-base64 encode は、バイト列データを次のようにします >>86

  1. [90] データRFC 4648 第4章 Base64 を適用した結果を返します。

[117] RFC 4648 第4章 Base64 は、 バイト列データを次のようにします。

  1. [118] を、空バイト列に設定します。
  2. [202] 結果を、空文字列に設定します。
  3. [119] データの各バイトバイトについて、順に、
    1. [120] の末尾に、バイトを追加します。
    2. [122] 長さ3 の場合、
      1. [198] ビット列0を、 [ 0 ] の上位6ビットに設定します。
      2. [199] ビット列1を、 [ 0 ] の下位2ビットを上位2ビット、 [ 1 ] の上位4ビットを下位4ビットとするビット列に設定します。
      3. [200] ビット列2を、 [ 1 ] の下位4ビットを上位4ビット、 [ 2 ] の上位2ビットを下位2ビットとするビット列に設定します。
      4. [201] ビット列3を、 [ 2 ] の下位6ビットに設定します。
      5. [216] 結果の末尾に、 ビット列0ビット列1ビット列2ビット列3のそれぞれが The Base 64 Alphabet の第1列の値である行の第2列の値を順に追加します。
      6. [215] を、空バイト列に設定します。
  4. [204] 長さ2 の場合、
    1. [205] ビット列0を、 [ 0 ] の上位6ビットに設定します。
    2. [206] ビット列1を、 [ 0 ] の下位2ビットを上位2ビット、 [ 1 ] の上位4ビットを下位4ビットとするビット列に設定します。
    3. [207] ビット列2を、 [ 1 ] の下位4ビットを上位4ビット、 0 を下位2ビットとするビット列に設定します。
    4. [208] ビット列3を、 (pad) に設定します。
    5. [217] 結果の末尾に、 ビット列0ビット列1ビット列2ビット列3のそれぞれが The Base 64 Alphabet の第1列の値である行の第2列の値を順に追加します。
  5. [209] 長さ1 の場合、
    1. [210] ビット列0を、 [ 0 ] の上位6ビットに設定します。
    2. [211] ビット列1を、 [ 0 ] の下位2ビットを上位2ビット、 0 を下位4ビットとするビット列に設定します。
    3. [212] ビット列2を、 (pad) に設定します。
    4. [213] ビット列3を、 (pad) に設定します。
    5. [203] 結果の末尾に、 ビット列0ビット列1ビット列2ビット列3のそれぞれが The Base 64 Alphabet の第1列の値である行の第2列の値を順に追加します。
  6. [214] 結果を返します。

[123] 次の文脈で用いられます。

[124] forgiving-base64 encode応用

復号

[137] Base64 による復号は、 Base64ASCII文字列をその表すバイト列へと変換する処理です。

[91] forgiving-base64 decode は、文字列データを次のようにします >>86

  1. [92] データからASCII空白をすべて削除します。
  2. [93] データ長さ % 40 の場合、
    1. [94] データの末尾が === なら、これを削除します。
  3. [95] データ長さ % 41 の場合、
    1. [96] 失敗を返し、ここで停止します。
  4. [97] データ+/ASCII英数字のいずれでもない符号位置が含まれる場合、
    1. [98] 失敗を返し、ここで停止します。
  5. [99] 出力を、新しい空バイト列に設定します。
  6. [100] バッファーを、新しい空ビット列に設定します。
  7. [101] データに含まれる符号位置符号位置について、順に、
    1. [102] n を、RFC 4648 Table 1: The Base 64 Alphabet の第2列が符号位置であるの第1列の値に設定します。
    2. [103] バッファーの末尾に、n と等しく6ビットで大エンディアンビット列を追加します。
    3. [104] バッファー長さが24ビットの場合、
      1. [105] バッファーを3桁の大エンディアン8ビット整数と解釈したものを、 出力の末尾に順に追加します。
      2. [106] バッファーを、空に設定します。
  8. [107] バッファー長さが12ビットの場合、
    1. [108] バッファーの先頭8ビットを 1桁の大エンディアン8ビット整数と解釈したものを、 出力の末尾に順に追加します。
  9. [109] バッファー長さが18ビットの場合、
    1. [110] バッファーの先頭16ビットを 2桁の大エンディアン8ビット整数と解釈したものを、 出力の末尾に順に追加します。
  10. [111] 出力を返します。

[125] 次の文脈で用いられます。

[126] forgiving-base64 decode応用

[225] 仕様書forgiving-base64 decode は入力が文字列として定義されています。 data: URL処理器では入力がバイト列となるため、 同型復号を通しています。

Base64 の仕様書とバリエーション

[138]Base64」と呼ばれているものは、 注意して観察すると色々なバリエーションがあることがわかります。 Base64 は有用で様々な用途に活用されてきたのですが、 その過程で仕様書の規定の部分をコピペしたり、 用途依存の細かい改変を加えたりされたため、 単一の定義と言えるものが存在しなくなってしまいました。

[23] どの仕様書の定義を参照するかという政治的な問題の他に、 技術的に様々な違いがありますが、 主として次のような観点で比較できます。

電子メールの Base64

[145] Base64 は最初に PEM で導入されました。 PEM は特別な名前を与えず、単に「printable encoding」 (印字可能符号化) と呼んでいました。 >>142, >>143, >>144

[146] 字母詰めについては既に後の時代と同じ規定となっていました。 符号化後の最終行以外の各行は、64文字としなければならないとされていました。 誤り処理の明確な規定はありませんでした。

[147] 字母は、当時使われていた ASCIIEBCDIC文字コードとするシステムで問題なく扱えるものが選ばれていました。 行長制限は、SMTP の制約に由来するものでした。

[148] PEMBase64 は、あくまで PEM のプロトコルの一部を構成するもので、 汎用的な利用を想定したものではありませんでした。 Base64字母に加え、 PEM での利用上特別な意味を持った区切りの文字 *字母の1つとして挙げられていました。

[166] 符号化の方法は規定されていましたが、復号の方法は明確には定められていませんでした。

[157] PEM Base64応用

[25] MIME は、 PEM から派生して独自の Base64 を規定しました >>149, >>150, >>43Base64 という名称はここで与えられました。

[151] 基本的には PEM と同内容ですが、いくつかの違いがありました。

[152] MIME では特別な意味を持たない *字母に含まれませんでした。

[153] 行長制限は、76文字以下とされました。

[154] 字母以外は無視するべきことと定められ、 字母改行空白以外は誤りと考えられるため警告を出したり、 場合によっては拒絶するのもよいとされました。

[155] RFC 1521==== のようなあり得ない詰めを無視することを定めていましたが、 改訂版の RFC 2045 ではなぜか削除されました。

[156] このように PEM とは違って誤り処理が定められたことは注目に値しますが、 起こり得るすべての誤りケースをカバーできてはいませんでした。

[158] MIME Base64応用

[170] Content-MD5: を定める RFC 1864 は「base64」としか言っておらず、 どこで規定される何を指すのかは曖昧ですが、 MIME の追加機能ですから、 MIME の定義と解釈するのが自然でしょう。 ヘッダー値として使うため改行を自由には挿入できないはずですが、 符号化される値は十分短いため、実際には問題とはなりません。

[281] RFC 2065RFC 1521 から Base64 部分をコピペして組み込んでいました。 >>280

[827] 基本認証credentials では MIMERFC 1521RFC 2045Base64 から行長制限を撤廃したものと規定されていました >>826, >>183, >>828。 厳密に読めば制限が撤廃されたのは良いとして、改行が認められるのかは不明でした。 この点は後の改訂で明確化されました (>>185)。

[171] data: を定める RFC 2397 は「base64」としか言っておらず、 どこで規定される何を指すのかは曖昧ですが、参考文献として示された MIMERFC 2045 だけが文脈から推測できる候補でした。 しかし行長制限の扱いと URL としての構文の矛盾など、 著者の意図を断言するのは難しい状態でした。 (出版から20年後にようやく Fetch Standard により明確化されることになります。)

[224] OAuth 1.0HMAC-SHA1RSA-SHA1RFC 2045Base64 を採用していました。 符号化される値は十分短いため、 行長制限に達することはありません。

[282] rfc2060, https://datatracker.ietf.org/doc/html/rfc2060#page-66

ABNF 構文定義のみ


[74] PGPメッセージ交換形式もまた、独自に Base64 を規定しており、 Radix-64 と呼んでいます >>159, >>160, >>161

[162] RFC 1991 の規定は曖昧なものでした。

[163] RFC 2440RFC 4880 は、 MIMERFC 2045 と同内容の Base64 を規定しています。歴史的経緯によるものか、 MIMEBase64 への言及は一切ありません。 しかし明らかに同じテキストを流用しています。 ですが全く同じではなく、解釈次第ではこちらの定義の方が厳密ともいえます。

[46] Radix-64応用

[274] RFC 2801 - Internet Open Trading Protocol - IOTP Version 1.0, , https://tools.ietf.org/html/rfc2801#page-52

[276] RFC 3252 - Binary Lexical Octet Ad-hoc Transport, , https://tools.ietf.org/html/rfc3252#section-2.1

This RFC REQUIRES the contents of the payload to be encoded in the base-64 encoding of RFC 2045 [RFC2045], but removes the requirement that the encoded output MUST be wrapped on 76-character lines.

[283] rfc3885, https://datatracker.ietf.org/doc/html/rfc3885#section-1

字母の ABNF 定義のみ。

IETF の Base64

[15] IETF はその後 Base64 (と Base32Base16) のみを定める RFC を発行しました >>6, >>24

[30] MIME 式の base64 と、 base64url (>>833) との2種類が定義されています。 両者は字母のみが異なっています。

[164] MIME 式のものは、 MIMEOpenPGP に由来するものですが、 いくつか異なる点もあります。

[165] 詰めは、原則として必須ですが、応用は省略可能と定めることができます。 しかし詰めが省略された場合にどう処理しなければならないかは規定されていません。

[167] RFC 3548 にはありませんでしたが、 RFC 4648 は、 詰めの前の字母の選択時に余ったビット0 としなければならないとしています。 そうでない場合、復号時に拒絶しても構わないとされています。

[168] 復号時に字母以外が含まれる場合、 原則として拒絶しなければならず応用はそれ以外の処理方法を定めても良い、とされています。 電子メールのように行長制限が必要な場合には改行を挿入することを選べますが、 基本的には改行は含めないことになっているのが MIME との最大の違いです。 同様に復号時に不正な詰めも無視すると定めても良いことになっています。

[169] これらの RFC でも、完全な復号の方法は定められていません。

[33] RFC 3548 MIMEBase64応用
[67] RFC 4648 MIMEBase64応用

[36] RFC 4287Atom 1.0 における atom:content では、 RFC 3548MIMEBase64 が使われています >>177。 ただし、前後に空白があっても良いこと、 改行U+000A とすることが定められています >>177。 この改行の定めが何を意味するかは不明瞭です。 RFC 3548 によれば応用が明確に認めない限り改行の挿入は認められませんが、 RFC 4287 が明確に認めているとは言えず、 しかしそうだとすると RFC 4287 の記述は理解不能となります。

[197] RFC 7468 は、 .pem ファイルの Base64RFC 4648MIMEBase64 としています。 ただし、生成時には最終行以外を64文字丁度とすることと定めています (これは PEM に由来する制約です)。 解釈時には空白を含む字母以外を無視することを認めています。 ABNF 構文上は詰めの省略が認められているようですが、 本文には明確な規定がなく、意図は不明です。 (ABNF 構文は通常、緩め、厳密の3種類が用意されています。)

[287] rfc3977, https://datatracker.ietf.org/doc/html/rfc3977#section-3.2.1

[288] rfc3977, https://datatracker.ietf.org/doc/html/rfc3977#page-98

xs:base64Binary

[63] XML Schemaデータ型 xs:base64Binary は、 MIMERFC 2045 の定義を参照しつつ、 独自の構文を規定しています >>172

[173] US-ASCII ベースの RFC 2045 と違って、 XML SchemaUnicode ベースとなっています。 (文字レベルで見れば実質的な違いはありません。)

[174] 本来の字母の他に XMLの空白が任意の位置に認められることになっています。 ただし XML Schema正規化を経た字句形の構文上は途中に U+0020 各1つのみの挿入が認められることになっています。 MIME とは違って行長制限はありません。

[176] 正準字句形では空白は認められないことになっています。

[175] 詰めは必須であり、詰めの前の字母の選択時に足りないビット0 で埋めなければならないことになっています。

Web Base64

[87] Web では、 エラー処理を含め正確なアルゴリズムとして符号化 (>>89) と復号 (>>91) を定義した forgiving base64 >>86 を用いています。

[88] 正常な入力のみに限ったとき、 RFC 4648 第4章の Base64 と等価です。

[112] 詰めは、必ず生成されますが、省略されても復号には成功します。 詰めの直前の字母の余分なビットは、無視されます。

[113] 空白は生成されませんが、無視されます。 字母空白以外が含まれる場合や、 不正な詰めが含まれる場合は、復号失敗します。

[114] Infra Standardforgiving base64Base64 の歴史上最も厳密な定義となっており、特に事情がない場合、これを採用するのが望ましいと思われます。

UTF-7 修正 Base64

[2] UTF-7 は、修正Base64 (Modified Base64) と称する変種を定義していました >>44, >>47

[178] MIMERFC 1521RFC 2045 を参照しつつ、 詰め= は使わないこととしていました。 復号時には、16ビット単位の列として解釈した時に余ったビットは捨てることとされていました。 余ったビット0 でないものは ill-formed であるとされていましたが、 それをどう処理するべきかは明記されていませんでした。

[179] UTF-7 では字母でない文字修正Base64部分の終わりとみなすことになっていました。 従って改行の挿入は認められていませんでしたし、字母以外の混入時の復号の処理も明確でした。 ただし改行を挿入しないため行長制限を超えてしまうデータが認められると明記はしていませんでした。


[7] IMAP修正UTF-7 は、 UTF-7修正Base64を更に改変し、 字母 / の代わりに , を使うとしています >>182, >>181

URL 安全 Base64

[833] modified Base64 for URL >>829 あるいは base64url と呼ばれる変種は、 URL で利用しやすくした Base64 の一種です。 Web 関係の分野でよく用いられるようになってきました。

[277] Base64 のバリエーションの中では、 MIME 式に次いで2番目に普及していると思われます。

[834] MIME 式の Base64base64url との違いは、 次の通りです。


[838] 出典としてはしばしば Wikipedia >>829 が参照されます。 そんなあやふやなものを参照して技術基盤として大丈夫なんだろうか、 と不安になりますが、案外よく参照されています。

[839] 公的な文書としては RFC (>>30) があり、ファイル名や URL で安全なものとして紹介されています。ただし RFC は原則として詰め = は省略できないとしており、一般的な実装とは異なっています。

[17] =URL では query などで特別な意味を持つことがあるので、 あまり安全ではありません。 RFC は原則を貫こうとするあまり、 一般的な実装が意図的に加えた改変を無視しているのです。
[22] 実際には -ファイル名の先頭に来るのは必ずしも安全とはいえません。 URL で安全と言うのに留めておけばいいのに、RFC は余計な説明を加えています。

[840] RFC は既存の利用例としてメーリング・リストの記事を参照していますが、 URL が変わってしまったのか、関係ない記事になっています。本来指すべきだったと思われる >>831>>832 によると、元々は Freenet で使われていたのを採用したようです。

[293] Google Apps Script標準ライブラリーbase64EncodeWebSafe, base64DecodeWebSafebase-64 web-safe encoded string なるものに対応しています。 >>292 これは詰め = ありの base64url のようです。

[294] しばしば JWT など詰めないところで使われてトラブルを起こしているようです。 HTTP 基本認証 (本来は元々の Base64 の系統) に使われている事例まであるようです。

[229] I-JSON は、 RFC 4648 base64url を使うべきとしています。 (JSON で通常の Base64 では不都合な理由はなく、敢えて base64url を選択した理由は不明です。)

[221] JSON-Base64 は、 RFC 4648URL安全Base64 を参照しつつも、 独自に定義しています。 Base64字母を置き換え、 = を削除したものとなっています >>220RFC を参照しているものの、 RFC が改変する前の本来の URL安全Base64 ということになります。

[234] RFC 7515, RFC 7522, RFC 7636 Base64url Encoding >>233, >>54, >>56 は、 RFC 4648 base64url詰めを禁止し、 空白その他の挿入も明示的に禁止しています。 また RFC 7515符号化復号の、 RFC 7636符号化の実装例も掲載しています。 (>>242 も参照)

[236] 結局 IETFプロトコルでも詰めのない base64url が主流にみえます。 敢えて世間一般と違うものを定義した RFC の意義は何だったのでしょうか。そして利用実態に反したまま改訂せずに放置している IETF の意図は何なのでしょうか。


[241] 復号の方法は厳密には規定されていません。

[242] RFC 7515 は 「Base64url-decode the encoded representation of (入力データ), following the restriction that no line breaks, whitespace, or other additional characters have been used.」 という表現を用いています >>240。 これが満たされないとき検証失敗することとなり、 緩い復号を用いないことを求めています。 ただし詰めの扱いは明言していません。

[243] RFC 7515復号のサンプルコード >>233 は、次のような挙動を示します。 ただ、あくまで実装例に過ぎず、復号方法の規定とは到底言えません。

  • [244] +/-_ とそれぞれ同義とみなされる
  • [245] 末尾の = はあってもなくても同義とみなされる
  • [246] 文字数を 4 で割って 1 となるなら、復号は失敗とする
  • [247] その他は通常の Base64 の方法による
[270] >>244>>242 の規定と矛盾します。

[278] 仕様書がこんな状態なので、実装は混乱していることが予想されます。 base64url データの送信者は、壊れたデータを送信しないよう、 慎重に実装することが望まれます。 base64url データを受信する実装を作る開発者は、 既成のライブラリーを流用するなら、 そのライブラリーの挙動を慎重に調査し、 不正な入力が与えられても適切に動作するよう、 注意が必要です。


[75] 他の Base64 の変種同様、字母を置き換えるだけなので簡単に実装できます。 両対応のライブラリーも珍しくありません。

[842] Perl標準モジュールである MIME::Base64 >>841 に実装されています。 Perl では今後はこちらが標準的な実装となっていくと思われます。 Wikipedia >>829 が出典とされています。

[844] >>843>>841 が実装される前によく用いられていました。 Python の実装に倣った >>843, >>845 としつつ、 Wikipedia >>829 も引用しています。

[849] Python の実装というのは >>848 でしょうが、こちらは >>841>>843 とは違って = を省略しません。 >>839 に従っている実装です。

[850] 最初からそうだったのか、それとも Perl の実装が派生した後に動作が変わったのかは不明です。
[851] なお、 Python の実装は >>835 の2文字を任意の文字に変更できるようですw

[279] MIME 式と一部の字母が違うだけなので、 字母を置き換えてから MIME 式で復号するような実装が蔓延っています。 簡単に実装できるのは結構ですが、 この方式だと MIMEBase64 の入力や、 MIMEBase64base64url の両方の字母が混在している入力まで復号できてしまいます。 そんな実装が混在している (かもしれない) という現状は、 相互運用性セキュリティーの問題の温床です。


[66] RFC 4648 base64url応用
[237] RFC 7515, RFC 7522, RFC 7636 base64url応用

[263] BASE64URL(OCTETS) のような仕様書上の表記法が使われています >>262, >>296, >>297

[235] いくつかの RFC は、バイナリーデータRFC として記述するための便宜上の方法として base64url を使っています。 RFC 4648 を引用しつつ、 RFC の制約上空白を挿入することとしています。 明記はされていませんが、詰めも省略されています。

[238] 表示用の base64url の事例

[266] Base64urlUInt は、 正整数または 0 の値について、 符号無し大エンディアン表現をオクテット列としたとき、 これを base64url 符号化したものです。 このときオクテット列は、 当該整数値を表現するために必要な最低数のオクテットのみ用いなければなりません>>265

[267] 0AA となります。 >>265

[54] RFC 7522 - Security Assertion Markup Language (SAML) 2.0 Profile for OAuth 2.0 Client Authentication and Authorization Grants ( 版) https://tools.ietf.org/html/rfc7522

The SAML Assertion XML data MUST be encoded using base64url, where the encoding adheres to the definition in Section 5 of RFC 4648 [RFC4648] and where the padding bits are set to zero. To avoid the need for subsequent encoding steps (by "application/x-www-form- urlencoded" [W3C.REC-html401-19991224], for example), the base64url- encoded data MUST NOT be line wrapped and pad characters ("=") MUST NOT be included.

[56] RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients ( 版) https://tools.ietf.org/html/rfc7636

Base64 encoding using the URL- and filename-safe character set defined in Section 5 of [RFC4648], with all trailing '=' characters omitted (as permitted by Section 3.2 of [RFC4648]) and without the inclusion of any line breaks, whitespace, or other additional characters. (See Appendix A for notes on implementing base64url encoding without padding.)

処理

[248] 符号化は、バイト列入力を、次のようにするべきです。

  1. [249] 結果を、入力forgiving-base64 encode した結果に設定します。
  2. [250] 結果中の + を、すべて - に置き換えます。
  3. [251] 結果中の / を、すべて _ に置き換えます。
  4. [252] 結果中の = を、すべて削除します。
  5. [253] 結果を返します。

[254] 復号は、文字列入力を、次のようにするべきです。

  1. [255] 入力中の - を、すべて + に置き換えます。
  2. [256] 入力中の _ を、すべて / に置き換えます。
  3. [257] 入力中に +, /, =, ASCII英数字のいずれでもない符号位置が含まれる場合、
    1. [258] 失敗を返し、ここで停止します。
  4. [259] 入力forgiving-base64 decode した結果を返します。

HTTP Certificate Store Interface の Base64

[300] HTTP Certificate Store InterfaceBase64 の一種を使っています。 >>299

[301] 仕様書では 「Base64」, 「Base64 encoding」, 「base64 encoding」, 「base64-encoded」 といった表現が使われています。 >>299

[302] 末尾の = は省略しなければならないとされています。 >>299

[303] 実装は ASCII英数字+/ 以外が含まれるとき、 拒絶しなければならないとされています。 >>299

[304] このように IETF にしてはしっかりエラー処理が規定されているにも関わらず、 なぜか 「Base64」 とは何かという最も重要な部分が規定されていません。

[305] >>303 から、 MIMEPEMBase64 から空白= を禁止したものだと推測はできますが...

その他のバリエーション

[306] BUCS と共に使う外字グリフ記述用の Base64 案は ASCII英数字./ を使っていました。 BUCS

[9] urn:urn-5 URN 名前空間で使っている Base64 変種は、 / の代わりに - を使います。 (URN では / が使えないため。) また、詰め文字は使いません。 (Namespace ID: urn-5 http://www.iana.org/assignments/urn-informal/urn-5)

[16] RFC 3548 曰く、 MIME Base64 ではファイル名や URI で安全ではないので、 / の代わりに ~ を使う提案があったそうです。しかし ~ もやはりファイル・システムや URI で安全とは言えません。

[18] M$XML/ の代わりに * を使っていたそうです。最近の版では両方認識するそうです。

[20] OpenToken >>19クッキーで使うためとして、 RFC 4648Base64詰め文字= ではなく * に変えたものを採用しています >>19

[847] >>846

採用アプリ変換方式
Hibernate+/ → *-
IMAP4+/ → +,
IRCu+/ → []
Python+/ → -_
正規表現フリー注2+/ → !-

[29] Norton AntiSpamencoded-word の最後の = を省くそうです。 mew-dist 25264 もちろんこの実装は MIME 違反です。

[39] 機械的に電子メイルを生成する類のプログラムで、 末尾に4つも = を付けるとんでもない符号化するものがあるそうです。 (しかも改善するように要求したら使っている MUA が悪いのだろうと言われたとか。。。)

(名無しさん [sage] 2005-12-10 07:32:30 +00:00)

[45] RFC 4387 では固定長のオクテット列を符号化するため、常に最後が = になってしまうので、 = は省略することになっています >>884

[55] PerlDigest::MD5Digest::SHA1 が出力する Base64文字列は、詰めが省略されています >>853


[189] IMAP4AUTHENTICATE 命令は、 base64符号化するとされていますが、その定義は示されていません >>186, >>187, >>188

[190] インターネットメールプロトコルであるから MIMEBase64 ではないかと推測したいところですが、 ABNF 構文が示されており、そこでは改行が認められていません。 本文中も単数の a line となっており、複数行は認められないようです。 しかし符号化されるデータが MIMEBase64 で1行に収まる保証はありません。

[191] 構文は、 MIME 式の字母詰めを認めており、 それ以外の文字は一切認めていません。詰めが含まれる数は、正しくなければなりません。 詰めの前の字母の制約は構文上は現れていません。

不透明な Base64 字母列

[273] 普通 Base64 は他の誰かが復号することを期待して用いられるものですが、 それを期待しない、あるいは自分自身しか復号しないので相互運用性が不要なところでも用いられる場合があります。 それなら任意のデータで構わないのですが、 プロトコルの文脈的な制約からまったく任意のバイト列を認めるわけにもいかず、 一定の制約は設けておきたい、 というようなノリで、 Base64 のようだけどそうとも言い切らない構文が使われることがあります。

[269] RFC 6750Bearercredentials として b64token と称する構文を規定しています。 これは MIMEBase64 とは矛盾しないという程度の構文上の制約で、若干の拡張も施されています。 構文の定義としてそうなっているだけで、 Base64 によるデータであることは求めていません。 (「b64」という名前で暗示しているだけで、 Base64 に言及すらしていません。) Bearer

[268] RFC 8030 Topic: HTTPヘッダーは、 構文の制約を RFC 4648 base64url により定めています。字母の定義として参照しているだけで、 それが実際に base64url で符号化されたデータであることは要求していません。

uuencode 風表現

[3] MIME 以外の場面でファイルを貼り付けるのに、 uuencode みたいな書き方をすることがあるみたい。

例1:

begin-base64 644 base64ed.data
... base64 stream ...
====

[26] 例2:

begin-base64 644 code.tgz
... base64 stream ...
=

実装

[193] Base64 の実装の選択時には、利用したいのがどのバリエーションで、 実装が対応しているのがどのバリエーションであるのかを慎重に検討する必要があります。

[8] uuencode64進数であることを利用して、 uuencode で符号化した後に tr を使うという方法が使われることもあります。

Perl

[4] Perl なら、 MIME::Base64 を使うのが気楽かと。 Perl 5.7.3 以降では標準で入っています。

[192] 但し、 >>2, >>7 のような変種には対応していません。

base64 コマンド

[68] 一般的な Linux 環境では、 base64 コマンドが用意されています。

[69] オプションなしで実行すると、標準入力符号化し、 結果を標準出力に書き込みます。

[71] echo コマンド-n オプションなしで実行すると最後に自動的に改行を付加するので、組み合わせて使う時は注意しないといけません。

[70] -d オプションつきで実行すると、標準入力復号し、 結果を標準出力に書き込みます。

BASE64.ASM

	ASSUME	CS:CODE,DS:CODE
CODE	SEGMENT

	ORG	100H
START:	MOV	BX,0
START1:	MOV	DI,0
LOOP1:	PUSH	BX
	PUSH	DI
	MOV	AH,06H
	MOV	DL,0FFH
	INT	21H
	POP	DI
	POP	BX
	JNZ	JUMP1
	CMP	DI,0
	JZ	END1
	CMP	DI,1
	JZ	END2
	CMP	DI,2
	JZ	END3
JUMP1:	MOV	BUFFER[DI],AL
	INC	DI
	CMP	DI,3
	JNZ	LOOP1

SHORI2:	MOV	CH,4
LOOP3:	MOV	CL,6
	MOV	SI,0
LOOP2:	SAL	BUFFER+2,1
	RCL	BUFFER+1,1
	RCL	BUFFER+0,1
	RCL	SI,1
	DEC	CL
	JNZ	LOOP2
	PUSH	BX
	PUSH	DI
	PUSH	SI
	PUSH	CX
	MOV	DL,BASE64[SI]
	MOV	AH,06H
	INT	21H
	POP	CX
	POP	SI
	POP	DI
	POP	BX
	DEC	CH
	JNZ	LOOP3
	ADD	BX,DI
	CMP	BX,57
	JNZ	START1
	PUSH	BX
	PUSH	CX
	PUSH	DI
	PUSH	SI
	MOV	DL,0AH
	MOV	AH,06H
	INT	21H
	MOV	DL,0DH
	MOV	AH,06H
	INT	21H
	POP	SI
	POP	DI
	POP	CX
	POP	BX
	JMP	START

END2:	MOV	CH,2
	JMP	LOOP5
END3:	MOV	CH,3
LOOP5:	MOV	CL,6
	MOV	SI,0
LOOP4:	SAL	BUFFER+2,1
	RCL	BUFFER+1,1
	RCL	BUFFER+0,1
	RCL	SI,1
	DEC	CL
	JNZ	LOOP4
	PUSH	CX
	PUSH	DI
	PUSH	SI
	MOV	DL,BASE64[SI]
	MOV	AH,06H
	INT	21H
	POP	SI
	POP	DI
	POP	CX
	DEC	CH
	JNZ	LOOP5
	CMP	DI,2
	JZ	JUMP2
	MOV	DL,'='
	MOV	AH,06H
	INT	21H
JUMP2:	MOV	DL,'='
	MOV	AH,06H
	INT	21H

;処理終了
END1:	MOV	AH,4CH
	MOV	AL,00H
	INT	21H

;base64 moji hyoji
	MOV	AH,09H
	MOV	DX,OFFSET BASE64
	INT	21H

BASE64	DB	'ABCDEFGHIJKLMNOP'

	DB	'QRSTUVWXYZabcdef'
	DB	'ghijklmnopqrstuv'
	DB	'wxyz0123456789+/'
BUFFER	DB	'000','$'

CODE	ENDS
	END	START
[52] BASE64.ASM 名無しさん

テスト

[223] tests-web/base64 at master · wakaba/tests-web () https://github.com/wakaba/tests-web/tree/master/base64

[40] RFC 4648 - The Base16, Base32, and Base64 Data Encodings () https://tools.ietf.org/html/rfc4648#section-10

[130] web-platform-tests/base64.json at master · w3c/web-platform-tests () https://github.com/w3c/web-platform-tests/blob/master/fetch/data-urls/resources/base64.json

[131] mime-base64/base64.t at master · gisle/mime-base64 () https://github.com/gisle/mime-base64/blob/master/t/base64.t

[132] mime-base64/base64url.t at master · gisle/mime-base64 () https://github.com/gisle/mime-base64/blob/master/t/base64url.t

[133] base64url/tests.txt at master · ptarjan/base64url () https://github.com/ptarjan/base64url/blob/master/tests.txt

[121] rust-base64/tests at master · alicemaz/rust-base64 () https://github.com/alicemaz/rust-base64/tree/master/tests

[218] tests/base64.c · master · gnutls / GnuTLS · GitLab () https://gitlab.com/gnutls/gnutls/blob/master/tests/base64.c

[219] org.bouncycastle.util.encoders: Base64Test.java () http://www.docjar.org/html/api/org/bouncycastle/util/encoders/Base64Test.java.html

[222] base64_url/base64_url_spec.rb at master · infopark/base64_url () https://github.com/infopark/base64_url/blob/master/base64_url_spec.rb

安全性に関して

[34] 秘密情報送信のための使用: HTTP認証SASL などでは、合言葉などの繊細な情報を送信するために Base64 を使うことがあります。 Base64 は転送符号化であって暗号化ではありませんが、 第3者 (例えばシステムの管理者) が繊細な情報を含むメッセージを見てしまったとしても読むことができません (流石に脳内で Base64 を復号できる猛者はいないでしょう)。 もちろん、悪意のある人は計算機を使って復号してしまうでしょうから、 それに対する効果はありません。

[35] バッファ溢れ攻撃: 不正な (字母に含まれない) 文字や末尾以外にある詰めの = への対処がいい加減だと、バッファ溢れ攻撃に使われることがあり得ます。 RFC 3920 14.9 など

関連

[65] Base64 が普及する前は、同じく64進数でもある uuencode がよく使われていました。

[194] PEMMIME が当時一般的だった uuencode ではなく Base64 を採用したのは、 EBCDICISO/IEC 646の版を採用するメールシステムでも問題が起こらないという要件があったためのようです。

[195] しかし当時マイナーだった Base64 を選択したことは、 MIME の普及の足を引っ張ることになりました。 インターネットメールUsenetファイル転送にはその後も uuencode が使われ続け、2000年を過ぎても MUA によっては添付ファイルMIME 形式と uuencode 形式のどちらで送信するか選択するオプションが付いていたくらいです。 受信は両方に対応する必要がありました。 MIME 未対応の MUA でも対応済みの MUA でも適切に処理できるよう、 uuencode を非公式に MIMECTE として実装した MUA もありました。


[14] MIMEapplication/octet-stream では、オクテット (8ビット) 単位でないビット列も扱うことが出来ます。 そのような場合には全体長が8の倍数になるようにビット 0 を詰め、 詰めた数を引数でメモっておきます。

歴史

[12] インターネットでのオクテット列の文字列転写法のデ・ファクト標準です。

[10] XML でバイナリを扱う時には Base64 を使うのが推奨されている (誰に?) そうです。 (XML は人間可読であるのじゃなかったのか? って気もするが。)

[11] >>10 実際のところ、 ISO/IEC 6479制御シーケンスとかが混じったデータを使いたいという要求はある。 (それは XML の思想に反するという反発は強く、 XML 1.1 でも結局駄目になったけど。)

[21] >>11 XML 1.1 では結局文字参照なら OK (U+0000 以外。) になりましたね。

[13] >>11 でも、せめて FF くらい使いたい気はする。 (実質 Un*x でしか使えない環境依存だから入れたくないのかもしれんが。)

[37] XML デジタル署名系仕様では Base64 を使うことを識別するために http://www.w3.org/2000/09/xmldsig#base64 という URI参照を使っています。 (名無しさん [sage])

[41] たっぴ (パソコン質問掲示板) - Question and Answers - http://pcq.furu.org/thread.php?thread=81003

BASE64への変換(エンコード)やBASE64からの逆変換(デコード)はこちらで確認することができるようです。 http://suika.fam.cx/~wakaba/-temp/wiki/wiki?Base64

ちょwwwwwwwwwwwwwwwwwwwwwwwwwww そんな話聞いたことないってwww (名無しさん 2006-05-28 11:09:01 +00:00)

[51] MTOM は、往復変換を保障するため、 XML Schemabase64Binary正準形のみを最適化対象としています。 (名無しさん)

[42] Base64 - Wikipedia, the free encyclopedia http://en.wikipedia.org/wiki/Base64 (名無しさん )

Web Base64 API の標準化

Base64

[825] RFC 6120 - Extensible Messaging and Presence Protocol (XMPP): Core ( ( 版)) http://tools.ietf.org/html/rfc6120#section-13.9.1

[852] W3C XML Schema Definition Language (XSD) 1.1 Part 2: Datatypes ( ( 版)) http://www.w3.org/TR/2012/REC-xmlschema11-2-20120405/#base64Binary

[854] Jakarta Commons Codec による Base64符号の末尾に改行が付加される件について - keigoiの日記 ( ( 版)) http://d.hatena.ne.jp/keigoi/20090820/1250760023

[855] Base 64 エンコーディングと改行 (line feed) の話 - ひだまりソケットは壊れない ( ( 版)) http://vividcode.hatenablog.com/entry/2012/05/12/051058#comment-11696248318757556925

[856] RFC 6591 - Authentication Failure Reporting Using the Abuse Reporting Format ( ( 版)) http://tools.ietf.org/html/rfc6591#section-2.3

[881] XPath and XQuery Functions and Operators 3.0 ( ( 版)) http://www.w3.org/TR/xpath-functions-3/#binary-functions

[882] Native base64 utility methods ( ( 版)) http://esdiscuss.org/topic/native-base64-utility-methods

[883] IRC logs: freenode / #whatwg / 20140505 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20140505#l-183

[885] Bug 22731 – Should atob() trim spaces, or not? ( ( 版)) https://www.w3.org/Bugs/Public/show_bug.cgi?id=22731

[886] IRC logs: freenode / #whatwg / 20140929 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20140929#l-683

[887] IRC logs: freenode / #whatwg / 20140929 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20140929#l-683

[888] RFC 989 - Privacy enhancement for Internet electronic mail: Part I: Message encipherment and authentication procedures ( ( 版)) https://tools.ietf.org/html/rfc989

[38] RFC 989 - Privacy enhancement for Internet electronic mail: Part I: Message encipherment and authentication procedures ( 版) https://tools.ietf.org/html/rfc989#section-4.4

A specific point regarding the integration of privacy-enhanced mail

facilities with the message encapsulation mechanism is worthy of

note. The subset of IA5 selected for transmission encoding

intentionally excludes the character "-", so encapsulated text can be

distinguished unambiguously from a message's closing encapsulation

boundary (Post-EB) without recourse to character stuffing.

[48] RFC 2440 - OpenPGP Message Format ( 版) https://tools.ietf.org/html/rfc2440#section-6.3

[49] RFC 4880 - OpenPGP Message Format ( 版) https://tools.ietf.org/html/rfc4880#section-6

[50] RFC 1113 - Privacy enhancement for Internet electronic mail: Part I - message encipherment and authentication procedures ( 版) http://tools.ietf.org/html/rfc1113#section-4.3

[53] RFC Errata Report ( 版) http://www.rfc-editor.org/errata_search.php?rfc=6455

The "test vector" for Sec-WebSocket-Key encoding, provided in RFC 6455 section 4.1, is wrong. It was processed by a base 64 encoder that was "improperly implemented" as mentioned in RFC 4648 section 3.5. Pad bits were not set to zero, which is a "MUST" requirement in RFC 4648,

[57] Base 64 エンコーディングと改行 (line feed) の話 - ひだまりソケットは壊れない ( 版) http://vividcode.hatenablog.com/entry/2012/05/12/051058

[59] Base64 って結構カオス? - DELPHIER@はてな ( 版) http://d.hatena.ne.jp/izariuo440/20110127/1296138201

[62] Editorial: put properties shared across globals on mixin · whatwg/html@cdd48e1 ( 版) https://github.com/whatwg/html/commit/cdd48e1f570c817402bf62108847c4a9f4b00b1e

[64] Encoded Polyline Algorithm Format  |  Google Maps APIs  |  Google Developers () https://developers.google.com/maps/documentation/utilities/polylinealgorithm

The encoding process converts a binary value into a series of character codes for ASCII characters using the familiar base64 encoding scheme

[76] XPath and XQuery Functions and Operators 3.1 () https://www.w3.org/TR/2017/REC-xpath-functions-31-20170321/#func-base64Binary-equal

Web Base64 の標準化

[77] Ambiguities in the "data" URL scheme () https://simonsapin.github.io/data-urls/

[78] Define forgiving base64 (annevk著, ) https://github.com/whatwg/infra/commit/6c69d4505476eb6adf08f3c17f682cff7f58ccb2

[79] base64: move code point check back down (annevk著, ) https://github.com/whatwg/infra/commit/6509cfbbf0c47020f8bcd0ce9786eea0b4f4bb74

[80] Define forgiving-base64 by annevk · Pull Request #145 · whatwg/infra () https://github.com/whatwg/infra/pull/145

[81] base64: move code point check back down by annevk · Pull Request #147 · whatwg/infra () https://github.com/whatwg/infra/pull/147

[82] base64: move code point check back down (annevk著, ) https://github.com/whatwg/infra/commit/6509cfbbf0c47020f8bcd0ce9786eea0b4f4bb74

[83] Move base64 algorithms to Infra by annevk · Pull Request #2920 · whatwg/html () https://github.com/whatwg/html/pull/2920

[84] Where should the web platform's base64 algorithm go? · Issue #2912 · whatwg/html () https://github.com/whatwg/html/issues/2912

[85] Move base64 algorithms to Infra (annevk著, ) https://github.com/whatwg/html/commit/9008ac9439aa7e4a30bd34ace8f7a2f1e63c153c

[127] Define data: URLs by annevk · Pull Request #579 · whatwg/fetch () https://github.com/whatwg/fetch/pull/579

[128] web-platform-tests/html/webappapis/atob at master · w3c/web-platform-tests () https://github.com/w3c/web-platform-tests/tree/master/html/webappapis/atob

[129] data: URL processing and generalized forgiving-base64 decode tests (annevk著, ) https://github.com/w3c/web-platform-tests/commit/7eec2bf5e522d28d99ced501b0f49477c3b105d5

[134] ptarjan/base64url: Various language implementations of base64_url_decode () https://github.com/ptarjan/base64url

Some simple samples of doing base64 url decoding.

[226] () https://info.quantcast.com/rs/516-DGM-318/images/Framework%20Vendor%20List%20%26%20Cookie%20Format%20Specification.pdf

Base64-encoding of

the concatenated

Cookie Value Fields

bits described below

The binary bits should be padded at the

end with zeroes to the nearest multiple of

8 bits, packed into a string of bytes, and

have websafe-base64 encoding

performed.

[227] () https://info.quantcast.com/rs/516-DGM-318/images/Framework%20Vendor%20List%20%26%20Cookie%20Format%20Specification.pdf

Above fields are multiples of 6 bits to fit

into base64-encoded bytes.

[228] Concise Binary Object Representation (CBOR) () https://cbor-wg.github.io/CBORbis/#encodedtext

Tags 33 and 34 are for base64url- and base64-encoded text strings, as defined in [RFC4648];

[230] Correct variable name in base64 algorithm (annevk著, ) https://github.com/whatwg/infra/commit/fcacad00d2b34fbc7ae1d023e81e9661f46e4b0d

[231] Correct variable name in base64 algorithm by annevk · Pull Request #195 · whatwg/infra () https://github.com/whatwg/infra/pull/195

[232] Language Guide (proto3)  |  Protocol Buffers  |  Google Developers () https://developers.google.com/protocol-buffers/docs/proto3#json

JSON value will be the data encoded as a string using standard base64 encoding with paddings. Either standard or URL-safe base64 encoding with/without paddings are accepted.

[260] Enc - OpenSSLWiki () https://wiki.openssl.org/index.php/Enc#Options

By default the encoded file has a line break every 64 characters. To suppress this you can use in addition to -base64 the -A flag. This will produce a file with no line breaks at all.

[261] Base64 - OpenSSLWiki () https://wiki.openssl.org/index.php/Base64

Base64 itself does not impose a line split, but openssl uses it in PEM context hence enforce that base64 content is splitted by lines with a maximum of 80 characters.

[271] Decentralized Identifiers (DIDs) v1.0 (, ) https://w3c.github.io/did-core/#cbor-extensibility

[272] draft-multiformats-multibase-02 - The Multibase Data Format, , https://tools.ietf.org/html/draft-multiformats-multibase-02

[275] カスタムポリシーを使用する署名付き Cookie の設定 - Amazon CloudFront () https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-custom-policy.html#private-content-custom-policy-signature-cookies

MIME base64 エンコーディングを使用して文字列を Base64 エンコードします。詳細については、RFC 2045, MIME (Multipurpose Internet Mail Extensions) Part One: Format of Internet Message Bodies の Section 6.8, Base64 Content-Transfer-Encoding を参照してください。

URL クエリ文字列内の無効な文字を有効な文字で置き換えます。次の表に無効な文字と有効な文字を示します。

無効な文字 (置換元) 有効な文字 (置換先)

+

- (ハイフン)

=

_ (下線)

/

~ (チルダ)

[289] base64 dialect · Issue #539 · httpwg/http-extensions () https://github.com/httpwg/http-extensions/issues/539

[291] d3x0r/JSOX: JavaScript Object eXchange format; extended JSON/JSON6 () https://github.com/d3x0r/JSOX#base64-character-set

[298] How does the base64 chosen here compare to atob/btoa? · Issue #5 · tc39/proposal-arraybuffer-base64 · GitHub, https://github.com/tc39/proposal-arraybuffer-base64/issues/5