sm2 验签不通过
This commit is contained in:
+92
-29
@@ -253,24 +253,25 @@ function extractInfoFromJsrsasignP7(base64Data) {
|
||||
*/
|
||||
module.exports.verifyPKCS7 = function (p7sign, originalData) {
|
||||
// 处理输入数据
|
||||
let pemData
|
||||
let base64Data
|
||||
if (Buffer.isBuffer(p7sign)) {
|
||||
pemData = p7sign.toString('ascii')
|
||||
base64Data = p7sign.toString('base64')
|
||||
} else if (typeof p7sign === 'string') {
|
||||
// 判断是否是 PEM 格式
|
||||
if (p7sign.includes('-----BEGIN PKCS7-----')) {
|
||||
pemData = p7sign
|
||||
// 提取 base64 部分
|
||||
base64Data = p7sign
|
||||
.replace(/-----BEGIN PKCS7-----\n?/, '')
|
||||
.replace(/-----END PKCS7-----\n?/, '')
|
||||
.replace(/\n/g, '')
|
||||
} else {
|
||||
// 如果不是 PEM 格式,假设是 base64,包装成 PEM
|
||||
pemData = `-----BEGIN PKCS7-----\n${p7sign}\n-----END PKCS7-----`
|
||||
// 如果不是 PEM 格式,假设是 base64
|
||||
base64Data = p7sign
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid input type for p7sign')
|
||||
}
|
||||
|
||||
// 解析 PKCS7 数据
|
||||
const p7 = forge.pkcs7.messageFromPem(pemData)
|
||||
|
||||
// 准备验证所需的数据
|
||||
let verifyData
|
||||
if (originalData) {
|
||||
@@ -282,17 +283,22 @@ module.exports.verifyPKCS7 = function (p7sign, originalData) {
|
||||
} else {
|
||||
throw new Error('Invalid input type for originalData')
|
||||
}
|
||||
} else {
|
||||
// 当没有提供原始数据时,从 PKCS7 中提取数据进行验证(attach 模式)
|
||||
if (p7.content) {
|
||||
verifyData = Buffer.from(p7.content.getBytes(), 'binary')
|
||||
} else {
|
||||
throw new Error('No content found in PKCS7 signature for attach mode')
|
||||
}
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
// 尝试使用 node-forge 解析和验证(支持 RSA)
|
||||
try {
|
||||
const pemData = `-----BEGIN PKCS7-----\n${base64Data}\n-----END PKCS7-----`
|
||||
const p7 = forge.pkcs7.messageFromPem(pemData)
|
||||
|
||||
// 如果没有提供原始数据,从 PKCS7 中提取(attach 模式)
|
||||
if (!verifyData) {
|
||||
if (p7.content) {
|
||||
verifyData = Buffer.from(p7.content.getBytes(), 'binary')
|
||||
} else {
|
||||
throw new Error('No content found in PKCS7 signature for attach mode')
|
||||
}
|
||||
}
|
||||
|
||||
// 对于 RSA 签名,使用公钥手动验证
|
||||
if (p7.certificates && p7.certificates.length > 0) {
|
||||
const publicKey = p7.certificates[0].publicKey
|
||||
@@ -309,22 +315,79 @@ module.exports.verifyPKCS7 = function (p7sign, originalData) {
|
||||
|
||||
// 如果 RSA 验证失败或不适用,尝试使用 node-forge 的 verify(如果支持)
|
||||
return p7.verify()
|
||||
} catch (error) {
|
||||
// 如果验证失败,尝试使用 SM2 验证
|
||||
} catch (forgeError) {
|
||||
// 如果 node-forge 解析失败,尝试使用 jsrsasign 解析和验证(支持 SM2)
|
||||
try {
|
||||
// 提取签名值和公钥
|
||||
const signInfo = module.exports.getInfoFromPKCS7(p7sign)
|
||||
if (!signInfo.publicKey || !signInfo.signature) {
|
||||
throw new Error('Cannot extract public key or signature from PKCS7')
|
||||
}
|
||||
|
||||
// 使用 SM2 验证签名
|
||||
const hash = sm3(verifyData.toString())
|
||||
return sm2.doVerify(hash, signInfo.signature, signInfo.publicKey)
|
||||
} catch (sm2Error) {
|
||||
console.error('SM2 verification error:', sm2Error)
|
||||
return verifyPKCS7WithJsrsasign(base64Data, verifyData)
|
||||
} catch (jsrsasignError) {
|
||||
// 静默处理错误,直接返回 false
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 jsrsasign 验证 PKCS7 签名(支持 SM2)
|
||||
*/
|
||||
function verifyPKCS7WithJsrsasign(base64Data, verifyData) {
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser()
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(base64Data))
|
||||
|
||||
// 如果没有提供原始数据,从 PKCS7 中提取(attach 模式)
|
||||
if (!verifyData) {
|
||||
if (p7.econtent && p7.econtent.hex) {
|
||||
// econtent.hex 是原始数据的 hex 编码
|
||||
verifyData = Buffer.from(p7.econtent.hex, 'hex')
|
||||
} else {
|
||||
throw new Error('No content found in PKCS7 signature for attach mode')
|
||||
}
|
||||
}
|
||||
|
||||
// 获取签名信息
|
||||
if (!p7.sinfos || p7.sinfos.length === 0) {
|
||||
throw new Error('No signer info found in PKCS7')
|
||||
}
|
||||
|
||||
const signer = p7.sinfos[0]
|
||||
|
||||
// 获取证书和公钥
|
||||
if (!p7.certs || !p7.certs.array || p7.certs.array.length === 0) {
|
||||
throw new Error('No certificate found in PKCS7')
|
||||
}
|
||||
|
||||
const certPem = p7.certs.array[0]
|
||||
const x509 = new rs.X509()
|
||||
x509.readCertPEM(certPem)
|
||||
|
||||
// 判断签名算法
|
||||
const sigAlg = signer.sigalg
|
||||
|
||||
// SM2 签名算法 OID: 1.2.156.10197.1.301.1 或 1.2.156.10197.1.501
|
||||
if (sigAlg === '1.2.156.10197.1.301.1' || sigAlg === '1.2.156.10197.1.501' || sigAlg.includes('sm2')) {
|
||||
// SM2 验证
|
||||
// 提取公钥 hex
|
||||
const certHex = rs.pemtohex(certPem)
|
||||
const tbsCert = rs.ASN1HEX.getTLVbyList(certHex, 0, [0])
|
||||
const spki = rs.ASN1HEX.getTLVbyList(tbsCert, 0, [6])
|
||||
const publicKeyBitString = rs.ASN1HEX.getTLVbyList(spki, 0, [1])
|
||||
const publicKeyHex = publicKeyBitString.substring(6) // 跳过 tag, length, unused bits
|
||||
|
||||
// 计算 SM3 哈希
|
||||
const hash = sm3(verifyData.toString())
|
||||
|
||||
// 使用 SM2 验证签名 (注意:使用 doVerifySignature,不是 doVerify)
|
||||
return sm2.doVerifySignature(hash, signer.sighex, publicKeyHex)
|
||||
} else {
|
||||
// RSA 验证(通过 jsrsasign)
|
||||
try {
|
||||
const pubKey = x509.getPublicKey()
|
||||
const sig = new rs.KJUR.crypto.Signature({ alg: 'SHA256withRSA' })
|
||||
sig.init(pubKey)
|
||||
sig.updateString(verifyData.toString())
|
||||
return sig.verify(signer.sighex)
|
||||
} catch (e) {
|
||||
throw new Error('RSA verification failed: ' + e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user