[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 WindowOrWorkerGlobalScope mixin 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
-
data
URI -
atob()
-
Components.utils.importGlobalProperties