nodeJS之crypto模組公鑰加密及解密

龍恩0707發表於2018-06-03

nodeJS之crypto模組公鑰加密及解密

NodeJS有以下4個與公鑰加密相關的類。
1. Cipher: 用於加密資料;
2. Decipher: 用於解密資料;
3. Sign: 用於生成簽名;
4. Verify: 用於驗證簽名;

在使用公鑰加密技術時,需要使用公鑰及私鑰,公鑰是用於建立只有私鑰的擁有者能夠讀出的加密資料,以及對私鑰的擁有者的簽名進行驗證;私鑰是用於解密資料以及對資料進行簽名。

一:加密資料
在crypto模組中,Cipher類用於對資料進行加密操作;我們可以通過如下兩種方式建立cipher物件;

1.1 createCipher方法;該方法使用指定的演算法與密碼來建立cipher物件。該方法使用方式如下:

crypto.createCipher(params, pasword);

該方法使用兩個引數,第一個引數用於指定在加密資料時所使用的演算法,比如 'ase-256-cbc'這些等,第二個引數用於指定加密時所使用的密碼,該引數值必須為一個二進位制格式的字串或一個Buffer物件。

createCipher 方法返回一個被建立的cipher物件。

1.2 createCipheriv方法;該方法使用指定的演算法、密碼與初始向量、來建立cipher物件,使用方法如下所示:

crypto.createCipheriv(params, password, iv);

該方法的第一個引數是在加密資料時所使用的演算法,比如 'ase-256-cbc'等等,第二個引數用於指定加密時所使用的密碼,該引數值必須為一個二進位制格式的字串或一個Buffer物件。 第三個引數指定加密時所使用的初始向量,引數值也必須為一個二進位制格式的字串或一個Buffer物件。
該方法返回的也是一個被建立的cipher物件。

1.3 在上面通過兩種方式建立了cipher物件後,可以通過使用該物件的update方法來指定需要被加密的資料,該方法使用的方式如下:

cipher.update(data, [input_encoding], [output_encoding])

其中第一個引數為必選項(其他的引數為可選項), 該引數值是一個Buffer物件或一個字串,用於指定需要加密的資料。第二個引數用於指定被加密的資料所使用的編碼格式,可指定引數值為 'utf-8', 'ascii' 或 'binary'. 如果不使用第二個引數的話,那麼第一個引數必須為一個Buffer物件。
第三個引數用於指定輸出加密資料時使用的編碼格式,可指定的引數值為 'hex', 'binary' 或 'base64' 等。如果不使用第三個引數的話,該方法就返回了一個存放了加密資料的Buffer物件。

1.4 可以使用cipher物件的final方法來返回加密資料。當該方法被呼叫時,任何cipher物件中所快取的資料都將被加密。在使用了cipher物件的final方法
後,不能再向cipher物件中追加加密資料,該方法使用方式如下:

cipher.final([output_encoding]);

該方法使用一個可選引數,該引數值為一個字串,用於指定在輸出加密資料的編碼格式,可指定引數值為 'hex', 'binary', 及 'base64'. 如果使用了
該引數,那麼final方法返回字串格式的加密資料,如果不使用該引數,那麼該方法就返回一個Buffer物件。

具體使用的程式碼如下:

const crypto = require('crypto');

/*
 下面是使用加密演算法對 '我不是笨蛋' 幾個字進行加密,所加密使用的密碼是 123456
*/
const data = '我不是笨蛋';
const password = '123456';

// 建立加密演算法
const aseEncode = function(data, password) {

  // 如下方法使用指定的演算法與密碼來建立cipher物件
  const cipher = crypto.createCipher('aes192', password);

  // 使用該物件的update方法來指定需要被加密的資料
  let crypted = cipher.update(data, 'utf-8', 'hex');

  crypted += cipher.final('hex');

  return crypted;
};

console.log(aseEncode(data, password)); // 輸出 ebdf98c254b9aa5265f6d4a5e73f861d

二:解密資料

在crypto模組中,Decipher類用於對加密後的資料進行解密操作。
建立一個decipher物件,可以通過如下兩種方式進行建立:

2.1 createDecipher方法,該方法使用指定的演算法與密碼來建立 decipher物件,該方法使用的方式如下:

