Base 64プローブ

18244 ワード

Base 64とは?RFC 2045の定義に従って、Base 64は、Base 64コンテンツ転送符号化が、任意のシーケンスの8ビットバイトを直接認識されにくい形式として記述するように設計されていると定義される.
 
なぜBase 64を使うのですか?このコードを設計する際、設計者は主に3つの問題を考慮したと思います:1.暗号化しますか?2.暗号化アルゴリズムの複雑さと効率3.転送の処理方法暗号化は肯定的ですが、暗号化の目的はユーザーに非常に安全なEmailを送信させることではありません.この暗号化方式は主に「君子を防ぎ小人を防ぐ」ことだ.一目で見ても内容が全く見えないようにすればいい.この目的に基づいた暗号化アルゴリズムの複雑さと効率もあまり大きくも低くはできない.前の理由と同様に、MIMEプロトコルなどのEmailを送信するためのプロトコルは、どのように安全にEmailを送受信するかではなく、どのようにEmailを送受信するかを解決します.そのためアルゴリズムの複雑さは小さく、効率が高い.そうしないと、Emailを送信するために資源を大量に占有し、道が少し歪んでしまう.
アルゴリズム詳細解Base 64符号化は、3つの8ビットバイト(3*8=24)を4つの6ビットバイト(4*6=24)に変換し、その後、6ビットの前に2つの0を補い、8ビットの1バイトの形式を形成することを要求する.具体的な変換形式間の下図:文字列「張3」11010101 1100010010010010010010010010010010010010010010010010010011表1は、8ビットのバイトを1列110101011100010010010010011に接続し、順番に6つを選択した後、この6バイナリ数の前に0を2つ追加すると、新しいバイトになると考えられる.その後6個を選択し、0を追加し、24個のバイナリ数がすべて選択されるまで類推する.
実際の結果を見てみましょう.文字列「張3」11010101 HEX:D 5 11000101 HEX:C 5 0010011 HEX:33 0010101 00011100 0010010010010010011文字'5'文字'^'文字'^T'文字'3'10進53 10進34 10進51表2のように「張3」という文字列はBase 64で「5^^T 3」と表されていますか.間違いだ!Base 64符号化方式は、単に変換されたコンテンツを用いて符号化されるものではない.「^」のような文字は制御文字であり、コンピュータでは表示されず、場合によっては使用できません.Base 64はそれ自身の符号表を持っている:Table 1:The Base 64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 C 19 T 36 k 36 k 53 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 7 H 24 Y 41 p 58 8 8 8 I 25 Z 25 Z 26 a 43 r 60 8 10 K 27 b 44 s 61 11 L 28 c 45 t 62+12 M 29 d 46 46 d 46 46 d 46 6 6 6 6 6 6 H 24 H 24 H 24 H 24 H 24 H 24 Y 24 Y 41 p 58 8 8 8 8 8 8 8 8 u 63/13 N 30 e 47 v(pad)=14 O 31 f 48 w 15 P 32 g 49 x 16 Q 33 h 50 yテーブル3これもBase 64名の由来であり、Base 64符号化の結果はアルゴリズムによって符号化を2桁高く0桁低く6桁を代表データとするのではなく、上の表のように「A」が7桁、「a」が6桁となる.表では,符号化された番号は,得られた新しいバイトの10進数値に対応する.従って、表2から対応するBase 64符号化を得ることができる:文字列"張3"11010101 HEX:D 5 11000101 HEX:C 5 0011010011 HEX:33 0010101 00011100 00010100 0010011文字'5'文字'^'文字'^T'文字'3'10進数53 10進数34 10進数20 10進数51文字'1文字'i'文字'U'文字'z'表4のように、文字列「張3」は符号化されて文字列「1 iUz」となる.Base 64は3バイトを4バイトに変換するので、符号化後の符号量(バイト単位、以下同)は符号化前の符号量より約1/3多い.「約」というのは、コード量がちょうど3の整数倍であれば、自然と1/3多くなるからです.でもそうじゃなかったら?注意深い人は、The Base 64 Alphabetの最後に(pad)=文字があることに気づいたかもしれません.この文字の目的はこの問題を処理することです.符号量が3の整数倍でない場合、符号量/3の残数は自然に2または1である.変換するときは、結果的に6位未満は0で対応する位置を補い、その後6位の前に2つの0を補います.変換して空にした結果を「=」で補正します.例えば、結果として、最後の残りが2バイトの「張」:文字列「張」11010101 HEX:D 5 11000101 HEX:C 5 0010101 00011100 00010100十進法53十進法34十進法20 pad文字'1'文字'i'文字'U'文字'='表6のように、最後の2バイトが「1 iU=」に整理される.同様に、元のコードが1バイトしか残っていない場合、「=」が2つ追加されます.この2つのケースのみであるため、Base 64の符号化は符号化の最後に2つの"="があり、Base 64を復号するには、単純な符号化の逆過程にすぎず、読者は自分で検討することができる.私は文章の最後に復号アルゴリズムを与えます.
 
