如何理解「異或(XOR)」運算在計算機科學中的重要性?(轉自-阿里聚安全)

XOR加密是一種簡單高效、很是安全的加密方法webpack

1、 XOR 運算

邏輯運算之中,除了 ANDOR,還有一種 XOR 運算,中文稱爲"異或運算"。web

它的定義是:兩個值相同時,返回false,不然返回true。也就是說,XOR能夠用來判斷兩個值是否不一樣。算法

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

JavaScript 語言的二進制運算,有一個專門的 XOR 運算符,寫做^。安全

1 ^ 1 // 0
0 ^ 0 // 0
1 ^ 0 // 1
0 ^ 1 // 1

上面代碼中,若是兩個二進制位相同,就返回0,表示false;不然返回1,表示true。dom

2、 XOR 的應用

XOR 運算有一個很奇妙的特色:若是對一個值連續作兩次 XOR,會返回這個值自己。加密

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

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

上面代碼中,原始值是1010,再任意選擇一個值(上例是1111),作兩次 XOR,最後老是會獲得原始值1010。這在數學上是很容易證實的。code

3、加密應用

XOR 的這個特色,使得它能夠用於信息的加密。blog

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

上面代碼中,原始信息是message,密鑰是key,第一次 XOR 會獲得加密文本cipherText。對方拿到之後,再用key作一次 XOR 運算,就會還原獲得message。ip

4、完美保密性

二戰期間,各國爲了電報加密,對密碼學進行了大量的研究和實踐,其中就包括 XOR 加密。md5

戰後,美國數學家香農(Claude Shannon)將他的研究成果公開發表,證實了只要知足兩個條件,XOR 加密是沒法破解的。

key的長度大於等於message key必須是一次性的,且每次都要隨機產生

理由很簡單,若是每次的key都是隨機的,那麼產生的CipherText具備全部可能的值,並且是均勻分佈,沒法從CipherText看出message的任何特徵。也就是說,它具備最大的"信息熵",所以徹底不可能破解。這被稱爲 XOR 的"完美保密性"(perfect secrecy)。

知足上面兩個條件的key,叫作 one-time pad(縮寫爲OTP),意思是"一次性密碼本",由於之前這樣的key都是印刷成密碼本,每次使用的時候,必須從其中挑選key。

5、實例:哈希加密

下面的例子使用 XOR,對用戶的登錄密碼進行加密。實際運行效果看這裏

第一步,用戶設置登錄密碼的時候,算出這個密碼的哈希,這裏使用的是 MD5 算法,也能夠採用其餘哈希算法。

const message = md5(password);

第二步,生成一個隨機的 key。

// 生成一個隨機整數,範圍是 [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)沒有泄露,對方也沒法破解。

相關文章
相關標籤/搜索