なぜBase64を使用するのですか?


275

ウィキペディアは言う

Base64エンコードスキームは、テキストデータを処理するように設計されたメディアを介して保存および転送する必要があるバイナリデータをエンコードする必要がある場合に一般的に使用されます。これは、転送中にデータが変更されることなくそのままであることを保証するためです。

しかし、私たちのマシンが持っているメモリはバイナリを格納し、それはあなたがそれをどのように解釈するかに依存するので、データは常にバイナリで格納/送信されるということではありませんか?したがって、ビットパターン010011010110000101101110ManASCII としてエンコードする場合でもTWFu、Base64 としてエンコードする場合でも、最終的には同じビットパターンを格納することになります。

究極のエンコーディングがゼロと1に関するものであり、すべてのマシンとメディアがそれらを処理できる場合、データがASCIIまたはBase64として表されているかどうかはどうですか?

「テキストデータを扱うように設計されたメディア」とはどういう意味ですか?彼らはバイナリを扱うことができます=>彼らは何をでも扱うことができます。


みなさん、ありがとうございます。

データを送信するとき、意図したとおりの形式でデータが解釈されるかどうかはわかりません。したがって、両方の当事者が理解できる何らかの形式(Base64など)でコード化されたデータを送信します。同じ方法で送信者と受信者が異なる方法で解釈しても、コード化された形式に同意するため、データが誤って解釈されることはありません。

Mark Byersの例から

送りたい場合

Hello
world!

1つの方法は、次のようにASCIIで送信することです。

72 101 108 108 111 10 119 111 114 108 100 33

ただし、バイト10は、反対側の改行として正しく解釈されない場合があります。したがって、ASCIIのサブセットを使用して、次のようにエンコードします

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

同じ情報量で転送されるデータが増えるという犠牲を払って、レシーバーが残りの文字セットの解釈が異なる場合でも、レシーバーが意図した方法でデータをデコードできるようにします。


6
歴史的背景:電子メールサーバーは以前は7ビットASCIIでした。それらの多くは高ビットを0に設定するため、7ビット値のみを送信する必要がありました。en.wikipedia.org/wiki/Email#Content_encoding
Harold Lを

53
Perlより読みやすいため、base64を使用します
Martin

2
@マーティン、冗談です。Perlは読みにくいですが、base64はまったく読めません。
ピーターロング

1
@Lazer画像がありません
Mick

2
@Lazer、「しかし、バイト10は反対側の改行として正しく解釈されない可能性があります。」どうして?両者はASCIIに同意しており、ASCIIはそれを正しく解釈している必要があります。
ProgramCpp 2017

回答:


298

最初の間違いは、ASCIIエンコーディングとBase64エンコーディングは互換性があると考えていることです。ではない。それらはさまざまな目的で使用されます。

  • テキストをASCIIでエンコードするときは、テキスト文字列から始めて、それを一連のバイトに変換します。
  • Base64でデータをエンコードするときは、バイトのシーケンスから始めて、それをテキスト文字列に変換します。

そもそもなぜBase64が必要なのかを理解するには、コンピューティングの歴史が少し必要です。


コンピュータは0と1のバイナリで通信しますが、一般的に人々はテキストや画像などのよりリッチなフォームデータと通信したいと考えています。コンピュータ間でこのデータを転送するには、まず0と1にエンコードして送信し、再度デコードする必要があります。テキストを例に取ると、このエンコーディングを実行するにはさまざまな方法があります。私たち全員が単一のエンコーディングに同意できれば、はるかに簡単になりますが、悲しいことにそうではありません。

もともとはさまざまなエンコーディングが多く作成され(例:ボードットコード)、最終的にASCIIが文字あたり7ビットの標準になるまで、文字あたりのビット数が異なりました。ただし、ほとんどのコンピューターはバイナリデータをそれぞれ8ビットで構成されるバイトに格納するため、ASCIIはこのタイプのデータの転送には適していません。システムによっては、最も重要なビットをワイプすることさえあります。さらに、システム間での行末エンコーディングの違いは、ASCII文字10と13も時々変更されたことを意味します。

これらの問題を解決するために、Base64エンコーディングが導入されました。これにより、不正なバイトを、破損することなく安全に送信できることがわかっているバイト(ASCII英数字といくつかの記号)にエンコードできます。欠点は、Base64を使用してメッセージをエンコードすると、その長さが増加することです。3バイトのデータごとに4つのASCII文字にエンコードされます。

