node資料加密,還不快快點進來?

鮑康霖發表於2018-06-07

crypto模組

node.js中crypto 模組提供了加密功能,包含對 OpenSSL 的雜湊、HMAC、加密、解密、簽名、以及驗證功能的一整套封裝。 使用 require('crypto') 來訪問該模組。

let cryto = require('crypto');
console.log(cryto.getHashes());
複製程式碼

cryto模組支援下列陣列中的雜湊雜湊演算法

[ 'DSA', 'DSA-SHA', 'DSA-SHA1', 'DSA-SHA1-old', 'RSA-MD4', 'RSA-MD5', 'RSA-MDC2', 'RSA-RIPEMD160', 'RSA-SHA', 'RSA-SHA1', 'RSA-SHA1-2', 'RSA-SHA224', 'RSA-SHA256', 'RSA-SHA384', 'RSA-SHA512', 'dsaEncryption', 'dsaWithSHA', 'dsaWithSHA1', 'dss1', 'ecdsa-with-SHA1', 'md4', 'md4WithRSAEncryption', 'md5', 'md5WithRSAEncryption', 'mdc2', 'mdc2WithRSA', 'ripemd', 'ripemd160', 'ripemd160WithRSA', 'rmd160', 'sha', 'sha1', 'sha1WithRSAEncryption', 'sha224', 'sha224WithRSAEncryption', 'sha256', 'sha256WithRSAEncryption', 'sha384', 'sha384WithRSAEncryption', 'sha512', 'sha512WithRSAEncryption', 'shaWithRSAEncryption', 'ssl2-md5', 'ssl3-md5', 'ssl3-sha1', 'whirlpool' ]

常見的幾種演算法

1 雜湊(雜湊)演算法

node資料加密,還不快快點進來?
  • 特性
    1. 不可逆,不能從輸出推算出輸入的值
    2. 不管加密內容多長,最後輸出的結果長度相等
    3. 內容不同,輸出的結果就完全不同,內容相同,則輸出的結果相同

例:md5摘要演算法

雖然人們經常說md5加密,但實際上,md5屬於摘要演算法,他是不可逆的,確切的說,他不是加密演算法。市面上常見的md5解密網站也並不是真的將md5摘要演算法的結果逆向解密出來,而是通過撞庫的方式,硬生生裝出來的。
複製程式碼
let md5 = crypto.createHash('md5');
md5.update('123456'); // update資料
let result = md5.digest('hex') // 十六進位制輸出
console.log(result) // e10adc3949ba59abbe56e057f20f883e
複製程式碼

在呼叫digest方法之前,可以多次呼叫update方法新增資料,但是在呼叫digest方法之後,無法再繼續使用update方法

let md5 = crypto.createHash('md5');
md5.update('123');
md5.update('456');
let result = md5.digest('hex');
console.log(result); // e10adc3949ba59abbe56e057f20f883e
md5.update('789') // Error: Digest already called
複製程式碼

常見的輸出格式還有base64格式

let md5 = crypto.createHash('md5');
md5.update('123456');
let result = md5.digest('base64');
console.log(result) // 4QrcOUm6Wau+VuBX8g+IPg==
複製程式碼

資料庫存的資訊如果是密碼,那麼應該進行多次加密,防止拖庫後被破解。最大的反例就是csdn,600萬使用者名稱和密碼由於資料庫明文儲存,被黑客攻擊後遭到洩漏。

2 HMAC演算法

HMAC演算法將雜湊演算法與一個金鑰結合在一起,以阻止對簽名完整性的破壞

node資料加密,還不快快點進來?

2.1 語法

let hmac = crypto.createHmac(algorihtm,key);
hmac.update(data);
hmac.digest('hex');
複製程式碼
  • algorithm 是一個可用的摘要演算法,例如 sha1、md5、sha256
  • key為一個字串,用於指定一個PEM格式的金鑰

2.2生成私鑰

PEM是OpenSSL的標準格式,OpenSSL使用PEM檔案格式儲存證書和金鑰,是基於Base64編碼的證書.

windows版openSSL下載

openssl genrsa -out rsa_private.key 2048
複製程式碼

生成PEM格式的金鑰

2.3加密示例

