zoukankan      html  css  js  c++  java
  • base 64

    Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。
    Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,需要解码后才能阅读。
     
    外文名
    base64
    属    性
    编码方式
    应    用
    用于传输8Bit字节代码
    定    义
    8Bit字节代码的编码方式之一
    可用于
    HTTP环境下传递较长的标识信息
    特    性
    Base64编码具有不可读性

    目录

    1. 原理
    2. 应用
    3. 简介
    4. ▪ 规则
    5. ▪ 例子(1)
    1. ▪ 例子(2)
    2. 代码实现
    3. ▪ JavaScript版
    4. ▪ BASH版
    5. ▪ Java版
    1. ▪ PHP版
    2. ▪ VB版
    3. ▪ C#版
    4. MIME

    原理

    编辑
    转码过程例子:
    3*8=4*6
    内存1个字节占8位
    转前: s 1 3
    先转成ascii:对应 115 49 51
    2进制: 01110011 00110001 00110011
    6个一组(4组) 011100110011000100110011
    然后才有后面的 011100 110011 000100 110011
    然后计算机是8位8位的存数 6不够,自动就补两个高位0了
    所有有了 高位补0
    科学计算器输入 00011100 00110011 00000100 00110011
    得到 28 51 4 51
    查对下照表 c z E z

      先以“迅雷下载”为例: 很多下载类网站都提供“迅雷下载”的链接,其地址通常是加密的迅雷专用下载地址。
    其实迅雷的“专用地址”也是用Base64"加密"的,其过程如下:
    一、在地址的前后分别添加AA和ZZ
    二、对新的字符串进行Base64编码
    另: Flashget的与迅雷类似,只不过在第一步时加的“料”不同罢了,Flashget在地址前后加的“料”是[FLASHGET]
    而QQ旋风的干脆不加料,直接就对地址进行Base64编码了

    应用

    编辑
    Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
    然而,标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
    为解决此问题,可采用一种用于URL的改进Base64编码,它不仅在末尾去掉填充的'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
    另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“/”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
    此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。
    其他应用
    Mozilla Thunderbird和Evolution用Base64来保密电子邮件密码
    Base64 也会经常用作一个简单的“加密”来保护某些数据,而真正的加密通常都比较繁琐。
    垃圾讯息传播者用Base64来避过反垃圾邮件工具,因为那些工具通常都不会翻译Base64的讯息。
    在LDIF档案,Base64用作编码字串。

    简介

    编辑
    标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符
    为解决此问题,可采用一种用于URL的改进Base64编码,它在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
    另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
    此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。
    Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

    规则

    关于这个编码的规则:
    ①.把3个字符变成4个字符。
    ②每76个字符加一个换行符。
    ③.最后的结束符也要处理。

    例子(1)

    转换前 11111111, 11111111, 11111111 (二进制)
    转换后 00111111, 00111111, 00111111, 00111111 (二进制)
    上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。
    转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)
    转换表
    Table 1: The Base64 Alphabet
    索引
    对应字符
    索引
    对应字符
    索引
    对应字符
    索引
    对应字符
    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
       
    15
    P
    32
    g
    49
    x
       
    16
    Q
    33
    h
    50
    y
       

    例子(2)

    转换前 10101101,10111010,01110110
    转换后 00101011, 00011011 ,00101001 ,00110110
    十进制 43 27 41 54
    对应码表中的值 r b p 2
    所以上面的24位编码,编码后的Base64值为 rbp2
    解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
    (解码只是编码的逆过程,有关MIME的RFC还有很多,如果需要详细情况请自行查找。)
    第一个字节,根据源字节的第一个字节处理。
    规则:源第一字节右移两位,去掉低2位,高2位补零。
    既:00 + 高6位
    第二个字节,根据源字节的第一个字节和第二个字节联合处理。
    规则如下,第一个字节高6位去掉然后左移四位,第二个字节右移四位
    即:源第一字节低2位 + 源第2字节高4位
    第三个字节,根据源字节的第二个字节和第三个字节联合处理,
    规则第二个字节去掉高4位并左移两位(得高6位),第三个字节右移6位并去掉高6位(得低2位),相加即可
    第四个字节,规则,源第三字节去掉高2位即可
    //用更接近于编程的思维来说,编码的过程是这样的:
    //第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一//个目标字符。
    //然后将第一个字符与0x03(00000011)进行与(&)操作并左移4位,接着第二个字符右移4位与前者相或(|),即获得第二个目标字符。
    //再将第二个字符与0x0f(00001111)进行与(&)操作并左移2位,接着第三个字符右移6位与前者相或(|),获得第三个目标字符。
    //最后将第三个字符与0x3f(00111111)进行与(&)操作即获得第四个目标字符。
    //在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。
    可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?
    我们的解决办法是这样的:原文剩余的字节根据编码规则继续单独转(1变2,2变3;不够的位数用0补全),再用=号补满4个字节。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:
    一个原字节至少会变成两个目标字节
    所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况)。如果是1的话,转成2个Base64编码字符,为了让Base64编码是4的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。

    代码实现

    编辑

    JavaScript版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    if (!Shotgun)
        var Shotgun = {};
    if (!Shotgun.Js)
        Shotgun.Js = {};
    Shotgun.Js.Base64 = {
        _table: [
            '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''+''/'
        ],
      
        encode: function (bin) {
            var codes = [];
            var un = 0;
            un = bin.length % 3;
            if (un == 1)
                bin.push(0, 0);
            else if (un == 2)
                bin.push(0);
            for (var i = 2; i < bin.length; i += 3) {
                var c = bin[i - 2] << 16;
                c |= bin[i - 1] << 8;
                c |= bin[i];
                codes.push(this._table[c >> 18 & 0x3f]);
                codes.push(this._table[c >> 12 & 0x3f]);
                codes.push(this._table[c >> 6 & 0x3f]);
                codes.push(this._table[c & 0x3f]);
            }
            if (un >= 1) {
                codes[codes.length - 1] = "=";
                bin.pop();
            }
            if (un == 1) {
                codes[codes.length - 2] = "=";
                bin.pop();
            }
            return codes.join("");
        },
        decode: function (base64Str) {
            var i = 0;
            var bin = [];
            var x = 0, code = 0, eq = 0;
            while (i < base64Str.length) {
                var c = base64Str.charAt(i++);
                var idx = this._table.indexOf(c);
                if (idx == -1) {
                    switch (c) {
                        case '=': idx = 0; eq++; break;
                        case ' ':
                        case ' ':
                        case " ":
                        case ' ':
                            continue;
                        default:
                            throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au65E0u6548u7F16u7801uFF1A" + c };
                    }
                }
                if (eq > 0 && idx != 0)
                    throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au7F16u7801u683Cu5F0Fu9519u8BEFuFF01" };
      
                code = code << 6 | idx;
                if (++x != 4)
                    continue;
                bin.push(code >> 16);
                bin.push(code >> 8 & 0xff);
                bin.push(code & 0xff)
                code = x = 0;
            }
            if (code != 0)
                throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au7F16u7801u6570u636Eu957Fu5EA6u9519u8BEF" };
            if (eq == 1)
                bin.pop();
            else if (eq == 2) {
                bin.pop();
                bin.pop();
            else if (eq > 2)
                throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au7F16u7801u683Cu5F0Fu9519u8BEFuFF01" };
      
            return bin;
        }
    };

    BASH版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    base64Table=(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 + /);
     
    function str2binary() {
        idx=0;
        for((i=0; i<${#str}; i++)); do
            dividend=$(printf "%d" "'${str:i:1}");
            for((j=0;j<8;j++)); do
                let idx=8*i+7-j;
                let bin[$idx]=$dividend%2;
                dividend=$dividend/2;
            done;
        done;
        let idx=${#str}*8;
        for((i=0; i<appendEqualCnt*2; i++)); do
            let bin[$idx]=0;
            let idx++;
        done;
    }
    function calcBase64() {
        for((i=0; i<${#bin[*]}/6; i++)); do
            sum=0;
            for((j=0; j<6; j++)); do
                let idx=i*6+j;
                let n=6-1-j;
                let sum=sum+${bin[$idx]}*2**n;
            done;
            echo -n ${base64Table[$sum]};
        done
    }
     
    declare -a bin
    function base64Encode() {
        read -p "please enter ASCII string:" str;
        let appendZero=${#str}*8%6;
        let bits=${#str}*8;
        appendEqualCnt=0;
        if [[ $appendZero -ne 0 ]]; then
            let appendEqualCnt=(6-$appendZero)/2;
        fi
        str2binary;
        calcBase64;
        if [[ $appendEqualCnt -eq 2 ]]; then
            echo -n "==";
        elif [[ $appendEqualCnt -eq 1 ]]; then
            echo -n "=";
        fi
        echo;
         
    }

    Java版

    1
    2
    3
    4
    5
    6
    7
    import java.util.Base64;
    对于标准的Base64:
    加密为字符串使用Base64.getEncoder().encodeToString();
    加密为字节数组使用Base64.getEncoder().encode();
    解密使用Base64.getDecoder().decode();
    对于URL安全或MIME的Base64,只需将上述getEncoder()getDecoder()更换为getUrlEncoder()getUrlDecoder()
    或getMimeEncoder()和getMimeDecoder()即可。

    PHP版

    [下列代码仅在GBK中实现,UTF8代码请把 if($button=="迅雷地址->普通地址") echo substr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2); 这句改为if($button=="迅雷地址->普通地址") echo substr(mb_convert_encoding(base64_decode(str_ireplace("thunder://","",$txt1))),2,-2); 并把charset=gb2312改为charset=utf-8]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <?php
    $txt1=trim($_POST['text1']);
    $txt2=trim($_POST['text2']);
    $txt3=trim($_POST['text3']);
    $button=$_POST['button'];
    ?>
    <!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">
    <html>
    <head>
    <title>迅雷和FlashGet,QQ旋风地址地址转换工具</title>
    <metahttp-equiv="Content-Type"content="text/html;charset=gb2312">
    <metacontent="迅雷,FlashGet,地址转换,"name="keywords">
    </head>
    <body>
    <formname="form1"method="post"action="">
    <hrsize="1">
    <h3>迅雷转换</h3>
    <P>转换地址:
    <inputname="text1"value="<?phpecho$txt1;?>"type="text"style="516px;"/></P>
    <P>转换后的:
    <inputtype="text"value="<?php
    if($button=="普通地址->迅雷地址")echo"thunder://".base64_encode("AA".$txt1."ZZ");
    if($button=="迅雷地址->普通地址")echosubstr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2);
    ?>"style="516px;"/></P>
    <P>
    <inputtype="submit"name="button"value="普通地址->迅雷地址"/>
    <inputtype="submit"name="button"value="迅雷地址->普通地址"/></P>
    <h3>FlashGet转换</h3>
    <P>FlashGet地址:
    <inputname="text2"value="<?phpecho$txt2;?>"type="text"style="516px;"/></P>
    <P>转换后地址:
    <inputtype="text"value="<?php
    if($button=="普通地址->FlashGet地址")echo"flashget://".base64_encode($txt2);
    if($button=="FlashGet地址->普通地址")echostr_ireplace("[FLASHGET]","",base64_decode(str_ireplace("flashget://","",$txt2)));
    ?>"style="516px;"/></P>
    <P>
    <inputtype="submit"value="普通地址->FlashGet地址"name="button"/>
    <inputtype="submit"value="FlashGet地址->普通地址"name="button"/></P>
    <h3>QQ旋风转换</h3>
    <P>QQ旋风地址:
    <inputname="text3"value="<?phpecho$txt3;?>"type="text"style="516px;"/></P>
    <P>转换后地址:
    <inputtype="text"value="<?php
    if($button=="普通地址->QQ旋风")echo"qqdl://".base64_encode($txt3);
    if($button=="QQ旋风->普通地址")echobase64_decode(str_ireplace("qqdl://","",$txt3));
    ?>"style="516px;"/></P>
    <P>
    <inputtype="submit"value="普通地址->QQ旋风"name="button"/>
    <inputtype="submit"value="QQ旋风->普通地址"name="button"/></P>
    </form>
    </body>
    </html>

    VB版

    注:其中DigestStrToHexStr为可在程序外部调用加密函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    Option Explicit
    'B as e64Encoding/DecodingAlgorithm
    'By:DavidMidkif f(mznull@earthlink.net)
    '
    'Thisalgorithmsencodes and decodesdatain to B as e64
    'for mat.Thisfor matisextremelymoreefficientthan
    'Hexadecimalencoding.
    Private m_bytIndex(0 To 63) As Byte
    Private m_bytReverseIndex(0 To 255) As Byte
    Private Const k_bytEqualSign As Byte = 61
    Private Const k_bytmask1 As Byte = 3
    Private Const k_bytmask2 As Byte = 15
    Private Const k_bytmask3 As Byte = 63
    Private Const k_bytmask4 As Byte = 192
    Private Const k_bytmask5 As Byte = 240
    Private Const k_bytmask6 As Byte = 252
    Private Const k_bytShift2 As Byte = 4
    Private Const k_bytShift4 As Byte = 16
    Private Const k_bytShift6 As Byte = 64
    Private Const k_lMaxBytesPerLine As Long = 152
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As LongByVal Source As LongByVal Length As Long)
    Public Function Decode64(sInput As StringAs String
    If sInput = "" Then Exit Function
    Decode64 = StrConv(DecodeArray64(sInput), vbUnicode)
    End Function
    Private Function DecodeArray64(sInput As StringAs Byte()
    Dim bytInput() As Byte
    Dim bytWorkspace() As Byte
    Dim bytResult() As Byte
    Dim lInputCounter As Long
    Dim lWorkspaceCounter As Long
    bytInput = Replace(Replace(sInput, vbCrLf, ""), "=""")
    ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 2)) As Byte
    lWorkspaceCounter = LBound(bytWorkspace)
    For lInputCounter = LBound(bytInput) To UBound(bytInput)
        bytInput(lInputCounter) = m_bytReverseIndex(bytInput(lInputCounter))
    Next lInputCounter
    For lInputCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 8) + 8)) Step 8
        bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
        bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4)  k_bytShift2)
        bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytmask1) * k_bytShift6) + bytInput(lInputCounter + 6)
        lWorkspaceCounter = lWorkspaceCounter + 3
    Next lInputCounter
    Select Case (UBound(bytInput) Mod 8):
        Case 3:
            bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
        Case 5:
            bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
            bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4)  k_bytShift2)
            lWorkspaceCounter = lWorkspaceCounter + 1
        Case 7:
            bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
            bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4)  k_bytShift2)
            bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytmask1) * k_bytShift6) + bytInput(lInputCounter + 6)
            lWorkspaceCounter = lWorkspaceCounter + 2
    End Select
    ReDim bytResult(LBound(bytWorkspace) To lWorkspaceCounter) As Byte
    If LBound(bytWorkspace) = 0 Then lWorkspaceCounter = lWorkspaceCounter + 1
        CopyMemoryVarPtr (bytResult(LBound(bytResult))), VarPtr(bytWorkspace(LBound(bytWorkspace))), lWorkspaceCounter
        DecodeArray64 = bytResult
    End Function
    Public Function Encode64(ByRefsInput As StringAs String
    If sInput = "" Then Exit Function
    Dim bytTemp() As Byte
    bytTemp = StrConv(sInput, vbFromUnicode)
    Encode64 = EncodeArray64(bytTemp)
    End Function
    Private Function EncodeArray64(ByRefbytInput() As ByteAs String
    On Error GoTo ErrorHandler
    Dim bytWorkspace() As Byte, bytResult() As Byte
    Dim bytCrLf(0 To 3) As Byte, lCounter As Long
    Dim lWorkspaceCounter As Long, lLineCounter As Long
    Dim lCompleteLines As Long, lBytesRemaining As Long
    Dim lpWorkSpace As Long, lpResult As Long
    Dim lpCrLf As Long
    If UBound(bytInput) < 1024 Then
        ReDim bytWorkspace(LBound(bytInput) To (LBound(bytInput) + 4096)) As Byte
    Else
        ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 4)) As Byte
    End If
    lWorkspaceCounter = LBound(bytWorkspace)
    For lCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 3) + 3)) Step 3
        bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
        bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytmask1) * k_bytShift4) + ((bytInput(lCounter + 1))  k_bytShift4))
        bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex(((bytInput(lCounter + 1) And k_bytmask2) * k_bytShift2) + (bytInput(lCounter + 2)  k_bytShift6))
        bytWorkspace(lWorkspaceCounter + 6) = m_bytIndex(bytInput(lCounter + 2) And k_bytmask3)
        lWorkspaceCounter = lWorkspaceCounter + 8
    Next lCounter
    Select Case (UBound(bytInput) Mod 3):
        Case 0:
            bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
            bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex((bytInput(lCounter) And k_bytmask1) * k_bytShift4)
            bytWorkspace(lWorkspaceCounter + 4) = k_bytEqualSign
            bytWorkspace(lWorkspaceCounter + 6) = k_bytEqualSign
        Case 1:
            bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
            bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytmask1) * k_bytShift4) + ((bytInput(lCounter + 1))  k_bytShift4))
            bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex((bytInput(lCounter + 1) And k_bytmask2) * k_bytShift2)
            bytWorkspace(lWorkspaceCounter + 6) = k_bytEqualSign
        Case 2:
            bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
            bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytmask1) * k_bytShift4) + ((bytInput(lCounter + 1))  k_bytShift4))
            bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex(((bytInput(lCounter + 1) And k_bytmask2) * k_bytShift2) + ((bytInput(lCounter + 2))  k_bytShift6))
            bytWorkspace(lWorkspaceCounter + 6) = m_bytIndex(bytInput(lCounter + 2) And k_bytmask3)
    End Select
    lWorkspaceCounter = lWorkspaceCounter + 8
    If lWorkspaceCounter <= k_lMaxBytesPerLine Then
        EncodeArray64 = Left$(bytWorkspace, InStr(1, bytWorkspace, Chr$(0)) - 1)
    Else
        bytCrLf(0) = 13
        bytCrLf(1) = 0
        bytCrLf(2) = 10
        bytCrLf(3) = 0
    ReDim bytResult(LBound(bytWorkspace) To UBound(bytWorkspace))
    lpWorkSpace = VarPtr(bytWorkspace(LBound(bytWorkspace)))
    lpResult = VarPtr(bytResult(LBound(bytResult)))
    lpCrLf = VarPtr(bytCrLf(LBound(bytCrLf)))
    lCompleteLines = Fix(lWorkspaceCounter / k_lMaxBytesPerLine)
    For lLineCounter = 0 To lCompleteLines
        CopyMemorylpResult , lpWorkSpace, k_lMaxBytesPerLine
        lpWorkSpace = lpWorkSpace + k_lMaxBytesPerLine
        lpResult = lpResult + k_lMaxBytesPerLine
        CopyMemorylpResult , lpCrLf, 4&
        lpResult = lpResult + 4&
    Next lLineCounter
    lBytesRemaining = lWorkspaceCounter - (lCompleteLines * k_lMaxBytesPerLine)
    If lBytesRemaining > 0 Then CopyMemorylpResult , lpWorkSpace, lBytesRemaining
        EncodeArray64 = Left$(bytResult, InStr(1, bytResult, Chr$(0)) - 1)
    End If
    Exit Function
    ErrorHandler:
        Er As ebytResult
        EncodeArray64 = bytResult
    End Function

    C#版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    直接使用.NET中的的库类函数
    方法:
    ///<summary>
    ///Base64加密
    ///</summary>
    ///<paramname="Message"></param>
    ///<returns></returns>
    publicstringBase64Code(stringMessage)
    {
    byte[]bytes=Encoding.Default.GetBytes(Message);
    returnConvert.ToBase64String(bytes);
    }
    ///<summary>
    ///Base64解密
    ///</summary>
    ///<paramname="Message"></param>
    ///<returns></returns>
    publicstringBase64Decode(stringMessage)
    {
    byte[]bytes=Convert.FromBase64String(Message);
    returnEncoding.Default.GetString(bytes);
    }

    MIME

    编辑
    在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。
    完整的base64定义可见 RFC1421和 RFC2045。编码后的数据比原始数据略长,为原来的4/3。在电子邮件中,根据RFC822规定,每76个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的135.1%。
    转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的Bit用0补足。然后,每次取出6个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
    如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
    举例来说,一段引用自Thomas Hobbes's Leviathan的文句:
    Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.
    经过base64编码之后变成:
    TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
    IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
    dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
    dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
    ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=
    Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。
    Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,需要解码后才能阅读。
     
    外文名
    base64
    属    性
    编码方式
    应    用
    用于传输8Bit字节代码
    定    义
    8Bit字节代码的编码方式之一
    可用于
    HTTP环境下传递较长的标识信息
    特    性
    Base64编码具有不可读性

    目录

    1. 原理
    2. 应用
    3. 简介
    4. ▪ 规则
    5. ▪ 例子(1)
    1. ▪ 例子(2)
    2. 代码实现
    3. ▪ JavaScript版
    4. ▪ BASH版
    5. ▪ Java版
    1. ▪ PHP版
    2. ▪ VB版
    3. ▪ C#版
    4. MIME

    原理

    编辑
    转码过程例子:
    3*8=4*6
    内存1个字节占8位
    转前: s 1 3
    先转成ascii:对应 115 49 51
    2进制: 01110011 00110001 00110011
    6个一组(4组) 011100110011000100110011
    然后才有后面的 011100 110011 000100 110011
    然后计算机是8位8位的存数 6不够,自动就补两个高位0了
    所有有了 高位补0
    科学计算器输入 00011100 00110011 00000100 00110011
    得到 28 51 4 51
    查对下照表 c z E z

      先以“迅雷下载”为例: 很多下载类网站都提供“迅雷下载”的链接,其地址通常是加密的迅雷专用下载地址。
    其实迅雷的“专用地址”也是用Base64"加密"的,其过程如下:
    一、在地址的前后分别添加AA和ZZ
    二、对新的字符串进行Base64编码
    另: Flashget的与迅雷类似,只不过在第一步时加的“料”不同罢了,Flashget在地址前后加的“料”是[FLASHGET]
    而QQ旋风的干脆不加料,直接就对地址进行Base64编码了

    应用

    编辑
    Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java Persistence系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
    然而,标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
    为解决此问题,可采用一种用于URL的改进Base64编码,它不仅在末尾去掉填充的'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
    另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“/”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
    此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。
    其他应用
    Mozilla Thunderbird和Evolution用Base64来保密电子邮件密码
    Base64 也会经常用作一个简单的“加密”来保护某些数据,而真正的加密通常都比较繁琐。
    垃圾讯息传播者用Base64来避过反垃圾邮件工具,因为那些工具通常都不会翻译Base64的讯息。
    在LDIF档案,Base64用作编码字串。

    简介

    编辑
    标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符
    为解决此问题,可采用一种用于URL的改进Base64编码,它在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
    另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
    此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。
    Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

    规则

    关于这个编码的规则:
    ①.把3个字符变成4个字符。
    ②每76个字符加一个换行符。
    ③.最后的结束符也要处理。

    例子(1)

    转换前 11111111, 11111111, 11111111 (二进制)
    转换后 00111111, 00111111, 00111111, 00111111 (二进制)
    上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。
    转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)
    转换表
    Table 1: The Base64 Alphabet
    索引
    对应字符
    索引
    对应字符
    索引
    对应字符
    索引
    对应字符
    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
       
    15
    P
    32
    g
    49
    x
       
    16
    Q
    33
    h
    50
    y
       

    例子(2)

    转换前 10101101,10111010,01110110
    转换后 00101011, 00011011 ,00101001 ,00110110
    十进制 43 27 41 54
    对应码表中的值 r b p 2
    所以上面的24位编码,编码后的Base64值为 rbp2
    解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
    (解码只是编码的逆过程,有关MIME的RFC还有很多,如果需要详细情况请自行查找。)
    第一个字节,根据源字节的第一个字节处理。
    规则:源第一字节右移两位,去掉低2位,高2位补零。
    既:00 + 高6位
    第二个字节,根据源字节的第一个字节和第二个字节联合处理。
    规则如下,第一个字节高6位去掉然后左移四位,第二个字节右移四位
    即:源第一字节低2位 + 源第2字节高4位
    第三个字节,根据源字节的第二个字节和第三个字节联合处理,
    规则第二个字节去掉高4位并左移两位(得高6位),第三个字节右移6位并去掉高6位(得低2位),相加即可
    第四个字节,规则,源第三字节去掉高2位即可
    //用更接近于编程的思维来说,编码的过程是这样的:
    //第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一//个目标字符。
    //然后将第一个字符与0x03(00000011)进行与(&)操作并左移4位,接着第二个字符右移4位与前者相或(|),即获得第二个目标字符。
    //再将第二个字符与0x0f(00001111)进行与(&)操作并左移2位,接着第三个字符右移6位与前者相或(|),获得第三个目标字符。
    //最后将第三个字符与0x3f(00111111)进行与(&)操作即获得第四个目标字符。
    //在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。
    可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?
    我们的解决办法是这样的:原文剩余的字节根据编码规则继续单独转(1变2,2变3;不够的位数用0补全),再用=号补满4个字节。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:
    一个原字节至少会变成两个目标字节
    所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况)。如果是1的话,转成2个Base64编码字符,为了让Base64编码是4的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。

    代码实现

    编辑

    JavaScript版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    if (!Shotgun)
        var Shotgun = {};
    if (!Shotgun.Js)
        Shotgun.Js = {};
    Shotgun.Js.Base64 = {
        _table: [
            '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''+''/'
        ],
      
        encode: function (bin) {
            var codes = [];
            var un = 0;
            un = bin.length % 3;
            if (un == 1)
                bin.push(0, 0);
            else if (un == 2)
                bin.push(0);
            for (var i = 2; i < bin.length; i += 3) {
                var c = bin[i - 2] << 16;
                c |= bin[i - 1] << 8;
                c |= bin[i];
                codes.push(this._table[c >> 18 & 0x3f]);
                codes.push(this._table[c >> 12 & 0x3f]);
                codes.push(this._table[c >> 6 & 0x3f]);
                codes.push(this._table[c & 0x3f]);
            }
            if (un >= 1) {
                codes[codes.length - 1] = "=";
                bin.pop();
            }
            if (un == 1) {
                codes[codes.length - 2] = "=";
                bin.pop();
            }
            return codes.join("");
        },
        decode: function (base64Str) {
            var i = 0;
            var bin = [];
            var x = 0, code = 0, eq = 0;
            while (i < base64Str.length) {
                var c = base64Str.charAt(i++);
                var idx = this._table.indexOf(c);
                if (idx == -1) {
                    switch (c) {
                        case '=': idx = 0; eq++; break;
                        case ' ':
                        case ' ':
                        case " ":
                        case ' ':
                            continue;
                        default:
                            throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au65E0u6548u7F16u7801uFF1A" + c };
                    }
                }
                if (eq > 0 && idx != 0)
                    throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au7F16u7801u683Cu5F0Fu9519u8BEFuFF01" };
      
                code = code << 6 | idx;
                if (++x != 4)
                    continue;
                bin.push(code >> 16);
                bin.push(code >> 8 & 0xff);
                bin.push(code & 0xff)
                code = x = 0;
            }
            if (code != 0)
                throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au7F16u7801u6570u636Eu957Fu5EA6u9519u8BEF" };
            if (eq == 1)
                bin.pop();
            else if (eq == 2) {
                bin.pop();
                bin.pop();
            else if (eq > 2)
                throw "message""u0062u0061u0073u0065u0036u0034u002Eu0074u0068u0065u002Du0078u002Eu0063u006Eu0020u0045u0072u0072u006Fu0072u003Au7F16u7801u683Cu5F0Fu9519u8BEFuFF01" };
      
            return bin;
        }
    };

    BASH版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    base64Table=(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 + /);
     
    function str2binary() {
        idx=0;
        for((i=0; i<${#str}; i++)); do
            dividend=$(printf "%d" "'${str:i:1}");
            for((j=0;j<8;j++)); do
                let idx=8*i+7-j;
                let bin[$idx]=$dividend%2;
                dividend=$dividend/2;
            done;
        done;
        let idx=${#str}*8;
        for((i=0; i<appendEqualCnt*2; i++)); do
            let bin[$idx]=0;
            let idx++;
        done;
    }
    function calcBase64() {
        for((i=0; i<${#bin[*]}/6; i++)); do
            sum=0;
            for((j=0; j<6; j++)); do
                let idx=i*6+j;
                let n=6-1-j;
                let sum=sum+${bin[$idx]}*2**n;
            done;
            echo -n ${base64Table[$sum]};
        done
    }
     
    declare -a bin
    function base64Encode() {
        read -p "please enter ASCII string:" str;
        let appendZero=${#str}*8%6;
        let bits=${#str}*8;
        appendEqualCnt=0;
        if [[ $appendZero -ne 0 ]]; then
            let appendEqualCnt=(6-$appendZero)/2;
        fi
        str2binary;
        calcBase64;
        if [[ $appendEqualCnt -eq 2 ]]; then
            echo -n "==";
        elif [[ $appendEqualCnt -eq 1 ]]; then
            echo -n "=";
        fi
        echo;
         
    }

    Java版

    1
    2
    3
    4
    5
    6
    7
    import java.util.Base64;
    对于标准的Base64:
    加密为字符串使用Base64.getEncoder().encodeToString();
    加密为字节数组使用Base64.getEncoder().encode();
    解密使用Base64.getDecoder().decode();
    对于URL安全或MIME的Base64,只需将上述getEncoder()getDecoder()更换为getUrlEncoder()getUrlDecoder()
    或getMimeEncoder()和getMimeDecoder()即可。

    PHP版

    [下列代码仅在GBK中实现,UTF8代码请把 if($button=="迅雷地址->普通地址") echo substr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2); 这句改为if($button=="迅雷地址->普通地址") echo substr(mb_convert_encoding(base64_decode(str_ireplace("thunder://","",$txt1))),2,-2); 并把charset=gb2312改为charset=utf-8]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <?php
    $txt1=trim($_POST['text1']);
    $txt2=trim($_POST['text2']);
    $txt3=trim($_POST['text3']);
    $button=$_POST['button'];
    ?>
    <!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">
    <html>
    <head>
    <title>迅雷和FlashGet,QQ旋风地址地址转换工具</title>
    <metahttp-equiv="Content-Type"content="text/html;charset=gb2312">
    <metacontent="迅雷,FlashGet,地址转换,"name="keywords">
    </head>
    <body>
    <formname="form1"method="post"action="">
    <hrsize="1">
    <h3>迅雷转换</h3>
    <P>转换地址:
    <inputname="text1"value="<?phpecho$txt1;?>"type="text"style="516px;"/></P>
    <P>转换后的:
    <inputtype="text"value="<?php
    if($button=="普通地址->迅雷地址")echo"thunder://".base64_encode("AA".$txt1."ZZ");
    if($button=="迅雷地址->普通地址")echosubstr(base64_decode(str_ireplace("thunder://","",$txt1)),2,-2);
    ?>"style="516px;"/></P>
    <P>
    <inputtype="submit"name="button"value="普通地址->迅雷地址"/>
    <inputtype="submit"name="button"value="迅雷地址->普通地址"/></P>
    <h3>FlashGet转换</h3>
    <P>FlashGet地址:
    <inputname="text2"value="<?phpecho$txt2;?>"type="text"style="516px;"/></P>
    <P>转换后地址:
    <inputtype="text"value="<?php
    if($button=="普通地址->FlashGet地址")echo"flashget://".base64_encode($txt2);
    if($button=="FlashGet地址->普通地址")echostr_ireplace("[FLASHGET]","",base64_decode(str_ireplace("flashget://","",$txt2)));
    ?>"style="516px;"/></P>
    <P>
    <inputtype="submit"value="普通地址->FlashGet地址"name="button"/>
    <inputtype="submit"value="FlashGet地址->普通地址"name="button"/></P>
    <h3>QQ旋风转换</h3>
    <P>QQ旋风地址:
    <inputname="text3"value="<?phpecho$txt3;?>"type="text"style="516px;"/></P>
    <P>转换后地址:
    <inputtype="text"value="<?php
    if($button=="普通地址->QQ旋风")echo"qqdl://".base64_encode($txt3);
    if($button=="QQ旋风->普通地址")echobase64_decode(str_ireplace("qqdl://","",$txt3));
    ?>"style="516px;"/></P>
    <P>
    <inputtype="submit"value="普通地址->QQ旋风"name="button"/>
    <inputtype="submit"value="QQ旋风->普通地址"name="button"/></P>
    </form>
    </body>
    </html>

    VB版

    注:其中DigestStrToHexStr为可在程序外部调用加密函数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    Option Explicit
    'B as e64Encoding/DecodingAlgorithm
    'By:DavidMidkif f(mznull@earthlink.net)
    '
    'Thisalgorithmsencodes and decodesdatain to B as e64
    'for mat.Thisfor matisextremelymoreefficientthan
    'Hexadecimalencoding.
    Private m_bytIndex(0 To 63) As Byte
    Private m_bytReverseIndex(0 To 255) As Byte
    Private Const k_bytEqualSign As Byte = 61
    Private Const k_bytmask1 As Byte = 3
    Private Const k_bytmask2 As Byte = 15
    Private Const k_bytmask3 As Byte = 63
    Private Const k_bytmask4 As Byte = 192
    Private Const k_bytmask5 As Byte = 240
    Private Const k_bytmask6 As Byte = 252
    Private Const k_bytShift2 As Byte = 4
    Private Const k_bytShift4 As Byte = 16
    Private Const k_bytShift6 As Byte = 64
    Private Const k_lMaxBytesPerLine As Long = 152
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As LongByVal Source As LongByVal Length As Long)
    Public Function Decode64(sInput As StringAs String
    If sInput = "" Then Exit Function
    Decode64 = StrConv(DecodeArray64(sInput), vbUnicode)
    End Function
    Private Function DecodeArray64(sInput As StringAs Byte()
    Dim bytInput() As Byte
    Dim bytWorkspace() As Byte
    Dim bytResult() As Byte
    Dim lInputCounter As Long
    Dim lWorkspaceCounter As Long
    bytInput = Replace(Replace(sInput, vbCrLf, ""), "=""")
    ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 2)) As Byte
    lWorkspaceCounter = LBound(bytWorkspace)
    For lInputCounter = LBound(bytInput) To UBound(bytInput)
        bytInput(lInputCounter) = m_bytReverseIndex(bytInput(lInputCounter))
    Next lInputCounter
    For lInputCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 8) + 8)) Step 8
        bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
        bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4)  k_bytShift2)
        bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytmask1) * k_bytShift6) + bytInput(lInputCounter + 6)
        lWorkspaceCounter = lWorkspaceCounter + 3
    Next lInputCounter
    Select Case (UBound(bytInput) Mod 8):
        Case 3:
            bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
        Case 5:
            bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
            bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4)  k_bytShift2)
            lWorkspaceCounter = lWorkspaceCounter + 1
        Case 7:
            bytWorkspace(lWorkspaceCounter) = (bytInput(lInputCounter) * k_bytShift2) + (bytInput(lInputCounter + 2)  k_bytShift4)
            bytWorkspace(lWorkspaceCounter + 1) = ((bytInput(lInputCounter + 2) And k_bytmask2) * k_bytShift4) + (bytInput(lInputCounter + 4)  k_bytShift2)
            bytWorkspace(lWorkspaceCounter + 2) = ((bytInput(lInputCounter + 4) And k_bytmask1) * k_bytShift6) + bytInput(lInputCounter + 6)
            lWorkspaceCounter = lWorkspaceCounter + 2
    End Select
    ReDim bytResult(LBound(bytWorkspace) To lWorkspaceCounter) As Byte
    If LBound(bytWorkspace) = 0 Then lWorkspaceCounter = lWorkspaceCounter + 1
        CopyMemoryVarPtr (bytResult(LBound(bytResult))), VarPtr(bytWorkspace(LBound(bytWorkspace))), lWorkspaceCounter
        DecodeArray64 = bytResult
    End Function
    Public Function Encode64(ByRefsInput As StringAs String
    If sInput = "" Then Exit Function
    Dim bytTemp() As Byte
    bytTemp = StrConv(sInput, vbFromUnicode)
    Encode64 = EncodeArray64(bytTemp)
    End Function
    Private Function EncodeArray64(ByRefbytInput() As ByteAs String
    On Error GoTo ErrorHandler
    Dim bytWorkspace() As Byte, bytResult() As Byte
    Dim bytCrLf(0 To 3) As Byte, lCounter As Long
    Dim lWorkspaceCounter As Long, lLineCounter As Long
    Dim lCompleteLines As Long, lBytesRemaining As Long
    Dim lpWorkSpace As Long, lpResult As Long
    Dim lpCrLf As Long
    If UBound(bytInput) < 1024 Then
        ReDim bytWorkspace(LBound(bytInput) To (LBound(bytInput) + 4096)) As Byte
    Else
        ReDim bytWorkspace(LBound(bytInput) To (UBound(bytInput) * 4)) As Byte
    End If
    lWorkspaceCounter = LBound(bytWorkspace)
    For lCounter = LBound(bytInput) To (UBound(bytInput) - ((UBound(bytInput) Mod 3) + 3)) Step 3
        bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
        bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytmask1) * k_bytShift4) + ((bytInput(lCounter + 1))  k_bytShift4))
        bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex(((bytInput(lCounter + 1) And k_bytmask2) * k_bytShift2) + (bytInput(lCounter + 2)  k_bytShift6))
        bytWorkspace(lWorkspaceCounter + 6) = m_bytIndex(bytInput(lCounter + 2) And k_bytmask3)
        lWorkspaceCounter = lWorkspaceCounter + 8
    Next lCounter
    Select Case (UBound(bytInput) Mod 3):
        Case 0:
            bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
            bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex((bytInput(lCounter) And k_bytmask1) * k_bytShift4)
            bytWorkspace(lWorkspaceCounter + 4) = k_bytEqualSign
            bytWorkspace(lWorkspaceCounter + 6) = k_bytEqualSign
        Case 1:
            bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
            bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytmask1) * k_bytShift4) + ((bytInput(lCounter + 1))  k_bytShift4))
            bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex((bytInput(lCounter + 1) And k_bytmask2) * k_bytShift2)
            bytWorkspace(lWorkspaceCounter + 6) = k_bytEqualSign
        Case 2:
            bytWorkspace(lWorkspaceCounter) = m_bytIndex((bytInput(lCounter)  k_bytShift2))
            bytWorkspace(lWorkspaceCounter + 2) = m_bytIndex(((bytInput(lCounter) And k_bytmask1) * k_bytShift4) + ((bytInput(lCounter + 1))  k_bytShift4))
            bytWorkspace(lWorkspaceCounter + 4) = m_bytIndex(((bytInput(lCounter + 1) And k_bytmask2) * k_bytShift2) + ((bytInput(lCounter + 2))  k_bytShift6))
            bytWorkspace(lWorkspaceCounter + 6) = m_bytIndex(bytInput(lCounter + 2) And k_bytmask3)
    End Select
    lWorkspaceCounter = lWorkspaceCounter + 8
    If lWorkspaceCounter <= k_lMaxBytesPerLine Then
        EncodeArray64 = Left$(bytWorkspace, InStr(1, bytWorkspace, Chr$(0)) - 1)
    Else
        bytCrLf(0) = 13
        bytCrLf(1) = 0
        bytCrLf(2) = 10
        bytCrLf(3) = 0
    ReDim bytResult(LBound(bytWorkspace) To UBound(bytWorkspace))
    lpWorkSpace = VarPtr(bytWorkspace(LBound(bytWorkspace)))
    lpResult = VarPtr(bytResult(LBound(bytResult)))
    lpCrLf = VarPtr(bytCrLf(LBound(bytCrLf)))
    lCompleteLines = Fix(lWorkspaceCounter / k_lMaxBytesPerLine)
    For lLineCounter = 0 To lCompleteLines
        CopyMemorylpResult , lpWorkSpace, k_lMaxBytesPerLine
        lpWorkSpace = lpWorkSpace + k_lMaxBytesPerLine
        lpResult = lpResult + k_lMaxBytesPerLine
        CopyMemorylpResult , lpCrLf, 4&
        lpResult = lpResult + 4&
    Next lLineCounter
    lBytesRemaining = lWorkspaceCounter - (lCompleteLines * k_lMaxBytesPerLine)
    If lBytesRemaining > 0 Then CopyMemorylpResult , lpWorkSpace, lBytesRemaining
        EncodeArray64 = Left$(bytResult, InStr(1, bytResult, Chr$(0)) - 1)
    End If
    Exit Function
    ErrorHandler:
        Er As ebytResult
        EncodeArray64 = bytResult
    End Function

    C#版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    直接使用.NET中的的库类函数
    方法:
    ///<summary>
    ///Base64加密
    ///</summary>
    ///<paramname="Message"></param>
    ///<returns></returns>
    publicstringBase64Code(stringMessage)
    {
    byte[]bytes=Encoding.Default.GetBytes(Message);
    returnConvert.ToBase64String(bytes);
    }
    ///<summary>
    ///Base64解密
    ///</summary>
    ///<paramname="Message"></param>
    ///<returns></returns>
    publicstringBase64Decode(stringMessage)
    {
    byte[]bytes=Convert.FromBase64String(Message);
    returnEncoding.Default.GetString(bytes);
    }

    MIME

    编辑
    在MIME格式的电子邮件中,base64可以用来将binary的字节序列数据编码成ASCII字符序列构成的文本。使用时,在传输编码方式中指定base64。使用的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。
    完整的base64定义可见 RFC1421和 RFC2045。编码后的数据比原始数据略长,为原来的4/3。在电子邮件中,根据RFC822规定,每76个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的135.1%。
    转换的时候,将三个byte的数据,先后放入一个24bit的缓冲区中,先来的byte占高位。数据不足3byte的话,于缓冲区中剩下的Bit用0补足。然后,每次取出6个bit,按照其值选择ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
    如果最后剩下两个输入数据,在编码结果后加1个“=”;如果最后剩下一个输入数据,编码结果后加2个“=”;如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
    举例来说,一段引用自Thomas Hobbes's Leviathan的文句:
    Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.
    经过base64编码之后变成:
    TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
    IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
    dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
    dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
    ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=
  • 相关阅读:
    windowssdk编程从简单的对话框开始
    面向扣扣编程知识一
    循序渐进DLL编程(二)
    西方经济学导论
    循序渐进DLL编程(五)
    HLSL Effect的vertex shader和pixel shader的参数传递
    Directx11 HelloWorld之与Directx9的比较
    Directx11 HelloWorld之简单三角形绘制
    正式开始记录自己学习历程
    坐标系的转换
  • 原文地址:https://www.cnblogs.com/jack-hzm/p/10172088.html
Copyright © 2011-2022 走看看