テキストを確実に送信するには、最初に選択したテキストエンコーディング(UTF-8など)を使用してバイトにエンコードし、その後、結果のバイナリデータをBase64エンコードして、ASCIIとして安全にエンコードできるテキスト文字列にエンコードします。受信者は、元のメッセージを復元するためにこのプロセスを逆にする必要があります。もちろん、これには受信者がどのエンコーディングが使用されているかを知っている必要があり、多くの場合、この情報は個別に送信する必要があります。

歴史的には、電子メールサーバーが行末を変更する可能性のある電子メールメッセージのバイナリデータをエンコードするために使用されていました。より最近の例は、Base64エンコーディングを使用して、画像データをHTMLソースコードに直接埋め込むことです。ここでは、「<」や「>」などの文字がタグとして解釈されないように、データをエンコードする必要があります。


これが実際の例です:

2行のテキストメッセージを送信します。

こんにちは
世界!

ASCII(またはUTF-8)として送信すると、次のようになります。

72 101 108 108 111 10 119 111 114 108 100 33

一部のシステムではバイト10が破損しているため、これらのバイトをBase64文字列としてBase 64エンコードできます。

SGVsbG8sCndvcmxkIQ ==

ASCIIを使用してエンコードすると、次のようになります。

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

ここのすべてのバイトは既知の安全なバイトであるため、システムがこのメッセージを破損する可能性はほとんどありません。元のメッセージの代わりにこれを送信して、受信者に元のメッセージを復元するプロセスを取り消させることができます。


4
「ほとんどの最新の通信プロトコルはデータを破損しません」-たとえば、メールのように、メッセージをメールボックスに保存するときに配信エージェントが文字列「\ nFrom」を「\ n> From」に置き換える場合。または、HTTPヘッダーは改行で終了し、データ内の改行をエスケープするための可逆的な方法がないため(行の継続により空白が埋められます)、任意のASCIIをそれらにダンプすることもできません。base64は単なる 7ビットセーフよりも優れており、英数字と-= + /セーフです。
スティーブジェソップ2010

1
「欠点は、Base64を使用してメッセージをエンコードすると、その長さが増加することです。データの3バイトごとに4バイトにエンコードされます。」どのようにして4バイトに増加しますか?まだ3 * 8 = 24ビットのみでしょうか?
Lazer、

4
@Lazer:いいえ。あなた自身の例を見てください-「Man」は「TWFu」としてbase-64エンコードされています。3バイト-> 4バイト。これは、入力が2 ^ 8 = 256バイトのいずれかであることが許可されているのに対し、出力は2 ^ 6 = 64バイト(および=、データの長さを示すのに役立つ)のみを使用するためです。入力に含まれていても出力に「エキサイティングな」文字が含まれないようにするために、出力のカルテットごとに8ビットが「無駄」になっています。
スティーブジェソップ2010

2
「Base64でデータをエンコードするときは、一連のバイトで開始してテキスト文字列に変換する」と「Base64でデータをエンコードするときは、一連のバイトで開始してそれをASCII値のみで構成されるバイトのシーケンス」。ASCII文字のみで構成される一連のバイトは、SMTPに必要なものです。そのため、Base64(およびquoted-printable)がcontent-transfer-encodingsとして使用されます。素晴らしい概観!
ALEXintlsos 2013年

1
私は投票しますが、64票あります。申し訳ありませんがこれは完璧です。
ジェシーCatrinck

61

バイナリデータをXMLにエンコードする

いくつかの画像をXML文書に埋め込むとします。画像はバイナリデータですが、XMLドキュメントはテキストです。ただし、XMLは埋め込まれたバイナリデータを処理できません。それで、どうやってそれを行うのですか?

1つのオプションは、画像をbase64でエンコードし、バイナリデータをXMLが処理できるテキストに変換することです。

の代わりに:

<images>
  <image name="Sally">{binary gibberish that breaks XML parsers}</image>
  <image name="Bobby">{binary gibberish that breaks XML parsers}</image>
</images>

あなたがやる:

<images>
  <image name="Sally" encoding="base64">j23894uaiAJSD3234kljasjkSD...</image>
  <image name="Bobby" encoding="base64">Ja3k23JKasil3452AsdfjlksKsasKD...</image>
</images>

また、XMLパーサーはXMLドキュメントを正しく解析し、画像データを抽出することができます。


