基于js的rsa签名

引入node-forge

 const forge = require("node-forge");

新建RSA加密类

  • 将对象转换成签名字符串,并且按要求去除sign参数

  • 然后进行排列 小写字母在前

 // RSA加密类
 class RSACrypt {
   constructor(key) {
     this.key = forge.pki.publicKeyToPem(key);
   }
 ​
   // 将对象转换为签名字符串,对参数进行排序
   static signData(dataDict) {
     let tmp = [];
     for (let key in dataDict) {
       if (dataDict.hasOwnProperty(key) && key !== "sign") {
         // 排除sign参数
         let value = dataDict[key];
         if (typeof value === "object" && value !== null) {
           tmp.push(`${key}=${JSON.stringify(value)}`);
         } else {
           tmp.push(`${key}=${value}`);
         }
       }
     }
     // 按照参数名称排序,小写字母在前
     tmp.sort((a, b) => {
       return a.split("=")[0].localeCompare(b.split("=")[0], undefined, { numeric: true, sensitivity: "base" });
     });
     return tmp.join("&");
   }
 }
 ​

RSA私钥并且继承RSA加密类

  • 根据外部传入的RSA密钥生成签名

 // RSA私钥
 class RSAPrvCrypt extends RSACrypt {
   // RSA私钥生成签名
   sign(data) {
     if (typeof data === "object") {
       data = RSACrypt.signData(data);
     }
     data = new Uint8Array(forge.util.encodeUtf8(data));
     const md = forge.md.sha256.create();
     md.update(data);
     const privateKey = forge.pki.privateKeyFromPem(this.key);
     const signature = privateKey.sign(md);
     return signature.toBase64(); // 将签名结果进行Base64编码
   }
 }

RSA公钥加密 并且验证签名

 // RSA公钥
 class RSAPubCrypt extends RSACrypt {
   // RSA公钥加密
   encrypt(data) {
     const encrypted = [];
     const maxLength = 117; // 根据密钥长度调整,117是2048位密钥的推荐块大小
     data = data.utf8Encode();
     const publicKey = forge.pki.publicKeyFromPem(this.key);
     for (let i = 0; i < data.length; i += maxLength) {
       const block = data.subarray(i, i + maxLength);
       encrypted.push(publicKey.encrypt(block, "RSAES-PKCS1-V1_5"));
     }
     return encrypted.map((b) => b.toBase64()).join("");
   }
 ​
   // RSA公钥验证签名
   verifySign(data, signature) {
     if (typeof data === "object") {
       data = RSACrypt.signData(data);
     }
     data = new Uint8Array(forge.util.encodeUtf8(data));
     const signatureBytes = forge.util.decode64(signature);
     const publicKey = forge.pki.publicKeyFromPem(this.key);
     return publicKey.verify(data, signatureBytes, "SHA256");
   }
 }

导出模块供外部使用

 module.exports = {
   RSAPubCrypt,
   RSAPrvCrypt,
 };

外部

const forge = require("node-forge");
const { RSAPrvCrypt } = require("文件名"); // 

// 私钥
const privateKeyPem = `-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----`;

// 创建RSA私钥实例
const rsaPrvCrypt = new RSAPrvCrypt(privateKeyPem);

// API请求参数
const params = {
  foo: 1,
  bar: 2,
  'foo_bar': 3,
  foobar: 4
};

// 1. 对参数进行排序
const sortedParams = RSACrypt.signData(params);

// 2. 使用私钥对排序后的参数进行签名
const signature = rsaPrvCrypt.sign(sortedParams);

// 3. 将签名结果进行Base64编码(在sign方法中已经完成)

// 4. 将签名值赋给Sign参数,并发起API请求
const apiParamsWithSign = {
  ...params,
  Sign: signature
};


基于js的rsa签名
http://localhost:8090//archives/js-guan-yu-rsaqian-ming
作者
傅凯风
发布于
2024年11月11日
许可协议