RSA加密算法是一種非對稱加密算法。javascript
假設 A 與 B 通訊。A 和 B 都提供一個公開的公鑰。A 把須要傳遞的信息,先用本身的私鑰簽名,再用 B 的公鑰加密。B 接收到這串密文後,用本身的私鑰解密,用 A 提供的公鑰驗籤。html
爲何要先簽名後加密?若是你先加密後簽名,非法用戶經過獲取的公鑰就能夠破解簽名,破解以後就能夠替換籤名。java
詳細的原理能夠參考如下文檔:
RSA算法原理(一)
RSA算法原理(二)node
在 node.js 中使用 rsa 算法,咱們使用的是 node-rsa 這個包。git
const NodeRSA = require('node-rsa'); const a_public_key_data = '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----'; const a_private_key_data = '-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----'; const b_public_key_data = '-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----'; const b_private_key_data = '-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----'; // 生成 A 的公私鑰對象 const a_public_key = new NodeRSA(a_public_key_data); const a_private_key = new NodeRSA(a_private_key_data); // 生成 B 的公私鑰對象 const a_public_key = new NodeRSA(a_public_key_data); const a_private_key = new NodeRSA(a_private_key_data); const text = 'Hello RSA!'; // 加簽並加密 const sign = a_private_key.sign(text, 'base64', 'utf8'); console.log('A 私鑰加簽:', sign); const encrypted = a_public_key.encrypt(sign, 'base64'); console.log('B 公鑰加密:', encrypted); // 解密並驗籤 const decrypted = a_public_key.decrypt(encrypted, 'utf8'); console.log('B 私鑰解密:', decrypted); const verify = a_public_key.verify(text, decrypted, 'utf8', 'base64'); console.log('A 公鑰驗籤:', verify);
接口傳遞的通常是複雜的對象,因此咱們須要把對象按必定的順序排列並序列化成字符串再進行簽名加密的操做github
const serialize = (obj) => { const str = []; Object.keys(obj).sort().forEach((key) => { if (obj.hasOwnProperty(key)) { str.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])); } }); return str.join('&'); };
RSA 算法有必定的計算量,加上 Node 不適合作計算密集型的操做。當接口被頻繁調用可能會佔用主線程,阻塞其餘接口,使用了 RSA 的接口併發量會降低十倍左右。如非必要,謹慎在 Node 裏使用 RSA。算法