zqifa的博客

我不管,反正我最萌~

js实现base64编码解码

Base64编码解码原理介绍

1.Base64使用A-Z,a-z,0-9,+,/ 这64个字符.
2.编码原理:将3个字节转换成4个字节( (3X8)=24=(4X6) )先读入3个字节,每读一个字节,左移8位,再右移四次,每次6位,这样就有4个字节了.
3.解码原理:将4个字节转换成3个字节.先读入4个6位(用或运算),每次左移6位,再右移3次,每次8位.这样就还原了.

Base64是一种很常见的编码规范,其作用是将二进制序列转换为人类可读的ASCII字符序列,常用在需用通过文本协议(比如HTTP和SMTP)来传输二进制数据的情况下。Base64并不是一种用于安全领域的加密解密算法(这类算法有DES等),尽管我们有时也听到使用Base64来加密解密的说法,但这里所说的加密与解密实际是指编码(encode)和解码(decode)的过程,其变换是非常简单的,仅仅能够避免信息被直接识别。

Base64采用了一种很简单的编码转换:对于待编码数据,以3个字节为单位,依次取6位数据并在前面补上两个0形成新的8位编码,由于3*8=4*6,这样3个字节的输入会变成4个字节的输出,长度上增加了1/3。

上面的处理还不能保证得到的字符都是可见字符,为了达到此目的,Base64制定了一个编码表,进行统一的转换。码表的大小为2^6=64,这也是Base64名称的由来。

另外还有一点要注意的地方,前面提到编码是以3个字节为单位,当剩下的字符数量不足3个字节时,则应使用0进行填充,相应的,输出字符则使用’=‘占位,因此编码后输出的文本末尾可能会出现1至2个’=‘。

具体转换步骤:
第一步:将待转换的字符串转为一个个字符
第二步:计算每一个字符对应的ASCII码十进制
第三步:计算出十进制对应的二进制,若不足8位,在前面添加0进行补全
第四步:将8位的二进制码,按照6个6个一组划分,若不能整除6,在最末添加0补足6位
第五步:计算对应的十进制编码
第六步:按照base64表,查看对应的字符
第七步:将加密后的字符3个3个分成一组,不足3位的添加=进行补全
第八步:得到最终结果

同时得到base64位加密后的特征:
1.长度是3的倍数
2.只含有65中字符,大写的A至Z,小写的a至z,数字0到9,以及3种符号+/ =,=最多两个,且在末尾

方法1:js编码实现Base64编码解码函数

完整代码:

<script>
/**
 * Base64 编码工具,完美的支持 unicode 编码的字符串
 * Base64 加密解密使用方法:
 * Base64.encode('中文') --> 5Lit5paH
 * Base64.decode('5Lit5paH') --> 中文
 */
var Base64 = {
    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    // public method for encoding
    encode : function(input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
        input = Base64._utf8_encode(input);
        while (i < input.length) {
            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            output = output +
            this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
            this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
        }
        return output;
    },
    // public method for decoding
    decode : function(input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        while (i < input.length) {
            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            output = output + String.fromCharCode(chr1);
            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        output = Base64._utf8_decode(output);
        return output;
    },
    // private method for UTF-8 encoding
    _utf8_encode : function(string) {
        string = string.replace(/\r\n/g, "\n");
        var utftext = "";
        for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if ((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String
                        .fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
        }
        return utftext;
    },
    // private method for UTF-8 decoding
    _utf8_decode : function(utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;
        while (i < utftext.length) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if ((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6)
                        | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i + 1);
                c3 = utftext.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12)
                        | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }
}
</script>

方法2:使用btoa和atob进行Base64的编码和解码

btoa 和 atob 是window对象的两个函数,其中:
1.btoa:是binary to ascii,用于将binary的数据用ascii码表示,即Base64的编码过程。
2.atob:是ascii to binary,用于将ascii码解析成binary数据,即Base64的解码过程。

btoa 和 atob 使用方法:
window.atob(string)/atob(string):解码,用来解码一个已经被base-64编码过的字符串。(参数string: 必需是一个通过 btoa() 方法编码的字符串)。
window.btoa(string)/btoa(string):编码,用来创建一个 base-64编码的字符串。

不过想对Unicode字符编码进行编码,直接使用btoa不行的,需要使用encodeURIComponentdecodeURIComponent方法。因为 btoa 仅支持 ASCII 字符序列,如所以我们要先使用 encodeURIComponent ,将中文字符编码转变成ASCII字符序列。

编码时,先用encodeURIComponent对字符串进行编码,再用btoa进行Base64编码;
解码时,先用atob对Base64编码的串进行解码,再用decodeURIComponent对字符串进行解码

注意:
编码的过程:Unicode字符 ——-> 先encodeURI ——-> 再btoa编码
解码的过程:先atob解码 ——-> 再decodeURI ——-> Unicode字符

示例代码:


//编码,输出:"MTIzNDU2"
window.btoa("123456");
//解码,输出:123456
window.atob("MTIzNDU2");

// 编码,输出:"5Lit5paH"
btoa(unescape(encodeURIComponent("中文")))
// 解码,输出:"中文"
decodeURIComponent(escape(atob("5Lit5paH")))

注意:
1.在使用atob和btoa这两个函数时需要注意的是,IE9是不支持的(虽然现在基本都是面向Chrome浏览器编程)。
2.我们使用第三方Base64工具:webtoolkit.base64是一个第三方实现的 Base64 编码工具,完美的支持 unicode 编码的字符串。

done!

作者:zqifa

出处:https://www.l1mn.com

原文地址:https://www.l1mn.com/p/rwhq71.html

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

公告

昵称:zqifa

站龄: 3年8个月

博客持续完善ing,敬请期待...

打滚求打赏(๑ ̄ ̫  ̄๑)

此处弱弱求打赏~~万一有好心人呢~~

支付宝酱

支付宝赞助

微信酱

微信赞助

随笔分类

php(110)

linux(63)

python(44)

web前端(39)

js(35)

服务器(33)

mysql(30)

html(24)

docker(23)

centos(22)

windows(22)

django(20)

前端设计(18)

git(16)

数据库(14)

算法(14)

常用软件(14)

编程进阶(13)

字符编码(13)

jquery(12)

更多

我的标签

php(106)

linux(47)

python(45)

js(34)

mysql(30)

centos(28)

web前端(23)

windows(22)

docker(22)

django(20)

更多

相册

Copyright © zqifa 联系方式:z___qf@163.com