[js进阶]js自带的对称加密
前言
在登陆界面开发中,用户勾选了记住账号密码,账号密码信息被存储到cookies或localStorage中,此时我们不希望它是以明文的方式存储的,需要对其进行加密,同时又需要在下次用户登陆时从本地取出账号密码信息并解密,这便需要使用对称加密算法,通常使用的加密算法有DES 算法等。
下载第三方的对称加密包,例如CryptoJS,似乎又会增加打包的体积,因为我们的需求很简单,仅仅只是实现简单的对称加密,window对象中的btoa,atob函数能很轻便的完成这件事。
WindowOrWorkerGlobalScope.btoa()
WindowOrWorkerGlobalScope.btoa() 从 String 对象中创建一个 base-64 编码的 ASCII 字符串,其中字符串中的每个字符都被视为一个二进制数据字节。
Note: 由于这个函数将每个字符视为二进制数据的字节,而不管实际组成字符的字节数是多少,所以如果任何字符的码位 (en-US)超出 0x00 ~ 0xFF 这个范围,则会引发 InvalidCharacterError 异常。请参阅 Unicode_字符串 ,该示例演示如何编码含有码位超出 0x00 ~ 0xFF 范围的字符的字符串。
语法
let encodedData = window.btoa(stringToEncode);
参数
-  
   stringToEncode一个字符串, 其字符分别表示要编码为 ASCII 的二进制数据的单个字节。 
返回值
一个包含 stringToEncode 的 Base64 表示的字符串。
示例
let encodedData = window.btoa("Hello, world"); // 编码
let decodedData = window.atob(encodedData);    // 解码
备注
你可以使用此方法对可能导致通信问题的数据进行编码,传输,然后使用 atob() 方法再次解码数据。例如,可以编码控制字符,包括 ASCII 值为 0 到 31 的字符。
在用 JavaScript 编写 XPCOM 组件时,btoa() 方法也是可用的,虽然全局对象已经不是 Window 了。
Unicode 字符串
在多数浏览器中,使用 btoa() 对 Unicode 字符串进行编码都会触发 InvalidCharacterError 异常。
一种选择是转义任何扩展字符,以便实际编码的字符串是原始字符的 ASCII 表示形式。考虑这个例子,代码来自 Johan Sundström:
// ucs-2 string to base64 encoded ascii
function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
// base64 encoded ascii to ucs-2 string
function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
}
// Usage:
utoa('✓ à la mode'); // 4pyTIMOgIGxhIG1vZGU=
atou('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
utoa('I \u2661 Unicode!'); // SSDimaEgVW5pY29kZSE=
atou('SSDimaEgVW5pY29kZSE='); // "I ♡ Unicode!"
更好、更可靠、性能更优异的解决方案是使用类型化数组进行转换。
规范
| 规范 | 状态 | 备注 | 
|---|---|---|
| HTML Living Standard WindowOrWorkerGlobalScope.btoa() | Living Standard | Method moved to the WindowOrWorkerGlobalScopemixin in the latest spec. | 
| HTML 5.1 WindowBase64.btoa() | Recommendation | Snapshot of HTML Living Standard. No change. | 
| HTML5 WindowBase64.btoa() | Recommendation | Snapshot of HTML Living Standard. Creation of WindowBase64(properties where on the target before it). | 
Polyfill
// Polyfill from  https://github.com/MaxArt2501/base64-js/blob/master/base64.js
(function() {
    // base64 character set, plus padding character (=)
    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        // Regular expression to check formal correctness of base64 encoded strings
        b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
    window.btoa = window.btoa || function(string) {
        string = String(string);
        var bitmap, a, b, c,
            result = "",
            i = 0,
            rest = string.length % 3; // To determine the final padding
        for (; i < string.length;) {
            if ((a = string.charCodeAt(i++)) > 255 ||
                (b = string.charCodeAt(i++)) > 255 ||
                (c = string.charCodeAt(i++)) > 255)
                throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
            bitmap = (a << 16) | (b << 8) | c;
            result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) +
                b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
        }
        // If there's need of padding, replace the last 'A's with equal signs
        return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
    };
    window.atob = window.atob || function(string) {
        // atob can work with strings with whitespaces, even inside the encoded part,
        // but only \t, \n, \f, \r and ' ', which can be stripped.
        string = String(string).replace(/[\t\n\f\r ]+/g, "");
        if (!b64re.test(string))
            throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
        // Adding the padding if missing, for semplicity
        string += "==".slice(2 - (string.length & 3));
        var bitmap, result = "",
            r1, r2, i = 0;
        for (; i < string.length;) {
            bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 |
                (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));
            result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) :
                r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) :
                String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
        }
        return result;
    };
})()
参考
-  
   Base64 encoding and decoding
-  
   dataURI
-  
   atob()
-  
   Components.utils.importGlobalProperties 