crypto.createDecipher(params, password);

在該方法中,第一個引數用於指定在解密資料時所使用的演算法,比如 'aes-256-cbc'等,該演算法必須與加密資料時所使用的演算法保持一致。
第二個引數用於指定解密時所使用的密碼,其引數值為一個二進位制格式的字串或一個Buffer物件,該密碼同樣必須與加密該資料時所使用的密碼保持一致。

createDecipher方法返回一個被建立的 decipher物件。

2.2 createDecipheriv方法;該方法使用指定的演算法、密碼與初始向量來建立decipher物件。該方法使用如下所示:

crypto.createDecipheriv(params, password, iv);

在該方法中,第一個引數用於指定在解密資料時所使用的演算法,比如 'aes-256-cbc'等,該演算法必須與加密資料時所使用的演算法保持一致。第二個引數用於指定解密時所使用的密碼,引數值必須為一個二進位制格式的字串或一個Buffer物件,同樣的道理,該密碼必須與加密該資料時所使用的密碼保持一致。 
第三個引數用於指定解密時所使用的初始向量,該引數值也必須為一個二進位制格式的字串或者一個Buffer物件,該初始向量必須與加密該資料時所使用的初始向量保持一致。

2.3 在建立了decipher物件之後,可以通過使用該物件的update方法來指定需要被解密的資料。該方法使用如下所示:

decipher.update(data, [input_encoding], [output_encoding]);

在該方法中,第一個引數為一個Buffer物件或一個字串,用於指定需要被解密的資料,第二個引數用於指定被解密資料所使用的編碼格式,可指定的引數值為 'hex', 'binary', 'base64'等,如果不使用第二個引數的話,那麼引數值必須為一個buffer物件。第三個引數用於指定輸出解密資料時使用的編碼格式,可選引數值為'utf-8', 'ascii' 或 'binary';

2.4 可以使用decipher物件的final方法來返回經過解密之後的原始資料,該方法使用如下所示:

decipher.final([output_encoding]);

在該物件的final方法中,使用了一個可選引數,引數值為一個字串,用於指定在輸出解密資料時使用的編碼格式,可指定引數值為 'utf-8', 'ascii' 或 'binary';
如果使用了 該引數,final返回字串格式的解密資料,如果不使用該引數,final方法返回一個Buffer物件。

如下解密資料的程式碼:

const crypto = require('crypto');

/*
 下面是使用加密演算法對 '我不是笨蛋' 幾個字進行加密,所加密使用的密碼是 123456
*/
const data = '我不是笨蛋';
const password = '123456';

// 建立加密演算法
const aseEncode = function(data, password) {

  // 如下方法使用指定的演算法與密碼來建立cipher物件
  const cipher = crypto.createCipher('aes192', password);

  // 使用該物件的update方法來指定需要被加密的資料
  let crypted = cipher.update(data, 'utf-8', 'hex');

  crypted += cipher.final('hex');

  return crypted;
};

console.log(aseEncode(data, password)); // 輸出 ebdf98c254b9aa5265f6d4a5e73f861d

// 建立解密演算法
const aseDecode = function(data, password) {
  /* 
   該方法使用指定的演算法與密碼來建立 decipher物件, 第一個演算法必須與加密資料時所使用的演算法保持一致;
   第二個引數用於指定解密時所使用的密碼,其引數值為一個二進位制格式的字串或一個Buffer物件,該密碼同樣必須與加密該資料時所使用的密碼保持一致
  */
  const decipher = crypto.createDecipher('aes192', password);

  /*
   第一個引數為一個Buffer物件或一個字串,用於指定需要被解密的資料
   第二個引數用於指定被解密資料所使用的編碼格式,可指定的引數值為 'hex', 'binary', 'base64'等,
   第三個引數用於指定輸出解密資料時使用的編碼格式,可選引數值為 'utf-8', 'ascii' 或 'binary';
  */
  let decrypted = decipher.update(data, 'hex', 'utf-8');

  decrypted += decipher.final('utf-8');
  return decrypted;
}; 

console.log(aseDecode(aseEncode(data, password), password)); // 輸出  我不是笨蛋

相關文章