前端如何用密文跟後端互通?原來那麼簡單!

林恒發表於2024-07-01

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

後端:密碼得走密文哇!
我:base64?md5?
後端:這次不行哇,新來的測試不好糊弄呢!必須要國密sm2加密捏
我: 好吧,看我的。

我這邊使用的是sm-crypto,當然也有很多優秀的庫如:forge,我在業務上搭配jszip做過上傳zip檔案內藏加密後的私鑰進行證書登入,還是不錯的支援,但是文件社群不是很友好,所以推薦sm-crypto,接下來讓我們一起使用它吧。

sm-crypto是一個基於Node.js的密碼學庫,專為與國密演算法(中國密碼演算法標準)相容而設計。它提供了各種加密、解密、簽名和驗證功能。

sm-crypto包含多種密碼演算法的實現,例如:

  • SM1:對稱加密演算法,其加密強度與AES相當,但該演算法不公開,呼叫時需要透過加密晶片的介面進行呼叫。
  • SM2:非對稱加密演算法,基於ECC(橢圓曲線密碼學)。該演算法已公開,且由於基於ECC,其簽名速度與秘鑰生成速度都快於RSA。此外,ECC 256位(SM2採用的就是ECC 256位的一種)的安全強度比RSA 2048位高,但運算速度快於RSA。
  • SM3:訊息摘要演算法,可以用MD5作為對比理解,其校驗結果為256位。
  • SM4:無線區域網標準的分組資料演算法,屬於對稱加密,金鑰長度和分組長度均為128位。

sm-crypto內部方法介紹

1.SM2加密與解密

SM2是一種基於橢圓曲線密碼學的非對稱加密演算法。sm-crypto提供了SM2的金鑰生成、加密、解密等功能。透過呼叫相關方法,開發者可以輕鬆地生成SM2金鑰對,並使用公鑰進行加密、私鑰進行解密。

const { sm2 } = require('sm-crypto');  
const keyPair = sm2.generateKeyPairHex(); // 生成金鑰對  
const publicKey = keyPair.publicKey; // 公鑰  
const privateKey = keyPair.privateKey; // 私鑰  
  
const message = 'Hello, SM2!'; // 待加密的訊息  
const encrypted = sm2.doEncrypt(message, publicKey, { hash: true }); // 使用公鑰加密  
const decrypted = sm2.doDecrypt(encrypted, privateKey, { hash: true, raw: true }); // 使用私鑰解密  
  
console.log('加密結果:', encrypted);  
console.log('解密結果:', decrypted.toString()); // 輸出原始訊息

2.SM3摘要演算法

SM3是一種密碼雜湊演算法,用於生成訊息的摘要值。sm-crypto提供了SM3的摘要計算功能,開發者可以透過呼叫相關方法計算任意訊息的SM3摘要值。

const { sm3 } = require('sm-crypto');  
const message = 'Hello, SM3!'; // 待計算摘要的訊息  
const digest = sm3(message); // 計算SM3摘要值  
  
console.log('SM3摘要值:', digest);

3.SM4分組加密演算法

SM4是一種分組密碼演算法,適用於無線區域網等場景。sm-crypto提供了SM4的加密與解密功能,開發者可以使用SM4金鑰對資料進行加密和解密操作。

const sm4 = require('sm-crypto').sm4;                                               |
const sm4 = require('sm-crypto').sm4;  
const key = '0123456789abcdeffedcba9876543210'; // 16位元組的SM4金鑰  
const message = 'Hello, SM4!'; // 待加密的訊息  
const encrypted = sm4.encrypt(Buffer.from(message), Buffer.from(key, 'hex')); // 加密  
const decrypted = sm4.decrypt(encrypted, Buffer.from(key, 'hex')); // 解密  
  
console.log('加密結果:', encrypted.toString('hex'));  
console.log('解密結果:', decrypted.toString()); // 輸出原始訊息

4、簽名/驗籤

簽名(Sign)

const { sm2 } = require('sm-crypto'); 
const keyPair = sm2.generateKeyPairHex(); // 生成金鑰對 
const publicKey = keyPair.publicKey; // 公鑰 
const privateKey = keyPair.privateKey; // 私鑰

const message = '這是要簽名的訊息'; // 替換為實際要簽名的訊息 
// 使用私鑰對訊息進行簽名  
let sigValueHex = sm2.doSignature(message, privateKey); 
console.log('簽名結果:', sigValueHex);

驗籤(Verify Signature)

const message = '這是要驗證簽名的訊息'; // 應與簽名時使用的訊息相同  
const sigValueHex = '簽名值'; // 替換為實際的簽名值字串,即簽名步驟中生成的sigValueHex  
  
// 使用公鑰驗證簽名是否有效  
let verifyResult = sm2.doVerifySignature(message, sigValueHex, publicKey);  
  
console.log('驗簽結果:', verifyResult); // 如果驗證成功,應輸出true;否則輸出false

實戰例子

登入註冊,對使用者密碼進行加密

注意:前端是不儲存任何涉及安全的金鑰(公鑰是直接拿後端生成的)。

新建個工具檔案,專門存放加密邏輯,我這用的是SM2

// smCrypto.js
import { sm2 } from 'sm-crypto' // 引入加密庫

export const doEncrypt = ( // 加密
  data,
  pKey = publicKey,
  cipherMode = 0
) =>
  sm2.doEncrypt(
    typeof data === 'object'
      ? JSON.stringify(data) : data, 
    pKey, 
    cipherMode
  )
export const encryptionPwd = async data => {  // 加密密碼高階
  let servePublicKey = ''
  await user.getSm2Pkeys()
      .then(res => {
         servePublicKey = res.data.content
      })
  return doEncrypt(
    data,
    servePublicKey
  )
}

sm-crypto作為一款基於Node.js的國密演算法庫,為開發者提供了豐富的密碼學功能。透過呼叫sm-crypto的內部方法,開發者可以輕鬆地實現SM2加密與解密、SM3摘要計算以及SM4分組加密等操作。這些功能在保障資料安全、構建安全應用等方面發揮著重要作用。同時,開發者在使用sm-crypto時,也需要注意遵循最佳的安全實踐,確保金鑰的安全儲存和管理,以防止潛在的安全風險。

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

前端如何用密文跟後端互通?原來那麼簡單!

相關文章