瀏覽器端rsa加密方案node-forge

並無體驗多少庫,只看了一個npm裏最多人用的一個庫:前端

node-forge接口文檔node

rsa小知識

  • 加密解密用的key是成對的,分別稱爲私鑰和公鑰,私鑰必須存放在服務器等別人沒法獲取到的地方,公鑰能夠公開,誰均可以獲取。
  • 不能把公鑰當私鑰,私鑰當公鑰使用,由於私鑰能夠提取出公鑰。
  • 公鑰加密的內容,只有私鑰能解密,公鑰不能解密本身加密的內容。
  • 私鑰加密的過程稱爲簽名(sign),由於公鑰是公開的,誰都能解密,因此沒法保密信息,只能用於驗證簽名者是私鑰持有人。

前端代碼

// 他們github有提供 forge.min.js , 不用webpack的項目也能夠直接引用
import forge from 'node-forge'

const message = '要加密我了' // 原文長度有限制,並且中文還要url編碼,因此不能加密太長的字符串。通常也只用來加密密碼。
const publicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqM+l9ZWy1Frt6felFFLmfZNls\nVbU1dKpF8Rx83FtKCsztO5k/iV5N9BbfHFUg9Y40b/EK2j/BPc1xlLYAHMXn6563\nXCwZ4IuCxvfOwz9qT9gkKBxkI5b0rnikkSWTGlJEk2PdZ7Plc73Fa+bx3PvuKvMd\ncKWvd80+vt9+b/7hrwIDAQAB\n-----END PUBLIC KEY-----'
const publicK = forge.pki.publicKeyFromPem(publicKey)
const encrypted = publicK.encrypt(encodeURIComponent(message), 'RSA-OAEP') // 通過url編碼,後端解密後須要url解碼
console.log('密文:', encrypted) // 雖然亂碼,但能夠直接發給後端解密

ps. 以上代碼建議使用try,由於加密中若是出現問題,會throw Errorwebpack

nodejs端代碼

const forge = require('node-forge')
const privateKey = '-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKoz6X1lbLUWu3p9\n6UUUuZ9k2WxVtTV0qkXxHHzcW0oKzO07mT+JXk30Ft8cVSD1jjRv8QraP8E9zXGU\ntgAcxefrnrdcLBngi4LG987DP2pP2CQoHGQjlvSueKSRJZMaUkSTY91ns+VzvcVr\n5vHc++4q8x1wpa93zT6+335v/uGvAgMBAAECgYArxUnou6qnL39rUvIol9ncyfy4\nRZpicuxPLGCdI7Y+ZmSpJciVdGhSN9Gh8xFZdozpo1gj6Fi5A4HQEeR0RvIF9Rgh\nERblj1rRWqxPcsIddOO9VaknQPICWKqEW9+E1bEcyNUblCHA4LGyQwmuEFUb/Tkj\nxAghIHuEBCe0GFiVwQJBAN5i5QSoOIpdFHA0c981E4VhHc/muXwjx1HfE1pcuuFb\nTy3OwEoZdFp3LIjBnBkPRneLTNjo5WTIwrmfsy6VDF8CQQDD7c6d/nKiJwIESlr+\n/idqXAPNR/iS1YX3Nqtk9jgrgf5zULHr2nbk7MDas5S9Z9XPdUmxtnP44dhoGvDk\nzyyxAkB7XBxyQuZqSkvGGjKUhJq5iC/DXddSd35fegEARSQdUktPu7qK4Cfc7vKz\nQcLXW9PZCFqukDJ/f6YU1fPNSTy9AkADQ78hms/GK+g4shR6EzoM56OYlA5sQ+qL\nh/mrIP8mmm/m8/1C9MzuW5OLEVr1HPnPDyE/OM8N4pV8hpZk+Z7BAkEAzaFstazA\nxLzZOBWhvOzzo722glZ7HVezhMocLu7Y3EOXP/nbx09JpU3U7Egp5UVp0aiknh/Q\nez4Cc4ksMedxdA==\n-----END PRIVATE KEY-----\n'
const privateK = forge.pki.privateKeyFromPem(privateKey)
const decrypted = privateK.decrypt(encrypted, 'RSA-OAEP') // encrypted 爲前端傳過來的密文
console.log('原文:', decodeURIComponent(decrypted)) // decrypted 爲原文

ps. 以上代碼建議使用try,由於解密中若是出現問題,會throw Errorc++

ps. 以上例子用了RSA-OAEP規則,其實rsa還有不少加密規則,我粗略查了一下,聽說RSA-OAEP是目前比較新的方式,另外有一些舊的規則已經不推薦使用了,留着只是爲了向上兼容。沒有深刻查下去,由於我怕接下來要研究密碼學了...git

ps. 若是以爲加密後的字符串是亂碼很差看,或者擔憂傳輸會出問題,可使用base64轉一下,服務端接收到則先解析base64再解密。github

生成密鑰公鑰對

const forge = require('node-forge')
const { rsa, publicKeyToRSAPublicKeyPem, privateKeyToPem } = forge.pki
rsa.generateKeyPair({ bits: 2048, workers: 2 }, function (err, keypair) {
  if (err) {
    return
  }

  // 這裏就生成了字符串的公鑰和密鑰了,能夠把生成結果保存起來
  console.log({
    publicKey: publicKeyToRSAPublicKeyPem(keypair.publicKey, 72).replace(/\r/g, ''),
    privateKey: privateKeyToPem(keypair.privateKey, 72).replace(/\r/g, '')
  })
})
相關文章
相關標籤/搜索