これは、Microsoftの古い.mht形式(htmlファイル+ 1つのファイル内の画像)の動作のようです。
Sridhar Sarnobat

38

現在Base64を定義しているRFCを調べてみませんか?

データのベースエンコーディングは
、おそらくレガシーの理由でUS-ASCII [1]データに制限されている環境でデータを保存または転送するために多くの状況で使用されます。ベースエンコーディングは、レガシー制限のない新しいアプリケーションでも使用できます。単にテキストエディタでオブジェクトを操作できるようにするためです。

以前は、アプリケーションごとに要件が異なっていたため、ベースエンコーディングをわずかに異なる方法で実装することがありました。今日、プロトコルの仕様では、正確な説明や参照なしに、一般的にベースエンコーディング、特に「base64」を使用することがあります。多目的インターネットメール拡張機能(MIME)[4]は、多くの場合、行の折り返しや非アルファベット文字の影響を考慮せずに、base64のリファレンスとして使用されます。この仕様の目的は、一般的なアルファベットとエンコーディングの考慮事項を確立することです。これにより、他のドキュメントのあいまいさが軽減され、相互運用性が向上することが期待されます。

Base64は元々、多目的インターネットメール拡張機能の一部としてバイナリデータを電子メールに添付できるようにするために考案されました。


26

もちろん、テキストデータ用に設計されたメディアも最終的にはバイナリになりますが、テキストメディアは多くの場合、制御文字に特定のバイナリ値を使用します。また、テキストメディアは、特定のバイナリ値を非テキストとして拒否する場合があります。

Base64エンコーディングでは、バイナリデータをテキストメディアのテキストとしてのみ解釈できる値としてエンコードし、特殊文字や制御文字を含まないため、データはテキストメディア全体でも保持されます。


したがって、Base64と同様に、ほとんどの場合、ソースと宛先の両方がデータを同じ方法で解釈します。おそらく、制御文字を異なる方法で解釈したとしても、これらの64文字は同じ方法で解釈されるためです。そうですか?
Lazer、

6
それらのデータは転送中に破壊される可能性さえあります。たとえば、サーバーとクライアントのオペレーティングシステムが一致せず、転送にテキストモードのフラグが設定されている場合、多くのFTPプログラムは行末が13、10から10に、またはその逆に書き換えられます。FTPは頭に浮かんだ最初の例にすぎませんが、FTPはバイナリモードをサポートしているため、良い例ではありません。
Hendrik Brummermann、2010

@nhnb:テキストモードはバイナリデータを必要とするものには不適切であることを示しているので、FTPは良い例だと思います。
jamesdlin 2010

テキストメディアとは何ですか?
Koray Tugay

18

メディアが文字列エンコーディングを検証するだけではないので、処理アプリケーションでデータが受け入れ可能であることを確認したい(たとえば、EOLを表すバイナリシーケンスが含まれていない)

バイナリデータをUTF-8エンコードのメールで送信したいとします-1と0のストリームがUTF-8エンコードで有効なUnicodeではないシーケンスを作成すると、メールが正しく表示されない場合があります。

URL自体でURLに無効な文字をエンコードする場合も、同じタイプのことがURLで発生します。

http://www.foo.com/hello my friend-> http://www.foo.com/hello%20my%20friend

これは、スペースが臭いと思われるシステムを介してスペースを送信するためです。

私たちが行っているのは、既知の良好で許容可能な有害でないビットシーケンスと別のリテラルビットシーケンスとの1対1のマッピングがあり、処理アプリケーションエンコードを区別しないことを確認することだけです。

あなたの例でmanは、最初の形式で有効なASCIIである可能性があります。しかし、多くの場合、ランダムなバイナリである値を送信したい場合があります(つまり、メールで画像を送信します)。

MIMEバージョン:1.0
Content-Description: "a.gifのBase64エンコード"
Content-Type:image / gif; name = "a.gif"
Content-Transfer-Encoding:Base64
Content-Disposition:attachment; filename = "a.gif"

ここでは、GIF画像がbase64でメールのチャンクとしてエンコードされていることがわかります。電子メールクライアントはヘッダーを読み取ってデコードします。エンコーディングのため、GIFにプロトコルとして解釈される可能性のあるものが含まれていないことを確認できます。また、SMTPまたはPOPで重要と思われるデータを挿入することは避けます。


1
それは素晴らしいです-この説明はそれをクリックさせました。データを難読化または圧縮するのではなく、単にプロトコルとして解釈できる特別なシーケンスを使用しないようにするためです。
Patrick Michaelsen

