You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NodeJS中验证MSSQL SignByCert生成的签名

在Node.js中验证MSSQL SignByCert生成的签名

问题说明

使用MSSQL的SignByCert函数生成签名后,无法直接用Node.js的crypto.verify验证,因为MSSQL的签名格式与标准PKCS#1 v1.5规范存在差异,需要对签名进行特定转换。

修正后的验证代码

const crypto = require('crypto');

// 原始明文
const plainText = 'Hello World';
// MSSQL生成的十六进制签名
const sqlSignature = '01000502040000002B0DFBF8B0EB048B18BA30A7A9AC3C63C18D8F932DC974178C61F810758A3FB81F14247AA338E6DBABAE265A8D8077C689901E33B016379685F7A0D27429DCB78F438201F5C04827F2F2B816BF5EFD569FA2AD7EEECC69621AF5F7C39893F0001FC22EAA74DB0F5026CDB38F5BFF3A3D208196C75E7A7A9556050459C826194E460D4C5AB1F30ACFF8594E4E99BC8FD5C8675E79EC54AC9EB017FA112C1759BF387C248869C461677E1CF711860618BFCAC1332C879C01D88C0EBFD584BCF4B358D5D47618A7367DE3A1943AB18454D1B8C423437661120EEE2225A35F763002E9AC80B23B5F03F1EA4C16422BEA8C51032AA0C16B73C7AC5583496EDFD6AA21';
// MSSQL导出的十六进制公钥(证书)
const pbkHex = '3082036B30820253A00302010202146472932AE654353AF660E02361C2062FC040FEE6300D06092A864886F70D01010B05003045310B30090603550406130241553113301106035504080C0A536F6D652D53746174653121301F060355040A0C18496E7465726E6574205769646769747320507479204C7464301E170D3233313132303137303835375A170D3234313131393137303835375A3045310B30090603550406130241553113301106035504080C0A536F6D652D53746174653121301F060355040A0C18496E7465726E6574205769646769747320507479204C746430820122300D06092A864886F70D01010105000382010F003082010A0282010100CF9CCF5AF133484FC7DC8FF41C1B9010FC7821B373D0352A57E76A0FA0456AE1F35FDCED60343551594FC0E636727AF868EC237978BBBAE8C366B955A507CB942A3380755F6565F1811BF4476948008F18F3BEBE852540C660A781B362DAD21E70567CE70363EB4DE0F281DB239381308C2A8664B066F7F3331038E62465FC837AF170346AB63D1D18CA0400A6FC41EEE87FEFFB80C01D2FF7B86A1E48F299FA4BECA495C8B33CCB3A9603731AC9CE6B6F55EA1EB91DD919DCCBB17833CB1FB67C97891AF9FAC34EFDB2E7777DF5DFD7E4172638ED65ECBAE08AB5E17EB7EA81937DAAA79F9B041BE3C05488423BB3EF1B26C91D91CF7FD9D7A42E8E5582DA5F0203010001A3533051301D0603551D0E041604145F7A25691BA68CF1D6B59AD50E8F2CA6D0403018301F0603551D230418301680145F7A25691BA68CF1D6B59AD50E8F2CA6D0403018300F0603551D130101FF040530030101FF300D06092A864886F70D01010B0500038201010064E1E3CB35A81CB136B599134D0F536A4D1776CE26B2822B33C415C8E65EE4A8A5E185668455DDF326A4219CAB87D12ED59E85BDA31521201998165F41979CA0DB6608AF2A5D5A3A7566082B6E7B1204666233312E0FFABFF427DDB8E37415559CD8B5405F13425078ACDC1C02AECD3DE372FDC9DE0DCE9A74F3716AF2D0D2ACD06F6070AB620A5E6A5575CA760AED728AAD8549B047345D4F286EA51CB005719B2396F5C0340FB94162EE9E7EAC247CE402169FC754EACAC818C08DAD0A796D336F4437D665CD7ABAB1ED9E30D6213ED2328859709884C35BE1143861429A84FA2CE530F95434554B33131AA66EC6ABC22091E91072242B466877ED6D82C137';

// 加载证书并提取公钥
const x509Cert = new crypto.X509Certificate(Buffer.from(pbkHex, 'hex'));
const publicKey = x509Cert.publicKey;

// 处理MSSQL签名:移除前16字节头部,反转字节序转换为大端格式
const signatureBuffer = Buffer.from(sqlSignature, 'hex');
const rawSignature = signatureBuffer.slice(16); // 去掉前16字节的版本和算法标识
const standardSignature = Buffer.from(rawSignature).reverse(); // 转换为大端字节序

// 验证签名:使用RSA-SHA256算法,传入原始明文而非预计算的哈希
const isValid = crypto.verify(
  'sha256',
  Buffer.from(plainText, 'utf8'),
  publicKey,
  standardSignature
);

console.log('签名验证结果:', isValid); // 输出 true

关键修正点说明

  1. 签名格式转换:

    • MSSQL生成的签名前16字节是额外的头部信息(版本号+算法标识),必须移除才能得到实际的签名内容
    • MSSQL采用小端字节序存储签名,而标准PKCS#1 v1.5签名使用大端字节序,因此需要反转字节
  2. 验证参数修正:

    • 无需手动计算明文的哈希值,crypto.verify会自动对原始明文计算SHA256哈希并验证签名
    • 明确指定验证算法为sha256,与MSSQLSignByCert默认使用的哈希算法匹配(若SQL中指定了其他算法,需同步修改此处)

内容的提问来源于stack exchange,提问作者aii-yin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:47:26