博客 / 詳情

返回

Postman 發送 RSA 簽名請求(qbit)

前言

  • Postman 版本 10.13.6
  • qbit 將 RSAForPostman 壓縮拷貝到了碼雲便於國內訪問

Postman 腳本示例

  • Pre-request Script

    if (!pm.collectionVariables.has("forgeJS")) {
      pm.sendRequest("https://gitee.com/qbitoy/public/raw/master/forge_rsa_min.js", function (err, res) {
          if (err) {
              console.log(err);
          } else {
              pm.collectionVariables.set("forgeJS", res.text());
          }
      })
    } else {
      var moment = require('moment');
      eval(pm.collectionVariables.get("forgeJS"));   // 生成 forge 變量
      const prikey = pm.collectionVariables.get("prikey");
      console.log("prikey:" + prikey);
      var priv = forge.pki.privateKeyFromPem(prikey);
      const md = forge.md.sha256.create();
      var ts = moment().valueOf();
      pm.collectionVariables.set("ts", ts);
      console.log("ts:" + ts);
      var message = "/subject/eduSubject-" + ts;
      console.log("message:" + message);
      md.update(message);
      const data = md.digest().bytes();
      const sign = forge.util.encode64(priv.sign(md));
      pm.collectionVariables.set("sign", sign);
      console.log("sign:", sign);
    }

國密 S2 加密

  • 2025.9.17 添加本章
  • 對 Postman v11.63.3 可用
  • qbit 將 sm-crypto 壓縮拷貝到了碼雲便於國內訪問
  • Postman Pre-request Script 腳本示例

    // —— 1. 異步加載 sm2JS / sm3JS(不變) —— 
    const libs = [];
    if (!pm.collectionVariables.get('sm2JS')) {
    libs.push({ name: 'sm2JS', url: 'https://gitee.com/qbitoy/public/raw/master/sm2_min.js' });
    }
    if (!pm.collectionVariables.get('sm3JS')) {
    libs.push({ name: 'sm3JS', url: 'https://gitee.com/qbitoy/public/raw/master/sm3_min.js' });
    }
    if (libs.length) {
    libs.forEach(lib => {
      pm.sendRequest(lib.url, (err, res) => {
        if (err) console.error(`Load ${lib.name} error:`, err);
        else pm.collectionVariables.set(lib.name, res.text());
      });
    });
    return;  
    }
    
    // —— 2. 包裝 eval 拿到 module.exports —— 
    function loadModule(code) {
    const wrapper = `
      (function() {
        var module = { exports: {} };
        var exports = module.exports;
        ${code}
        return module.exports;
      })()
    `;
    return eval(wrapper);
    }
    
    console.log('=== 開始加載國密模塊 ===');
    const sm2Raw = loadModule(pm.collectionVariables.get('sm2JS'));
    const sm3Raw = loadModule(pm.collectionVariables.get('sm3JS'));
    console.log('sm2Raw 類型:', typeof sm2Raw, 'sm3Raw 類型:', typeof sm3Raw);
    
    const sm2 = (sm2Raw && sm2Raw.sm2) ? sm2Raw.sm2 : sm2Raw;
    const sm3 = (sm3Raw && sm3Raw.sm3) ? sm3Raw.sm3 : sm3Raw;
    
    if (typeof sm3 !== 'function') {
    console.error('sm3 不是函數,無法繼續');
    return;
    }
    if (typeof sm2 !== 'object' || typeof sm2.doSignature !== 'function') {
    console.error('sm2 接口不完整,無法繼續');
    return;
    }
    
    // —— 3. 讀取參數 —— 
    const message   = pm.collectionVariables.get('message')  || 'Hello SM2/SM3';
    const priKeyHex = pm.collectionVariables.get('sm2prikey');
    const pubKeyHex = pm.collectionVariables.get('sm2pubkey');
    
    console.log('message:', message);
    console.log('sm2Priv 存在?', !!priKeyHex, 'sm2Pub 存在?', !!pubKeyHex);
    
    // —— 4. SM3 摘要 —— 
    let digest;
    try {
    console.log('開始計算 SM3 摘要');
    digest = sm3(message);
    pm.collectionVariables.set('sm3Hash', digest);
    console.log('SM3 Digest:', digest);
    } catch (e) {
    console.error('SM3 計算失敗:', e);
    return;
    }
    
    // 如果缺少 SM2 密鑰,就早退,不做後續簽名加解密
    if (!priKeyHex || !pubKeyHex) {
    console.warn('缺少 SM2 密鑰,跳過後續簽名/加解密');
    return;
    }
    
    // —— 5. SM2 簽名 —— 
    let signature;
    try {
    console.log('開始 SM2 簽名');
    signature = sm2.doSignature(message, priKeyHex, {
      hash: true,
      userId: '1234567812345678'
    });
    pm.collectionVariables.set('sm2Sign', signature);
    console.log('SM2 Signature:', signature);
    } catch (e) {
    console.error('SM2 簽名失敗:', e);
    return;
    }
    
    // —— 6. SM2 驗籤 —— 
    try {
    console.log('開始 SM2 驗籤');
    const ok = sm2.doVerifySignature(message, signature, pubKeyHex, {
      hash: true,
      userId: '1234567812345678'
    });
    console.log('SM2 Verify OK:', ok);
    } catch (e) {
    console.error('SM2 驗籤失敗:', e);
    return;
    }
    
    // —— 7. SM2 加密 —— 
    let cipher;
    try {
    console.log('開始 SM2 加密');
    cipher = sm2.doEncrypt(message, pubKeyHex, { cipherMode: 1 });
    pm.collectionVariables.set('sm2Enc', cipher);
    console.log('SM2 Encrypted:', cipher);
    } catch (e) {
    console.error('SM2 加密失敗:', e);
    return;
    }
    
    // —— 8. SM2 解密 —— 
    try {
    console.log('開始 SM2 解密');
    const plain = sm2.doDecrypt(cipher, priKeyHex, { cipherMode: 1 });
    pm.collectionVariables.set('sm2Dec', plain);
    console.log('SM2 Decrypted:', plain);
    } catch (e) {
    console.error('SM2 解密失敗:', e);
    return;
    }
    
    console.log('=== 全部操作完成 ===');

Postman 內置庫

  • 官方文檔:https://learning.postman.com/docs/writing-scripts/script-refe...

    ajv
    atob
    btoa
    chai
    cheerio
    crypto-js    # md5、sha1、sha256 等
    csv-parse/lib/sync
    lodash
    moment        # 時間、日期
    postman-collection
    tv4
    uuid
    xml2js
本文出自 qbit snap
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.