アルゴリズム実装は実はアルゴリズムの詳細な解の時に基本的にすでにはっきり言った.プログラム上で制約判断を除くと,読み出しデータ3バイトはANDで上位6ビットをとり,新しい変数にを入れて右に2ビットシフトし,上位2ビット清0ANDは1バイト目の下位2ビットと2バイト目の上位4ビットシフトを取って新しい変数にを入れて右に2ビットシフトし,清0…というようになる.復号化されたクラスC言語実装アルゴリズム:
BYTE LMoveBit(int base, int MoveNum)
{
    BYTE result=base;
    if(MoveNum==0)return 1;
    if(MoveNum==1)return MoveNum;
    result=base<<(MoveNum-1);
    return result;
}

char base64_alphabet[]=
{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/','='};

BYTE Base64Decode(char *base64code, DWORD base64length)
{
    char buf[4];
    int i,j;
    int k;
    int l=0;
    BYTE temp1[4],temp2;
    BYTE *Buffer=new BYTE[base64length*3/4];
    DWORD base64a=(base64length/4)-1;
    DWORD base64b=0;
    for(;base64b<base64a+1;base64b++)
    {
        for(i=0;i<4;i++)
        {
            buf[i]=*(base64code+(base64b*4)+i);
            for(j=0;j<65;j++)
            {
                if(buf[i]==base64_alphabet[j])
                {
                    temp1[i]=j;
                   break;
                }
            }
        }
        i--;
        for(k=1;k<4;k++)
        {
            if(temp1[i-(k-1)]==64){m_padnum++; continue;}
            temp1[i-(k-1)]=temp1[i-(k-1)]/LMoveBit(2,(k-1)*2);
            temp2=temp1[i-k];
            temp2=temp2&(LMoveBit(2,k*2)-1);
           temp2*=LMoveBit(2,8-(2*k));//move 4
            temp1[i-(k-1)]=temp1[i-(k-1)]+temp2;
            Buffer[base64b*3+(3-k)]=temp1[i-(k-1)];
        }
    }
    return Buffer;
}                                 

 
このアルゴリズムによると、文章の最初に与えられたEmailの内容は、こんにちは、SnaiXこれはBase 64のテストメールです!
Javaアルゴリズム:
package javamail;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import sun.misc.BASE64Encoder;

public class Base64Util {
 public static void main(String[] args)throws IOException {
    BASE64Encoder encoder =new BASE64Encoder();
    System.out.println("please input username:");
    String username=new BufferedReader(new InputStreamReader(System.in)).readLine();
    System.out.println(encoder.encode(username.getBytes()));
    System.out.println("please input password:");
    String passwd=new BufferedReader(new InputStreamReader(System.in)).readLine();
    System.out.println(encoder.encode(passwd.getBytes()));
   }
}