web-dev-qa-db-ja.com

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

ウィキペディア 言う

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

しかし、データは常にバイナリで保存/送信されるわけではありません。なぜなら、マシンのメモリにはバイナリが保存されており、それを解釈する方法に依存しているからです。したがって、ビットパターン010011010110000101101110をASCIIのManとしてエンコードするか、Base64のTWFuとしてエンコードするかにかかわらず、最終的には同じビットパターンを格納します。

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

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


みなさんありがとう、私は今理解していると思います。

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

From 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

同じ量の情報に対してより多くのデータを転送するという犠牲を払って、受信者が意図した方法でデータをデコードできるようにします。受信者が偶然残りの文字セットに対して異なる解釈を行う場合でも。

233
Lazer

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

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

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


コンピューターはバイナリで通信します-0と1-しかし、人々は通常、テキストや画像などのよりリッチなフォームデータと通信することを望みます。このデータをコンピューター間で転送するには、最初に0と1にエンコードし、送信してから、再度デコードする必要があります。テキストを例にとると、このエンコードを実行する多くの異なる方法があります。単一のエンコーディングについて全員が同意できればもっと簡単になりますが、悲しいことにそうではありません。

もともと多くの異なるエンコードが作成されました(例 Baudotコード )。最終的にASCIIが文字あたり7ビットの標準になるまで、文字ごとに異なるビット数を使用していました。ただし、ほとんどのコンピューターは、それぞれ8ビットで構成されるバイトでバイナリデータを保存するため、このタイプのデータの転送には ASCII は不適切です。一部のシステムでは、最上位ビットも消去されます。さらに、システム間の行末エンコーディングの違いは、ASCII文字10と13も時々変更されることを意味します。

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

テキストを確実に送信するには、first選択したテキストエンコーディング(UTF-8など)を使用してバイトにエンコードしてから、afterwardsBase64は、結果のバイナリデータを、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

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

245
Mark Byers

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ドキュメントを正しく解析し、画像データを抽出できます。

56
yfeldblum

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

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

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

Base64はもともと、Multipurpose Internet Mail Extensionsの一部としてバイナリデータを電子メールに添付できるようにするために考案されました。

35
Billy ONeal

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

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

26
Håvard S

それはメディアvalidates文字列エンコーディング以上のものであるため、処理アプリケーションがデータを受け入れられるようにします(たとえば、EOLを表すバイナリシーケンスが含まれないようにします)。

UTF-8エンコーディングのバイナリデータを電子メールで送信することを想像してください-1と0のストリームがUTF-8で有効なUnicodeではないsequenceを作成すると、電子メールが正しく表示されない場合がありますエンコーディング。

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

http://www.foo.com/hello 私の友人-> 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:添付; filename = "a.gif"

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

16
Aiden Bell

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

12
Bill the Lizard

特殊文字をエスケープする代わりに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なしでそれを行うことは幸運です。しかし、それは複数のコマンドを必要とします-サーバーに投入するためのキーバインディングを複雑にします):

11

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

10
casablanca

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

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

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

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

  • プラットフォームによって異なる、行末に使用されるバイト0x0Aおよび0x0D。
  • 0x00(NULL = C文字列ターミネーター)、0x03(テキストの終わり)、0x04(送信の終わり)、または0x1A(DOSのファイルの終わり)など、データの終わりを早めに通知する他の制御文字。
  • 0x7Fを超えるバイト(ASCII用に設計されたプロトコルの場合)。
  • 無効なUTF-8のバイトシーケンス。

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

しかし、1つの質問。そのようなシステムは、一般的なUTF-8のような一般的なエンコード技術にまだ同意していないのでしょうか?

少なくともウェブ上では、ほとんどがそうです。 大部分のサイトはUTF-8を使用

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

東の問題は、GB2312やShift_JISなどのエンコーディングへの添付です。

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

6
dan04

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

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

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

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

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

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

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

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

3
dirkgently