13

特殊文字をエスケープする代わりにBase64

非常に異なるが実際の例を挙げましょう。私は、ブラウザーで実行するJavaScriptコードを記述します。HTMLタグにはID値がありますが、IDで有効な文字には制限があります。

しかし、私は自分のIDに無損失でファイルシステム内のファイルを参照させたいと思っています。実際のファイルには、感嘆符、アクセント付き文字、チルド、絵文字など、あらゆる種類の奇妙で素晴らしい文字を含めることができます。これは私にはできない:

<div id="/path/to/my_strangely_named_file!@().jpg">
    <img src="http://myserver.com/path/to/my_strangely_named_file!@().jpg">
    Here's a pic I took in Moscow.
</div>

次のようなコードを実行したいとします。

# ERROR
document.getElementById("/path/to/my_strangely_named_file!@().jpg");

このコードは実行すると失敗すると思います。

Base64を使用すると、どの言語がどの特殊文字を許可し、どの言語がエスケープする必要があるかを気にすることなく、複雑なものを参照できます。

document.getElementById("18GerPD8fY4iTbNpC9hHNXNHyrDMampPLA");

MD5やその他のハッシュ関数を使用する場合とは異なり、エンコーディングを逆にして、実際にどのデータが実際に有用であったかを調べることができます。

Base64年前に知っていたらいいのに。私は ' encodeURIComponent'で髪を引き裂くことを避けたでしょうstr.replace(‘\n’,’\\n’)

テキストのSSH転送:

sshを介して複雑なデータ(たとえば、シェルのパーソナライゼーションを取得できるようにドットファイル)を渡そうとしている場合は、Base 64なしで実行してください。これがBase 64で実行する方法です(SCPを使用できることはわかっていますが、しかし、それは複数のコマンドを必要とします-これはサーバーへのsshのキーバインディングを複雑にします):


12

XMLにバイナリデータ埋め込もうとしたときが便利だと思ったときの1つの例です。バイナリデータの一部は、SAXパーサーによって誤って解釈されていました。そのデータは、XML特殊文字を含めて、文字通り何でもかまいません。送信側でデータをBase64エンコードし、受信側でデコードすることで、この問題が修正されました。


1
+1-しかし、これは決してSAX固有ではありません。これは、DOMやXLINQなどのあらゆるXMLパーサーで発生します。
Billy ONeal

1
@ビリー:はい、絶対に。私はたまたまそのアプリケーションにSAXパーサーを使用しています。
、トカゲ

SAXパーサーなどの異なるエンジンは、ASCII値の一部を異なる方法で解釈する場合があります(異なる制御文字)。したがって、ここでの考え方は、普遍的に共通の意味を持つASCIIのサブセットを使用することです。正しい?
Lazer

1
@Lazer:そうです。エンコードされていないバイナリデータには、ASCII(この場合はそうではなかった)として解釈しようとしたときに、偶然に制御文字が含まれます。
、トカゲ

10

ほとんどのコンピュータは8ビットのバイナリ形式でデータを保存しますが、これは必須ではありません。一部のマシンおよび伝送メディアは、一度に7ビット(またはそれ以下)しか処理できません。このようなメディアは、ストリームを7ビットの倍数で解釈するため、8ビットのデータを送信する場合、反対側で期待したものを受信できません。Base-64は、この問題を解決するための1つの方法にすぎません。入力を6ビット形式にエンコードし、メディアを介して送信し、受信側で8ビット形式にデコードします。


3
7ビットの後でストリームが中断した場合、なぜ問題になるのですか。最後に、他のマシンはすべてのデータをストリームを介して受信します。表示するために8ビット形式を選択できますか?私の心のどこが悪いの!
マラウディン

6

他の(やや長い)回答に加えて、7ビットASCIIのみをサポートする古いシステムを無視しても、テキストモードでのバイナリデータの提供に関する基本的な問題は次のとおりです。

  • 改行は通常、テキストモードで変換されます。
  • NULバイトをテキスト文字列の終わりとして扱わないように注意する必要があります。これは、C系統のプログラムでは簡単に行えません。

一部のプラットフォームでは、ファイルの終わりとして解釈される^ C、^ D、^ Zなどの制御文字もあります。
dan04 2010

5

「テキストデータを扱うように設計されたメディア」とはどういう意味ですか?

