目次
コーディング手順
Base64と はバイナリデータを64個の印字可能な文字で表現する表現方法で、2^6=64なので6ビットが1単位で、ある印字可能な文字に対応します。
Base64 は、 MIME 電子メールや XML の複雑なデータなど、テキスト データが通常処理される状況で、一部のバイナリ データを表現、送信、および保存するためによく使用されます。
プロジェクトでバイト配列と文字列の変換を扱う場合、文字セットを指定しないと、後のデモで説明するように、文字配列の長さが変わります。
Base64 エンコーディングでは、3 つの 8 ビット バイト (3*8=24) を 4 つの 6 ビット バイト (4*6=24) に変換し、6 ビットの前に 2 つの 0 を追加して 8 ビット ワード セクション形式を形成する必要があります。 . 残りの文字が 3 バイト未満の場合は 0 で埋められ、出力文字は = を使用するため 、エンコードされた出力テキストの末尾に 1 または 2 = が表示される場合があります。
出力コード ビットが読み取り可能な文字であることを確認するために、Base64 は 統一変換用のコード テーブルを策定しました。エンコーディング テーブルのサイズは 2^6=64であり、これが Base64 という名前の由来でもあります。
Base64 で印刷可能な文字には、 文字AZ、az、および数字 0-9が含まれているため、合計で 62 文字であり、2 つの印刷可能な記号は異なるシステムでは異なります ( および ) 。+
/,还有=
Base64 はインデックス エンコーディングであり、各文字はインデックスに対応しています。具体的な関係図は次のとおりです。
エンコーディング
64 は 2 の 6 乗に等しいため、Base64 文字は実際には 6 バイナリ ビット (ビット) を表します。
ただし、バイナリデータの 1 バイトは 8 ビットに相当するため、3 バイト (3 x 8 = 24 ビット) の文字列/バイナリデータは、4 つの Base64 文字 (4 x 6 = 24 ビット) に変換できます。
なぜ 3 バイトのグループなのですか? 6 と 8 の最小公倍数は 24 なので、24 ビットはちょうど 3 バイトです。
特定のエンコード方法:
-
各 3 バイトをグループとして扱い、合計 24 バイナリ ビットで 3 バイトを扱います。
-
これらの 24 ビットをそれぞれ 6 ビットの 4 つのグループに分割します。
-
2 進数 6 桁の各グループの前に 2 つの 00 を追加して、2 進数 32 桁、つまり 4 バイトに拡張します。
-
各バイトは、文字数である 64 未満の数に対応します。
-
文字インデックス関係テーブルによると、各文字番号は文字に対応し、Base64 でエンコードされた文字が取得されます。
上図 の文字列を 'you'
変換すると、 のようにエンコードされます 'eW91'
。
サイズの増加
3文字をBase64でエンコードすると、最終的に4文字になることがわかります。各 6 ビットは 2 つの 0 で埋められるため、1 バイトに対応する 8 ビットになります。
これはちょうど 3 分の 1 であるため、通常の状況では、Base64 でエンコードされたデータの量は、通常、元のデータの量よりも 3 分の 1 大きくなります。
= 等号
3 文字の英字を 4 つの Base64 文字に変換できます。文字の長さが 3 の倍数でない場合、どのような規則を使用すればよいでしょうか。
実はこれも単純で、実際に Base エンコーディングを使ってみると、65 番目の文字が記号であることがよくありますが、 '='
この等号は、この特殊な状況の処理方法です。
3 バイト未満の場所では、24 バイナリ ビットになるまで末尾に 0 が追加されます。
ただし、バイト数を計算するときは、合計の長さが直接 3 で除算されることに注意してください。余りが 1 の場合は末尾に 1 が追加され、余りが 2 の場合は 2 が追加され=
ます=
。
したがって、トランスコードされた文字列には、次の図に詳細が示されているように、1 または 2 のいずれかの接尾辞の等号を追加する必要があります。
図の2番目は、 'd'
インデックス文字テーブルでインデックス0を区別するために単一の文字を使用しています.このとき、取得されたコードでは、インデックス0に対応するA文字があります'='
が 文字を追加します.
デモ
package com.cjian.security;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.security.SecureRandom;
/**
* @Author: cjian
* @Date: 2022/11/9 17:09
* @Des:
*/
public class Base64Demo {
public static Base64 base64 = new Base64();
public static void main(String[] args) {
String man = base64.encode("you".getBytes());
System.out.println("you的base64结果:"+man);
SecureRandom secureRandom = new SecureRandom();
byte[] randomBytes = new byte[16];
secureRandom.nextBytes(randomBytes);
String str = new String(randomBytes);
System.out.println("原值:" + str);
//问题来了,长度发生了变化
//如果转string和获取字节的时候指定ISO-8859-1就没有问题
System.out.println("原值转byte长度:"+str.getBytes().length);
String r = base64.encode(randomBytes);
System.out.println("base64后:" + r);
String str2 = new String(base64.decode(r));
System.out.println("base64编码:" + str2);
System.out.println("base64解码后byte长度:" + base64.decode(r).length);
}
}
出力:
you的base64结果:eW91
原值:�;Ķp�K�n�ώ�|/
原值转byte长度:26
base64后:1DvEtnCSS55uFMPPjqp8Lw==
base64编码:�;Ķp�K�n�ώ�|/
base64解码后byte长度:16