let crypro = require('crypto');
let fs = require('fs');
let key = fs.readFileSync(`${__dirname}/rsa_private.key`);
let hmac = crypto.createHmac('sha1',key);
hmac.update('牧瀨紅莉棲');
let result = hmac.digest('hex');
console.log(result) // a99a39b22a2272b070666194eede92ed1e9bbe46
複製程式碼

3 對稱加密

與雜湊雜湊演算法不同的是,他是可逆的,加密解密,使用相同的金鑰

blowfish、aes等演算法是一種對稱的加密演算法,對稱的意思就是加密和解密使用的是同一個金鑰。

node資料加密,還不快快點進來?
let crypto = require('crypto');
let fs = require('fs');
let key = fs.readFileSync(`${__dirname}/rsa_private.key`);
let cipher = crypto.createCipher('blowfish',key);
cipher.update('鳳凰');
let result = cipher.final('hex');
console.log(result); // 

let deciper = crypto.createDecipher('blowfish',key);
//需要知道是用那種編碼格式輸出的
deciper.update(result,'hex');
let r = deciper.final('utf8');
console.log(r) // 鳳凰
複製程式碼

4 非對稱加密演算法

  • 非對稱加密演算法需要兩個金鑰:公開金鑰(publickey)和私有金鑰(privatekey)
  • 公鑰和私鑰是一對,如果用公鑰對資料加密,則只有對應的私鑰才能解密,如果私鑰加密,那麼只有公鑰才能解密
  • 因為加密和解密使用的是兩個不同的金鑰,所以這種演算法叫做非對稱加密演算法
node資料加密,還不快快點進來?

為私鑰建立公鑰

openssl rsa -in rsa_private.key -pubout -out rsa_public.key 
複製程式碼
let crypto = require('crypto');
let fs = require('fs');
let pubkey = fs.readFileSync(`${__dirname}/rsa_public.key`,'utf8');
let prikey = fs.readFileSync(`${__dirname}/rsa_private.key`,'utf8');

let result = crypto.publicEncrypt(pubkey,Buffer.from('鳳凰院凶真'));
let r = crypto.privateDecrypt(prikey,result);

console.log(r.toString()); // '鳳凰院凶真'
複製程式碼

5 簽名

在網路中,私鑰的擁有者可以在一段資料被髮送前先對資料進行簽名得到一個簽名,通過網路吧此資料傳送給接受者之後,資料的接收者可以通過公鑰來對該簽名進行驗證,以確保這段資料是私鑰的擁有者所發出的原始資料,且在網路中的傳輸過程中未被修改.

node資料加密,還不快快點進來?
  • “Sign”類是生成簽名的實用工具。它有兩種使用方式:

    作為一個可寫的stream,在這裡,要簽署的資料是寫出來的,sign.sign()方法用於生成並返回簽名

  • 使用sign.update()和sign.sign()方法生產簽名。

  • crypto.createSign()方法用於建立Sign例項。Sign例項不能直接使用new關鍵字建立。

例:使用sign.write() sign.sign() 方法

let crypto = require('crypto');
let fs = require('fs')
let sign = crypto.createSign('SHA256');
sign.write('克里斯蒂娜');
sign.end();

let prikry = fs.readFileSync(`${__dirname}/rsa_private.key`);

console.log(sign.sign(prikry,'hex'));
複製程式碼

例:使用sign.update() sign.sign() 方法

let crypto = require('crypto');
let fs = require('fs')
let sign = crypto.createSign('SHA256');
sign.update('克里斯蒂娜');

let prikry = fs.readFileSync(`${__dirname}/rsa_private.key`);

console.log(sign.sign(prikry,'hex'));
複製程式碼

例:通過簽名校驗資料是否被修改

let fs = require('fs');
let crypto = require('crypto');
let path = require('path');
let private = fs.readFileSync(path.join(__dirname, 'rsa_private.key'));
let public = fs.readFileSync(path.join(__dirname, 'rsa_public.key'));
let str = '無限遠點的牽牛星';
let sign = crypto.createSign('RSA-SHA256');

sign.update(str);
let signed = sign.sign(private,'hex');
console.log(signed);

let verify = crypto.createVerify('RSA-SH256');
verify.update(str);
let verifyResult = verify.verify(public,signed,'hex');
console.log(verifyResult) // true
複製程式碼

結語

crypto模組常用的加密演算法的介紹到這裡就結束了,如果你有更好的思路和想法,歡迎分享哦!

如果覺得還可以,請點贊鼓勵一下,謝謝!

相關文章