これらのプロトコルは、バイナリデータ(.pngや.jpg画像など)ではなく、テキスト(多くの場合、英語のテキストのみ)を処理するように設計されています。

彼らはバイナリを扱うことができます=>彼らは何をでも扱うことができます。

しかし、その逆は真実ではありません。テキストを表すように設計されたプロトコルは、たまたま含まれているバイナリデータを不適切に処理する可能性があります。

  • プラットフォームによって異なる、行末に使用されるバイト0x0Aおよび0x0D。
  • 0x00(NULL = C文字列ターミネーター)、0x03(END OF TEXT)、0x04(END OF TRANSMISSION)、または0x1A(DOS end-of-file)などのその他の制御文字。
  • 0x7Fを超えるバイト(ASCII用に設計されたプロトコルの場合)。
  • 無効なUTF-8であるバイトシーケンス。

したがって、テキストベースのプロトコルでバイナリデータを送信することはできません。スペース以外の非制御ASCII文字を表すバイトに制限があり、そのうち94です。Base64が選択された理由は、2の累乗で動作する方が速く、64が動作する最大の文字であるためです。 。

1つの質問。そのようなシステムが、それほど一般的なUTF-8のような一般的なエンコーディング手法にまだ同意していないのですか?

少なくともWebでは、ほとんどがそうです。 ほとんどのサイトではUTF-8を使用しています

西側の問題は、1バイト= 1文字のass-u-me-sで、UTF-8で動作しない古いソフトウェアがたくさんあることです。

東部の問題は、GB2312やShift_JISなどのエンコーディングへのアタッチメントです。

そして、マイクロソフトがまだ間違ったUTFエンコーディングを選択したことを克服していないように見えるという事実。Windows APIまたはMicrosoft Cランタイムライブラリを使用する場合、UTF-16またはロケールの「ANSI」エンコーディングに制限されます。常に変換する必要があるため、UTF-8を使用するのは面倒です。


5

なぜ/どのようにBase64エンコーディングを使用するのですか?

Base64は、バイナリからテキストへのエンコードスキームの1つで、効率は75%です。これは、典型的なバイナリデータ(画像など)をレガシーの「8ビットではない」従来のチャネルで安全に送信できるようにするために使用されます。初期の電子メールネットワーク(1990年代前半まで)では、ほとんどの電子メールメッセージは7ビットUS-ASCII文字セットのプレーンテキストでした。そのため、初期の通信プロトコル標準の多くは、「8ビットではない」「7ビット」の通信リンクで機能するように設計されていました。スキーム効率は、入力のビット数とエンコードされた出力のビット数の比率です。16進数(Base16)も、バイナリからテキストへのエンコード方式の1つであり、効率は50%です。

Base64エンコード手順(簡略化):

  1. バイナリデータは、それぞれ24ビット(3バイト)の連続したチャンクに配置されます。
  2. 各24ビットのチャンクは、それぞれ6ビットの4つの部分にグループ化されます。
  3. 各6ビットグループは、対応するBase64文字値に変換されます。つまり、Base64エンコードは、3つのオクテットを4つのエンコードされた文字に変換します。入力バイトに対する出力バイトの比率は4:3(33%のオーバーヘッド)です。
  4. 興味深いことに、4つの文字を生成するためにエンコードされる3オクテットグループ内の位置に応じて、同じ文字は異なる方法でエンコードされます。
  5. 受信者は、元のメッセージを復元するためにこのプロセスを逆にする必要があります。

3

「テキストデータを扱うように設計されたメディア」とはどういう意味ですか?

ASCIIが非ASCII値を扱う世界を支配した当時、頭痛の種でした。人々はあらゆる種類のフープを飛び越えて、情報を失うことなくこれらをネットワーク経由で転送しました。


3
実際、当時、ASCIIはどこでも使用されていませんでした。多くのプロトコルには、データを転送するための個別のテキストモードとバイナリモードがありましたが、残念ながら、当時は電子メールがありませんでした。ASCIIではなく、単一のテキストエンコーディングが世界を支配していないため、テキストモードが必要です。すべてのコンピュータネットワークには独自のお気に入りのエンコーディングがあるため、交換されたテキストをローカルエンコーディングに変換して、日本企業がmojibakeなしでアメリカのビジネスコンサルタントにメールを送信できるようにするゲートウェイがあります。バイナリデータを送信する場合、この変換は明らかに望ましくありません。
Lie Ryan 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.