h5前端必需了解的异或加密解密

在当前h5各种活动漫天轰炸的时代,大量的访问量给h5带来了机遇,同时也带来了一些安全隐患,如何能对数据进行一些合理的加密成了我们H5必须考虑的问题,今天就先写下异或

一、 XOR 运算

逻辑运算之中,除了 AND OR ,还有一种 XOR 运算,中文称为"异或运算"。

它的定义是:两个值相同时,返回 false ,否则返回 true 。也就是说, XOR 可以用来判断两个值是否不同。

true XOR true // false false XOR false // false true XOR false // true true XOR false // true

上面代码中,如果两个二进制位相同,就返回 0 ,表示 false ;否则返回 1 ,表示 true

二、 XOR 的应用

XOR 运算有一个很奇妙的特点:如果对一个值连续做两次 XOR,会返回这个值本身。

// 第一次 XOR 1010 ^ 1111 // 0101 // 第二次 XOR 0101 ^ 1111 // 1010

上面代码中,原始值是 1010 ,再任意选择一个值(上例是 1111 ),做两次 XOR,最后总是会得到原始值 1010 。这在数学上是很容易证明的。

三、加密应用

XOR 的这个特点,使得它可以用于信息的加密。

message XOR key // cipherText cipherText XOR key // message

上面代码中,原始信息是 message ,密钥是 key ,第一次 XOR 会得到加密文本 cipherText 。对方拿到以后,再用 key 做一次 XOR 运算,就会还原得到 message

理由很简单,如果每次的 key 都是随机的,那么产生的 CipherText 具有所有可能的值,而且是均匀分布,无法从 CipherText 看出 message 的任何特征。也就是说,它具有最大的"信息熵",因此完全不可能破解。这被称为 XOR 的 "完美保密性" (perfect secrecy)。

满足上面两个条件的 key ,叫做 one-time pad (缩写为OTP),意思是"一次性密码本",因为以前这样的 key 都是印刷成密码本,每次使用的时候,必须从其中挑选 key

五、实例:哈希加密

下面的例子使用 XOR,对用户的登陆密码进行加密。实际运行效果看 这里

// 生成一个随机整数,范围是 [min, max] function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; // 生成一个随机的十六进制的值,在 0 ~ f 之间 function getHex() { let n = 0; for (let i = 4; i > 0; i--) { n = (getRandomInt(0, 1) << (i - 1)) + n; return n.toString(16); // 生成一个32位的十六进制值,用作一次性 Key function getOTP() { const arr = []; for (let i = 0; i < 32; i++) { arr.push(getHex()); return arr.join('');

上面代码中,生成的 key 是32位的十六进制值,对应 MD5 产生的128位的二进制哈希。

第三步,进行 XOR 运算,求出加密后的 message

function getXOR(message, key) { const arr = []; for (let i = 0; i < 32; i++) { const m = parseInt(message.substr(i, 1), 16); const k = parseInt(key.substr(i, 1), 16); arr.push((m ^ k).toString(16)); return arr.join('');

使用这种方法保存用户的登陆密码,即使加密文本泄露,只要一次性的密钥( key )没有泄露,对方也无法破解。

  典型XOR解密及unicode转义汉字
  // 异或解密(异或加密相当于一个双重加密,双重保障更安全)
export function Restore(str, keyIndex)
    var crytxt = '';
    var k, keylen = keyIndex.length;
    for(var i=0; i<str.length; i++) {
      k = i % keylen;
      crytxt += String.fromCharCode(str.charCodeAt(i) ^ keyIndex.charCodeAt(k));
    return toChineseWords(crytxt);
export function toChineseWords(data){
  var str= unescape(data.replace(/\\/g, "%"));