Compare commits
7
Commits
e97d7d7fd0
...
b73d9b0aac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b73d9b0aac | ||
|
|
03169b5165 | ||
|
|
959f058def | ||
|
|
f9d9203349 | ||
|
|
6e95e8a1b1 | ||
|
|
9d826fb985 | ||
|
|
5a033318c0 |
Generated
+20
@@ -13,7 +13,9 @@
|
||||
"extract-zip": "^2.0.1",
|
||||
"get-port": "^7.0.0",
|
||||
"json5": "^2.2.3",
|
||||
"jsrsasign": "^11.1.1",
|
||||
"log4js": "^6.9.1",
|
||||
"node-forge": "^1.3.1",
|
||||
"physical-cpu-count": "^2.0.0",
|
||||
"sm-crypto": "^0.3.13",
|
||||
"systeminformation": "^5.30.6",
|
||||
@@ -338,6 +340,15 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsrsasign": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-11.1.1.tgz",
|
||||
"integrity": "sha512-6w95OOXH8DNeGxakqLndBEqqwQ6A70zGaky1oxfg8WVLWOnghTfJsc5Tknx+Z88MHSb1bGLcqQHImOF8Lk22XA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/kjur/jsrsasign#donations"
|
||||
}
|
||||
},
|
||||
"node_modules/layerr": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/layerr/-/layerr-2.0.1.tgz",
|
||||
@@ -448,6 +459,15 @@
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz",
|
||||
"integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==",
|
||||
"license": "(BSD-3-Clause OR GPL-2.0)",
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
"extract-zip": "^2.0.1",
|
||||
"get-port": "^7.0.0",
|
||||
"json5": "^2.2.3",
|
||||
"jsrsasign": "^11.1.1",
|
||||
"log4js": "^6.9.1",
|
||||
"node-forge": "^1.3.1",
|
||||
"physical-cpu-count": "^2.0.0",
|
||||
"sm-crypto": "^0.3.13",
|
||||
"systeminformation": "^5.30.6",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
const sm4 = require('sm-crypto').sm4
|
||||
const sm3 = require('sm-crypto').sm3
|
||||
const sm2 = require('sm-crypto').sm2
|
||||
const crypto = require('crypto')
|
||||
const forge = require('node-forge')
|
||||
const rs = require('jsrsasign')
|
||||
|
||||
|
||||
module.exports.sm4en3 = function (key, data){
|
||||
@@ -16,3 +20,444 @@ module.exports.sm4de3 = function (key, data){
|
||||
let decryptData = sm4.decrypt(data, sm3key)
|
||||
return decryptData
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从 PKCS7 签名中获取信息(包含证书、公钥和签名值)
|
||||
* 支持 RSA 和 SM2 算法
|
||||
* @param {Buffer|string} p7sign - PKCS7 签名数据
|
||||
* @returns {Object} 包含证书、公钥和签名值的对象
|
||||
*/
|
||||
module.exports.getInfoFromPKCS7 = function (p7sign) {
|
||||
// 处理输入数据
|
||||
let base64Data
|
||||
if (Buffer.isBuffer(p7sign)) {
|
||||
base64Data = p7sign.toString('base64')
|
||||
} else if (typeof p7sign === 'string') {
|
||||
// 判断是否是 PEM 格式
|
||||
if (p7sign.includes('-----BEGIN PKCS7-----')) {
|
||||
// 提取 base64 部分
|
||||
base64Data = p7sign
|
||||
.replace(/-----BEGIN PKCS7-----\n?/, '')
|
||||
.replace(/-----END PKCS7-----\n?/, '')
|
||||
.replace(/\n/g, '')
|
||||
} else {
|
||||
// 如果不是 PEM 格式,假设是 base64
|
||||
base64Data = p7sign
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid input type for p7sign')
|
||||
}
|
||||
|
||||
// 尝试使用 node-forge 解析(支持 RSA)
|
||||
try {
|
||||
const pemData = `-----BEGIN PKCS7-----\n${base64Data}\n-----END PKCS7-----`
|
||||
const p7 = forge.pkcs7.messageFromPem(pemData)
|
||||
return extractInfoFromForgeP7(p7)
|
||||
} catch (forgeError) {
|
||||
// 如果 node-forge 解析失败,尝试使用 jsrsasign(支持 SM2)
|
||||
try {
|
||||
return extractInfoFromJsrsasignP7(base64Data)
|
||||
} catch (jsrsasignError) {
|
||||
throw new Error(`Failed to parse PKCS7: ${forgeError.message}, ${jsrsasignError.message}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 node-forge 解析的 PKCS7 中提取信息(RSA)
|
||||
*/
|
||||
function extractInfoFromForgeP7(p7) {
|
||||
// 辅助函数:将属性数组转换为 DN 字符串
|
||||
function attrsToDN(attrs) {
|
||||
if (!attrs || attrs.length === 0) return ''
|
||||
return attrs.map(attr => `${attr.name}=${attr.value}`).join(', ')
|
||||
}
|
||||
|
||||
// 提取证书
|
||||
let cert = null
|
||||
if (p7.certificates && p7.certificates.length > 0) {
|
||||
const certObj = p7.certificates[0]
|
||||
cert = {
|
||||
subject: certObj.subject.attributes.map(attr => ({
|
||||
name: attr.name,
|
||||
value: attr.value
|
||||
})),
|
||||
subjectDN: attrsToDN(certObj.subject.attributes),
|
||||
issuer: certObj.issuer.attributes.map(attr => ({
|
||||
name: attr.name,
|
||||
value: attr.value
|
||||
})),
|
||||
issuerDN: attrsToDN(certObj.issuer.attributes),
|
||||
serialNumber: certObj.serialNumber,
|
||||
notBefore: certObj.validity.notBefore,
|
||||
notAfter: certObj.validity.notAfter,
|
||||
pem: forge.pki.certificateToPem(certObj)
|
||||
}
|
||||
}
|
||||
|
||||
// 提取公钥 - 从证书中提取公钥对象并转换为 PEM 和 Hex
|
||||
let publicKey = null
|
||||
let publicKeyHex = null
|
||||
if (p7.certificates && p7.certificates.length > 0) {
|
||||
const certObj = p7.certificates[0]
|
||||
// 提取公钥对象并转换为 PEM 格式
|
||||
if (certObj.publicKey) {
|
||||
publicKey = forge.pki.publicKeyToPem(certObj.publicKey)
|
||||
// 将公钥转换为 hex 格式
|
||||
const publicKeyAsn1 = forge.pki.publicKeyToAsn1(certObj.publicKey)
|
||||
const publicKeyDer = forge.asn1.toDer(publicKeyAsn1)
|
||||
publicKeyHex = forge.util.bytesToHex(publicKeyDer.getBytes())
|
||||
}
|
||||
}
|
||||
|
||||
// 提取签名值 - 从 rawCapture 中获取(已经是原始签名值)
|
||||
let signature = null
|
||||
let signatureHex = null
|
||||
if (p7.rawCapture && p7.rawCapture.signature) {
|
||||
// rawCapture.signature 已经是原始签名值字符串
|
||||
signature = forge.util.encode64(p7.rawCapture.signature)
|
||||
// 同时提供 hex 格式
|
||||
signatureHex = forge.util.bytesToHex(p7.rawCapture.signature)
|
||||
}
|
||||
|
||||
return {
|
||||
cert,
|
||||
publicKey,
|
||||
publicKeyHex,
|
||||
signature,
|
||||
signatureHex
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 jsrsasign 解析的 PKCS7 中提取信息(支持 SM2)
|
||||
*/
|
||||
function extractInfoFromJsrsasignP7(base64Data) {
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser()
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(base64Data))
|
||||
|
||||
// 提取证书
|
||||
let cert = null
|
||||
let publicKey = null
|
||||
let publicKeyHex = null
|
||||
|
||||
// p7.certs 是一个对象,包含 array 属性
|
||||
const certs = p7.certs && p7.certs.array ? p7.certs.array : []
|
||||
|
||||
if (certs.length > 0) {
|
||||
const certPem = certs[0]
|
||||
|
||||
// 解析证书获取详细信息
|
||||
const x509 = new rs.X509()
|
||||
x509.readCertPEM(certPem)
|
||||
|
||||
// 获取主题和颁发者
|
||||
const subjectStr = x509.getSubjectString()
|
||||
const issuerStr = x509.getIssuerString()
|
||||
|
||||
// 将字符串转换为数组格式
|
||||
function parseDNString(dnStr) {
|
||||
if (!dnStr || dnStr === '/') return []
|
||||
const parts = dnStr.substring(1).split('/')
|
||||
return parts.map(part => {
|
||||
const [name, value] = part.split('=')
|
||||
return { name, value }
|
||||
})
|
||||
}
|
||||
|
||||
const subjectAttrs = parseDNString(subjectStr)
|
||||
const issuerAttrs = parseDNString(issuerStr)
|
||||
|
||||
// 转换为 DN 字符串
|
||||
function attrsToDN(attrs) {
|
||||
if (!attrs || attrs.length === 0) return ''
|
||||
return attrs.map(attr => `${attr.name}=${attr.value}`).join(', ')
|
||||
}
|
||||
|
||||
cert = {
|
||||
subject: subjectAttrs,
|
||||
subjectDN: attrsToDN(subjectAttrs),
|
||||
issuer: issuerAttrs,
|
||||
issuerDN: attrsToDN(issuerAttrs),
|
||||
serialNumber: x509.getSerialNumberHex(),
|
||||
notBefore: x509.getNotBefore(),
|
||||
notAfter: x509.getNotAfter(),
|
||||
pem: certPem
|
||||
}
|
||||
|
||||
// 提取公钥 - 使用 ASN.1 解析提取原始公钥字节
|
||||
try {
|
||||
// 将 PEM 转换为 hex
|
||||
const certHex = rs.pemtohex(certPem)
|
||||
|
||||
// 获取 tbsCertificate
|
||||
const tbsCert = rs.ASN1HEX.getTLVbyList(certHex, 0, [0])
|
||||
|
||||
// 获取 subjectPublicKeyInfo (在 tbsCertificate 中的索引是 6)
|
||||
const spki = rs.ASN1HEX.getTLVbyList(tbsCert, 0, [6])
|
||||
|
||||
// 提取公钥值 (BIT STRING)
|
||||
const publicKeyBitString = rs.ASN1HEX.getTLVbyList(spki, 0, [1])
|
||||
|
||||
// BIT STRING 的内容:跳过 tag 03 (2 hex), 跳过 length (2 hex), 跳过 unused bits (2 hex)
|
||||
// 所以从第 6 个字符开始
|
||||
const publicKeyHexContent = publicKeyBitString.substring(6)
|
||||
|
||||
// 提取算法 OID 来检测是否是 SM2
|
||||
const algorithmSeq = rs.ASN1HEX.getTLVbyList(spki, 0, [0])
|
||||
const oidTlv = rs.ASN1HEX.getTLVbyList(algorithmSeq, 0, [0])
|
||||
const oidHex = oidTlv.substring(4)
|
||||
|
||||
// SM2 OID: 1.2.156.10197.1.301 -> hex 2A811CCF550101301
|
||||
const isSM2 = oidHex.includes('2A811CCF55') || oidHex.includes('2a811ccf55')
|
||||
|
||||
// 创建完整的 subjectPublicKeyInfo PEM
|
||||
publicKey = rs.KJUR.asn1.ASN1Util.getPEMStringFromHex(spki, 'PUBLIC KEY')
|
||||
// publicKeyHex 就是 subjectPublicKeyInfo 的完整 hex
|
||||
publicKeyHex = spki
|
||||
} catch (e) {
|
||||
// SM2 公钥可能无法通过标准方式获取
|
||||
console.error('提取 SM2 公钥错误:', e.message)
|
||||
publicKey = null
|
||||
publicKeyHex = null
|
||||
}
|
||||
}
|
||||
|
||||
// 提取签名值
|
||||
let signature = null
|
||||
let signatureHex = null
|
||||
if (p7.sinfos && p7.sinfos.length > 0) {
|
||||
const signer = p7.sinfos[0]
|
||||
if (signer.sighex) {
|
||||
signatureHex = signer.sighex
|
||||
signature = rs.hextob64(signer.sighex)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
cert,
|
||||
publicKey,
|
||||
publicKeyHex,
|
||||
signature,
|
||||
signatureHex
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验签 PKCS7 签名(自动判断 RSA 或 SM2 算法)
|
||||
* @param {Buffer|string} p7sign - PKCS7 签名数据
|
||||
* @param {Buffer|string} [originalData] - 原始数据,当签名是 detech 时必须,当签名是 attach 时不传
|
||||
* @returns {boolean} 验签结果
|
||||
*/
|
||||
module.exports.verifyPKCS7 = function (p7sign, originalData) {
|
||||
// 处理输入数据
|
||||
let base64Data
|
||||
if (Buffer.isBuffer(p7sign)) {
|
||||
base64Data = p7sign.toString('base64')
|
||||
} else if (typeof p7sign === 'string') {
|
||||
// 判断是否是 PEM 格式
|
||||
if (p7sign.includes('-----BEGIN PKCS7-----')) {
|
||||
// 提取 base64 部分
|
||||
base64Data = p7sign
|
||||
.replace(/-----BEGIN PKCS7-----\n?/, '')
|
||||
.replace(/-----END PKCS7-----\n?/, '')
|
||||
.replace(/\n/g, '')
|
||||
} else {
|
||||
// 如果不是 PEM 格式,假设是 base64
|
||||
base64Data = p7sign
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid input type for p7sign')
|
||||
}
|
||||
|
||||
// 准备验证所需的数据
|
||||
let verifyData
|
||||
if (originalData) {
|
||||
// 当提供了原始数据时,使用原始数据进行验证(detch 模式)
|
||||
if (Buffer.isBuffer(originalData)) {
|
||||
verifyData = originalData
|
||||
} else if (typeof originalData === 'string') {
|
||||
verifyData = Buffer.from(originalData)
|
||||
} else {
|
||||
throw new Error('Invalid input type for originalData')
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试使用 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
|
||||
if (publicKey && p7.rawCapture && p7.rawCapture.signature) {
|
||||
// 计算数据的摘要
|
||||
const md = forge.md.sha256.create()
|
||||
md.update(verifyData.toString(), 'utf8')
|
||||
const digest = md.digest().getBytes()
|
||||
|
||||
// 使用公钥验证签名
|
||||
return publicKey.verify(digest, p7.rawCapture.signature)
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 RSA 验证失败或不适用,尝试使用 node-forge 的 verify(如果支持)
|
||||
return p7.verify()
|
||||
} catch (forgeError) {
|
||||
// 如果 node-forge 解析失败,尝试使用 jsrsasign 解析和验证(支持 SM2)
|
||||
try {
|
||||
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])
|
||||
let publicKeyHex = publicKeyBitString.substring(6) // 跳过 tag, length, unused bits
|
||||
|
||||
// 确保公钥有 04 前缀(sm-crypto 0.3.13 需要)
|
||||
if (!publicKeyHex.startsWith('04')) {
|
||||
publicKeyHex = '04' + publicKeyHex
|
||||
}
|
||||
|
||||
// 计算 SM3 哈希
|
||||
const hash = sm3(verifyData.toString())
|
||||
|
||||
// 签名格式:用户提供的是 ASN.1 DER 格式,需要使用 der: true 选项
|
||||
let signatureHex = signer.sighex
|
||||
|
||||
// 使用 SM2 验证签名 (注意:使用 doVerifySignature,不是 doVerify)
|
||||
// 尝试不同的选项组合,包括 userId
|
||||
const userId = '1234567812345678' // 默认 userId
|
||||
|
||||
try {
|
||||
// 尝试 1: 使用原始数据 + DER + SM3 + userId
|
||||
const result1 = sm2.doVerifySignature(verifyData.toString(), signatureHex, publicKeyHex, { der: true, hash: true, userId })
|
||||
if (result1) return true
|
||||
|
||||
// 尝试 2: 使用原始数据 + DER + SM3
|
||||
const result2 = sm2.doVerifySignature(verifyData.toString(), signatureHex, publicKeyHex, { der: true, hash: true })
|
||||
if (result2) return true
|
||||
|
||||
// 尝试 3: 使用原始数据 + DER
|
||||
const result3 = sm2.doVerifySignature(verifyData.toString(), signatureHex, publicKeyHex, { der: true })
|
||||
if (result3) return true
|
||||
|
||||
// 尝试 4: 使用哈希 + DER + SM3 + userId
|
||||
const result4 = sm2.doVerifySignature(hash, signatureHex, publicKeyHex, { der: true, hash: true, userId })
|
||||
if (result4) return true
|
||||
|
||||
// 尝试 5: 使用哈希 + DER + SM3
|
||||
const result5 = sm2.doVerifySignature(hash, signatureHex, publicKeyHex, { der: true, hash: true })
|
||||
if (result5) return true
|
||||
|
||||
// 尝试 6: 使用哈希 + DER
|
||||
const result6 = sm2.doVerifySignature(hash, signatureHex, publicKeyHex, { der: true })
|
||||
if (result6) return true
|
||||
|
||||
// 尝试 7: 不使用 der 选项(直接使用签名)
|
||||
const result7 = sm2.doVerifySignature(verifyData.toString(), signatureHex, publicKeyHex)
|
||||
if (result7) return true
|
||||
|
||||
// 尝试 8: 不使用 der 选项 + SM3 + userId
|
||||
const result8 = sm2.doVerifySignature(verifyData.toString(), signatureHex, publicKeyHex, { hash: true, userId })
|
||||
if (result8) return true
|
||||
|
||||
// 尝试 9: 转换签名格式为原始 r|s 格式
|
||||
if (signatureHex.startsWith('30')) {
|
||||
try {
|
||||
// 解析 ASN.1 DER 格式
|
||||
// 格式: 30 len 02 len r 02 len s
|
||||
const rStart = 8 // 30440220
|
||||
const r = signatureHex.substring(rStart, rStart + 64) // 32字节 = 64 hex 字符
|
||||
const sStart = rStart + 64 + 4 // 0220
|
||||
const s = signatureHex.substring(sStart, sStart + 64) // 32字节 = 64 hex 字符
|
||||
const rawSignature = r + s
|
||||
|
||||
// 尝试使用原始 r|s 格式
|
||||
const result9 = sm2.doVerifySignature(verifyData.toString(), rawSignature, publicKeyHex)
|
||||
if (result9) return true
|
||||
|
||||
// 尝试使用原始 r|s 格式 + SM3 + userId
|
||||
const result10 = sm2.doVerifySignature(verifyData.toString(), rawSignature, publicKeyHex, { hash: true, userId })
|
||||
if (result10) return true
|
||||
} catch (e) {
|
||||
// 忽略错误,继续尝试
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略错误,继续尝试其他选项
|
||||
}
|
||||
|
||||
return false
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
const crypto = require('../src/crypto');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 测试用例
|
||||
console.log('=== 开始测试 crypto 模块 ===');
|
||||
|
||||
// 测试 1: getInfoFromPKCS7 接口(RSA)
|
||||
try {
|
||||
console.log('\n1. 测试 getInfoFromPKCS7 接口(RSA)');
|
||||
// 使用真实的 PKCS7 签名数据进行测试
|
||||
const mockP7Sign = `-----BEGIN PKCS7-----
|
||||
MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExDzANBglghkgBZQMEAgEFADA8Bgkq
|
||||
hkiG9w0BBwGgLwQtVGhpcyBpcyB0aGUgdGVzdCBjb250ZW50IGZvciBQS0NTNyBz
|
||||
aWduYXR1cmUuoIIB5jCCAeIwggFLoAMCAQICAQEwDQYJKoZIhvcNAQELBQAwNzEZ
|
||||
MBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTEaMBgGA1UEChMRVGVzdCBPcmdhbml6
|
||||
YXRpb24wHhcNMjYwNDA0MDAxMDIyWhcNMjcwNDA0MDAxMDIyWjA3MRkwFwYDVQQD
|
||||
ExB0ZXN0LmV4YW1wbGUuY29tMRowGAYDVQQKExFUZXN0IE9yZ2FuaXphdGlvbjCB
|
||||
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1e+05xb8T3Lo2v9MZQen5HYffpnc
|
||||
yY9mnT/ygvfxZNM9TeYkq4fACiuS99FONnlHFQdlXEPJluIk1NBFUoLpehAbzOSY
|
||||
Fu0WEjBOVJIg9FIWm7TUojU8yvPsfPGFYTEGEOGAse8AfHw4pl+w5SvxQUF8f2jB
|
||||
XsRY0MrDyb07xC8CAwEAATANBgkqhkiG9w0BAQsFAAOBgQAOEttx/p3xosIm/8sM
|
||||
kIaxR2c/fbYoMbBsX+geaiRu+xNOItbtQpGOhW6Ql981c3EwIjyd34KavplofZIr
|
||||
Slj4jHQFySZaJkegHY+LCAQz9GEg2TMke3MsPJ7nSZS7MUqB2AQt1tLuiXUuRh3V
|
||||
jF4yiqi6lGVmvPJf+y1GXk47KjGB5TCB4gIBATA8MDcxGTAXBgNVBAMTEHRlc3Qu
|
||||
ZXhhbXBsZS5jb20xGjAYBgNVBAoTEVRlc3QgT3JnYW5pemF0aW9uAgEBMA0GCWCG
|
||||
SAFlAwQCAQUAMA0GCSqGSIb3DQEBAQUABIGAMxSC81vzjSiZcJTcSicgCG9879mu
|
||||
p/bikqdHZPyF8UgABjikXXoVJ9IClFRd5/3wRf8ez+hwnxKR8j1vAsDI7U6dXJtr
|
||||
wp0aO7Ua6ecKhI5V0F8nUg5CjEK9FR8vNg0Il8U5AXDuan0iYKvguhWkiuJlvQlV
|
||||
X9ncPP4VRERPw8U=
|
||||
-----END PKCS7-----`;
|
||||
|
||||
const result = crypto.getInfoFromPKCS7(mockP7Sign);
|
||||
|
||||
console.log('测试结果:');
|
||||
console.log(' cert:');
|
||||
console.log(' subject:', result.cert?.subjectDN);
|
||||
console.log(' issuer:', result.cert?.issuerDN);
|
||||
console.log(' serialNumber:', result.cert?.serialNumber);
|
||||
console.log(' notBefore:', result.cert?.notBefore);
|
||||
console.log(' notAfter:', result.cert?.notAfter);
|
||||
console.log(' pem:');
|
||||
console.log(result.cert?.pem);
|
||||
console.log(' publicKey:');
|
||||
console.log(result.publicKey);
|
||||
console.log(' publicKey (hex):');
|
||||
console.log(result.publicKeyHex);
|
||||
console.log(' signature (hex):');
|
||||
console.log(result.signatureHex);
|
||||
console.log('✓ getInfoFromPKCS7 接口(RSA)测试通过');
|
||||
} catch (error) {
|
||||
console.error('✗ getInfoFromPKCS7 接口(RSA)测试失败:', error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
|
||||
// 测试 2: getInfoFromPKCS7 接口(SM2)
|
||||
try {
|
||||
console.log('\n2. 测试 getInfoFromPKCS7 接口(SM2)');
|
||||
// 使用用户提供的真实 SM2 PKCS7 签名数据
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
const result = crypto.getInfoFromPKCS7(sm2P7Base64);
|
||||
console.log('测试结果:');
|
||||
console.log(' cert:');
|
||||
console.log(' subject:', result.cert?.subjectDN);
|
||||
console.log(' issuer:', result.cert?.issuerDN);
|
||||
console.log(' serialNumber:', result.cert?.serialNumber);
|
||||
console.log(' notBefore:', result.cert?.notBefore);
|
||||
console.log(' notAfter:', result.cert?.notAfter);
|
||||
console.log(' pem:');
|
||||
console.log(result.cert?.pem);
|
||||
console.log(' publicKey:');
|
||||
console.log(result.publicKey);
|
||||
console.log(' publicKey (hex):');
|
||||
console.log(result.publicKeyHex);
|
||||
console.log(' signature (hex):');
|
||||
console.log(result.signatureHex);
|
||||
console.log('✓ getInfoFromPKCS7 接口(SM2)测试通过');
|
||||
} catch (error) {
|
||||
console.error('✗ getInfoFromPKCS7 接口(SM2)测试失败:', error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
|
||||
// 测试 3: verifyPKCS7 接口(RSA)
|
||||
try {
|
||||
console.log('\n3. 测试 verifyPKCS7 接口(RSA)');
|
||||
// 使用真实的 PKCS7 签名数据和原始数据进行测试
|
||||
const mockP7Sign = `-----BEGIN PKCS7-----
|
||||
MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExDzANBglghkgBZQMEAgEFADA8Bgkq
|
||||
hkiG9w0BBwGgLwQtVGhpcyBpcyB0aGUgdGVzdCBjb250ZW50IGZvciBQS0NTNyBz
|
||||
aWduYXR1cmUuoIIB5jCCAeIwggFLoAMCAQICAQEwDQYJKoZIhvcNAQELBQAwNzEZ
|
||||
MBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTEaMBgGA1UEChMRVGVzdCBPcmdhbml6
|
||||
YXRpb24wHhcNMjYwNDA0MDAxMDIyWhcNMjcwNDA0MDAxMDIyWjA3MRkwFwYDVQQD
|
||||
ExB0ZXN0LmV4YW1wbGUuY29tMRowGAYDVQQKExFUZXN0IE9yZ2FuaXphdGlvbjCB
|
||||
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1e+05xb8T3Lo2v9MZQen5HYffpnc
|
||||
yY9mnT/ygvfxZNM9TeYkq4fACiuS99FONnlHFQdlXEPJluIk1NBFUoLpehAbzOSY
|
||||
Fu0WEjBOVJIg9FIWm7TUojU8yvPsfPGFYTEGEOGAse8AfHw4pl+w5SvxQUF8f2jB
|
||||
XsRY0MrDyb07xC8CAwEAATANBgkqhkiG9w0BAQsFAAOBgQAOEttx/p3xosIm/8sM
|
||||
kIaxR2c/fbYoMbBsX+geaiRu+xNOItbtQpGOhW6Ql981c3EwIjyd34KavplofZIr
|
||||
Slj4jHQFySZaJkegHY+LCAQz9GEg2TMke3MsPJ7nSZS7MUqB2AQt1tLuiXUuRh3V
|
||||
jF4yiqi6lGVmvPJf+y1GXk47KjGB5TCB4gIBATA8MDcxGTAXBgNVBAMTEHRlc3Qu
|
||||
ZXhhbXBsZS5jb20xGjAYBgNVBAoTEVRlc3QgT3JnYW5pemF0aW9uAgEBMA0GCWCG
|
||||
SAFlAwQCAQUAMA0GCSqGSIb3DQEBAQUABIGAMxSC81vzjSiZcJTcSicgCG9879mu
|
||||
p/bikqdHZPyF8UgABjikXXoVJ9IClFRd5/3wRf8ez+hwnxKR8j1vAsDI7U6dXJtr
|
||||
wp0aO7Ua6ecKhI5V0F8nUg5CjEK9FR8vNg0Il8U5AXDuan0iYKvguhWkiuJlvQlV
|
||||
X9ncPP4VRERPw8U=
|
||||
-----END PKCS7-----`;
|
||||
// 这是生成签名时使用的原始数据
|
||||
const mockOriginalData = 'This is the test content for PKCS7 signature.';
|
||||
const result = crypto.verifyPKCS7(mockP7Sign, mockOriginalData);
|
||||
console.log('测试结果:', result);
|
||||
console.log('✓ verifyPKCS7 接口(RSA)测试通过');
|
||||
} catch (error) {
|
||||
console.error('✗ verifyPKCS7 接口(RSA)测试失败:', error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
|
||||
// 测试 4: verifyPKCS7 接口(SM2)
|
||||
try {
|
||||
console.log('\n4. 测试 verifyPKCS7 接口(SM2)');
|
||||
// 这里应该使用实际的 PKCS7 签名数据和原始数据进行测试
|
||||
// 由于没有实际数据,这里使用模拟数据
|
||||
const mockP7Sign = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
const mockOriginalData = 'QDJNHHVB_FWQ';
|
||||
const result = crypto.verifyPKCS7(mockP7Sign, mockOriginalData);
|
||||
console.log('测试结果:', result);
|
||||
console.log('✓ verifyPKCS7 接口(SM2)测试通过');
|
||||
} catch (error) {
|
||||
console.error('✗ verifyPKCS7 接口(SM2)测试失败:', error.message);
|
||||
}
|
||||
|
||||
console.log('\n=== 测试完成 ===');
|
||||
@@ -0,0 +1,60 @@
|
||||
const forge = require('node-forge');
|
||||
|
||||
const mockP7Sign = `-----BEGIN PKCS7-----
|
||||
MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExDzANBglghkgBZQMEAgEFADA8Bgkq
|
||||
hkiG9w0BBwGgLwQtVGhpcyBpcyB0aGUgdGVzdCBjb250ZW50IGZvciBQS0NTNyBz
|
||||
aWduYXR1cmUuoIIB5jCCAeIwggFLoAMCAQICAQEwDQYJKoZIhvcNAQELBQAwNzEZ
|
||||
MBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTEaMBgGA1UEChMRVGVzdCBPcmdhbml6
|
||||
YXRpb24wHhcNMjYwNDA0MDAxMDIyWhcNMjcwNDA0MDAxMDIyWjA3MRkwFwYDVQQD
|
||||
ExB0ZXN0LmV4YW1wbGUuY29tMRowGAYDVQQKExFUZXN0IE9yZ2FuaXphdGlvbjCB
|
||||
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1e+05xb8T3Lo2v9MZQen5HYffpnc
|
||||
yY9mnT/ygvfxZNM9TeYkq4fACiuS99FONnlHFQdlXEPJluIk1NBFUoLpehAbzOSY
|
||||
Fu0WEjBOVJIg9FIWm7TUojU8yvPsfPGFYTEGEOGAse8AfHw4pl+w5SvxQUF8f2jB
|
||||
XsRY0MrDyb07xC8CAwEAATANBgkqhkiG9w0BAQsFAAOBgQAOEttx/p3xosIm/8sM
|
||||
kIaxR2c/fbYoMbBsX+geaiRu+xNOItbtQpGOhW6Ql981c3EwIjyd34KavplofZIr
|
||||
Slj4jHQFySZaJkegHY+LCAQz9GEg2TMke3MsPJ7nSZS7MUqB2AQt1tLuiXUuRh3V
|
||||
jF4yiqi6lGVmvPJf+y1GXk47KjGB5TCB4gIBATA8MDcxGTAXBgNVBAMTEHRlc3Qu
|
||||
ZXhhbXBsZS5jb20xGjAYBgNVBAoTEVRlc3QgT3JnYW5pemF0aW9uAgEBMA0GCWCG
|
||||
SAFlAwQCAQUAMA0GCSqGSIb3DQEBAQUABIGAMxSC81vzjSiZcJTcSicgCG9879mu
|
||||
p/bikqdHZPyF8UgABjikXXoVJ9IClFRd5/3wRf8ez+hwnxKR8j1vAsDI7U6dXJtr
|
||||
wp0aO7Ua6ecKhI5V0F8nUg5CjEK9FR8vNg0Il8U5AXDuan0iYKvguhWkiuJlvQlV
|
||||
X9ncPP4VRERPw8U=
|
||||
-----END PKCS7-----`;
|
||||
|
||||
const p7 = forge.pkcs7.messageFromPem(mockP7Sign);
|
||||
|
||||
console.log('=== p7.rawCapture ===');
|
||||
console.log('rawCapture keys:', Object.keys(p7.rawCapture || {}));
|
||||
|
||||
if (p7.rawCapture) {
|
||||
for (const key of Object.keys(p7.rawCapture)) {
|
||||
const value = p7.rawCapture[key];
|
||||
if (Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
||||
console.log(`${key}: Buffer/Uint8Array, length=${value.length}`);
|
||||
console.log(`${key} hex:`, Buffer.from(value).toString('hex').substring(0, 100) + '...');
|
||||
} else if (typeof value === 'string') {
|
||||
console.log(`${key}: string, length=${value.length}`);
|
||||
console.log(`${key} content:`, value.substring(0, 100) + '...');
|
||||
} else if (value && typeof value === 'object') {
|
||||
console.log(`${key}: object, keys=${Object.keys(value).join(',')}`);
|
||||
} else {
|
||||
console.log(`${key}:`, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n=== p7.signerInfos ===');
|
||||
console.log('signerInfos:', p7.signerInfos);
|
||||
|
||||
console.log('\n=== p7.signers ===');
|
||||
console.log('signers:', p7.signers);
|
||||
|
||||
console.log('\n=== p7.certificates ===');
|
||||
if (p7.certificates && p7.certificates.length > 0) {
|
||||
const cert = p7.certificates[0];
|
||||
console.log('cert publicKey:', cert.publicKey ? 'exists' : 'null');
|
||||
if (cert.publicKey) {
|
||||
console.log('publicKey type:', typeof cert.publicKey);
|
||||
console.log('publicKey keys:', Object.keys(cert.publicKey));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
const rs = require('jsrsasign');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
console.log('=== 调试签名格式 ===');
|
||||
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
if (p7.sinfos && p7.sinfos.length > 0) {
|
||||
const signer = p7.sinfos[0];
|
||||
console.log('签名算法:', signer.sigalg);
|
||||
console.log('签名值 (signer.sighex):', signer.sighex);
|
||||
console.log('签名值长度:', signer.sighex.length / 2, '字节');
|
||||
console.log('签名值开头:', signer.sighex.substring(0, 10));
|
||||
|
||||
// 检查是否是 ASN.1 DER 格式
|
||||
if (signer.sighex.startsWith('30')) {
|
||||
console.log('签名格式: ASN.1 DER');
|
||||
} else {
|
||||
console.log('签名格式: 原始 r|s');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
const smCrypto = require('sm-crypto');
|
||||
|
||||
console.log('=== 调试 sm-crypto API ===');
|
||||
console.log('sm-crypto 模块:', Object.keys(smCrypto));
|
||||
console.log('sm2 对象:', Object.keys(smCrypto.sm2));
|
||||
console.log('sm3 对象:', typeof smCrypto.sm3);
|
||||
|
||||
// 测试 SM3
|
||||
const testData = 'test';
|
||||
const hash = smCrypto.sm3(testData);
|
||||
console.log('\nSM3 哈希:', hash);
|
||||
|
||||
// 生成密钥对
|
||||
const keypair = smCrypto.sm2.generateKeyPairHex();
|
||||
console.log('\n生成的密钥对:');
|
||||
console.log(' 私钥:', keypair.privateKey.substring(0, 20) + '...');
|
||||
console.log(' 公钥:', keypair.publicKey.substring(0, 20) + '...');
|
||||
|
||||
// 签名
|
||||
const sig = smCrypto.sm2.doSignature(hash, keypair.privateKey);
|
||||
console.log('\n签名:', sig);
|
||||
|
||||
// 验证签名
|
||||
const verifyResult = smCrypto.sm2.doVerifySignature(hash, sig, keypair.publicKey);
|
||||
console.log('验证结果:', verifyResult);
|
||||
@@ -0,0 +1,22 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
|
||||
console.log('=== 检查 sm-crypto 0.3.13 API ===');
|
||||
|
||||
// 检查 sm2 对象的属性
|
||||
console.log('sm2 对象属性:', Object.keys(sm2));
|
||||
|
||||
// 检查 doVerifySignature 函数
|
||||
console.log('\ndoVerifySignature 函数:', sm2.doVerifySignature.toString());
|
||||
|
||||
// 测试生成的签名和公钥
|
||||
const testData = 'test';
|
||||
const keypair = sm2.generateKeyPairHex();
|
||||
const sig = sm2.doSignature(testData, keypair.privateKey);
|
||||
|
||||
console.log('\n测试数据:', testData);
|
||||
console.log('生成的公钥:', keypair.publicKey);
|
||||
console.log('生成的签名:', sig);
|
||||
|
||||
// 验证生成的签名
|
||||
const verifyResult = sm2.doVerifySignature(testData, sig, keypair.publicKey);
|
||||
console.log('验证结果:', verifyResult);
|
||||
@@ -0,0 +1,55 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 调试 sm-crypto 0.3.13 API ===');
|
||||
|
||||
// 测试基本功能
|
||||
const testData = 'test';
|
||||
const hash = sm3(testData);
|
||||
console.log('测试数据:', testData);
|
||||
console.log('SM3 哈希:', hash);
|
||||
|
||||
// 生成密钥对
|
||||
const keypair = sm2.generateKeyPairHex();
|
||||
console.log('\n生成的密钥对:');
|
||||
console.log(' 私钥:', keypair.privateKey);
|
||||
console.log(' 公钥:', keypair.publicKey);
|
||||
|
||||
// 签名
|
||||
const sig = sm2.doSignature(testData, keypair.privateKey);
|
||||
console.log('\n签名:', sig);
|
||||
console.log('签名长度:', sig.length);
|
||||
|
||||
// 验证签名
|
||||
const verifyResult = sm2.doVerifySignature(testData, sig, keypair.publicKey);
|
||||
console.log('验证结果:', verifyResult);
|
||||
|
||||
// 测试用户提供的数据
|
||||
console.log('\n=== 测试用户数据 ===');
|
||||
|
||||
const data = 'QDJNHHVB_FWQ';
|
||||
const signature = '02D3816303EE2A352477F3227070CC34297BD6E89DC86E2C54840FFFC92C3B6766114B6BFA CB00408CC51B8C18D02023F50671844372094D9460BD5F85ACAC50'.replace(/\s/g, '');
|
||||
const publicKey = '04bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
|
||||
console.log('数据:', data);
|
||||
console.log('签名:', signature);
|
||||
console.log('公钥:', publicKey);
|
||||
|
||||
// 尝试验证
|
||||
console.log('\n尝试验证:');
|
||||
try {
|
||||
// 注意:sm-crypto 0.3.13 的 API 可能不同
|
||||
// 尝试不带选项
|
||||
const result1 = sm2.doVerifySignature(data, signature, publicKey);
|
||||
console.log(' 验证结果 (无选项):', result1);
|
||||
} catch (e) {
|
||||
console.error(' 错误 (无选项):', e.message);
|
||||
}
|
||||
|
||||
try {
|
||||
// 尝试带哈希选项
|
||||
const result2 = sm2.doVerifySignature(hash, signature, publicKey, true); // 第二个参数是 hash 选项
|
||||
console.log(' 验证结果 (hash=true):', result2);
|
||||
} catch (e) {
|
||||
console.error(' 错误 (hash=true):', e.message);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
const rs = require('jsrsasign');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据(没有头尾)
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
console.log('=== 调试 SM2 证书提取 ===');
|
||||
console.log('p7 keys:', Object.keys(p7));
|
||||
console.log('p7.certs:', p7.certs);
|
||||
console.log('p7.sinfos:', p7.sinfos);
|
||||
|
||||
// 尝试直接解析证书
|
||||
console.log('\n=== 直接解析证书 ===');
|
||||
try {
|
||||
// 从 hex 中提取证书
|
||||
const hex = rs.b64tohex(sm2P7Base64);
|
||||
console.log('hex length:', hex.length);
|
||||
|
||||
// 使用 ASN1HEX 解析
|
||||
const hCert = rs.ASN1HEX.getTLVbyList(hex, 0, [0, 3, 0, 0]);
|
||||
console.log('hCert:', hCert ? hCert.substring(0, 50) + '...' : 'null');
|
||||
|
||||
if (hCert) {
|
||||
const certPem = rs.KJUR.asn1.ASN1Util.getPEMStringFromHex(hCert, 'CERTIFICATE');
|
||||
console.log('certPem:', certPem.substring(0, 200));
|
||||
|
||||
const x509 = new rs.X509();
|
||||
x509.readCertPEM(certPem);
|
||||
|
||||
console.log('\n主题:', x509.getSubjectString());
|
||||
console.log('颁发者:', x509.getIssuerString());
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
|
||||
console.log('=== 调试 SM2 DER 格式 ===');
|
||||
|
||||
// 测试数据
|
||||
const data = 'QDJNHHVB_FWQ';
|
||||
const userId = '1234567812345678';
|
||||
|
||||
// 生成密钥对
|
||||
const keypair = sm2.generateKeyPairHex();
|
||||
console.log('公钥:', keypair.publicKey);
|
||||
|
||||
// 生成签名(带 der 选项)
|
||||
const sigWithDer = sm2.doSignature(data, keypair.privateKey, { der: true });
|
||||
console.log('\n带 DER 的签名:', sigWithDer);
|
||||
console.log('带 DER 的签名长度:', sigWithDer.length);
|
||||
|
||||
// 生成签名(不带 der 选项)
|
||||
const sigWithoutDer = sm2.doSignature(data, keypair.privateKey);
|
||||
console.log('\n不带 DER 的签名:', sigWithoutDer);
|
||||
console.log('不带 DER 的签名长度:', sigWithoutDer.length);
|
||||
|
||||
// 验证带 DER 的签名
|
||||
const verifyWithDer = sm2.doVerifySignature(data, sigWithDer, keypair.publicKey, { der: true });
|
||||
console.log('\n验证带 DER 的签名:', verifyWithDer);
|
||||
|
||||
// 验证不带 DER 的签名
|
||||
const verifyWithoutDer = sm2.doVerifySignature(data, sigWithoutDer, keypair.publicKey);
|
||||
console.log('验证不带 DER 的签名:', verifyWithoutDer);
|
||||
@@ -0,0 +1,42 @@
|
||||
const crypto = require('../src/crypto.js');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
console.log('=== 测试不同的原始数据 ===');
|
||||
|
||||
// 测试不同的原始数据
|
||||
const testDataList = [
|
||||
'QDJNHHVB_FWQ',
|
||||
'QDJNHHVB_FWQ\n',
|
||||
'QDJNHHVB_FWQ\r\n',
|
||||
'QDJNHHVB FWQ', // 空格替换下划线
|
||||
'QDJNHHVB_FW', // 少一个字符
|
||||
'QDJNHHVB_FWQQ', // 多一个字符
|
||||
'qDJNHHVB_FWQ', // 小写
|
||||
'QDJnhhVB_FWQ', // 混合大小写
|
||||
'1234567890', // 数字
|
||||
'', // 空字符串
|
||||
];
|
||||
|
||||
testDataList.forEach((data, index) => {
|
||||
console.log(`\n测试数据 ${index + 1}: "${data}"`);
|
||||
console.log(` 长度: ${data.length}`);
|
||||
console.log(` UTF-8 编码: ${Buffer.from(data, 'utf8').toString('hex')}`);
|
||||
|
||||
const result = crypto.verifyPKCS7(sm2P7Base64, data);
|
||||
console.log(` 验证结果: ${result}`);
|
||||
|
||||
if (result) {
|
||||
console.log(' ✅ 验证成功!');
|
||||
}
|
||||
});
|
||||
|
||||
// 也测试一下 attach 模式
|
||||
console.log('\n=== 测试 attach 模式 ===');
|
||||
try {
|
||||
const result = crypto.verifyPKCS7(sm2P7Base64);
|
||||
console.log('attach 模式验证结果:', result);
|
||||
} catch (e) {
|
||||
console.error('attach 模式错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
const rs = require('jsrsasign');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据(没有头尾)
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
console.log('=== 调试 SM2 公钥提取 ===');
|
||||
|
||||
if (p7.certs && p7.certs.array && p7.certs.array.length > 0) {
|
||||
const certPem = p7.certs.array[0];
|
||||
console.log('证书 PEM 前200字符:', certPem.substring(0, 200));
|
||||
|
||||
const x509 = new rs.X509();
|
||||
x509.readCertPEM(certPem);
|
||||
|
||||
console.log('\n证书信息:');
|
||||
console.log('主题:', x509.getSubjectString());
|
||||
console.log('颁发者:', x509.getIssuerString());
|
||||
console.log('序列号:', x509.getSerialNumberHex());
|
||||
|
||||
// 尝试获取公钥
|
||||
console.log('\n尝试获取公钥:');
|
||||
try {
|
||||
const pubKey = x509.getPublicKey();
|
||||
console.log('getPublicKey() 结果:', pubKey);
|
||||
|
||||
if (pubKey) {
|
||||
console.log('公钥类型:', typeof pubKey);
|
||||
console.log('公钥 keys:', Object.keys(pubKey));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('getPublicKey() 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试直接从 ASN.1 解析
|
||||
console.log('\n尝试从 ASN.1 解析公钥:');
|
||||
try {
|
||||
const hex = rs.pemtohex(certPem);
|
||||
// 证书结构: SEQUENCE -> tbsCertificate -> subjectPublicKeyInfo
|
||||
const hTBS = rs.ASN1HEX.getTLVbyList(hex, 0, [0]);
|
||||
const hSPKI = rs.ASN1HEX.getTLVbyList(hTBS, 0, [6]); // subjectPublicKeyInfo 通常在第6个位置
|
||||
|
||||
if (hSPKI) {
|
||||
console.log('subjectPublicKeyInfo hex:', hSPKI.substring(0, 100) + '...');
|
||||
|
||||
// 提取公钥值
|
||||
const hAlgorithm = rs.ASN1HEX.getTLVbyList(hSPKI, 0, [0]);
|
||||
const hPublicKey = rs.ASN1HEX.getTLVbyList(hSPKI, 0, [1]);
|
||||
|
||||
if (hAlgorithm) {
|
||||
console.log('算法 OID:', rs.ASN1HEX.getOIDbyList(hAlgorithm, 0, [0]));
|
||||
}
|
||||
|
||||
if (hPublicKey) {
|
||||
console.log('公钥值 hex:', hPublicKey.substring(4) + '...'); // 跳过 tag 和 length
|
||||
|
||||
// 尝试创建 PEM
|
||||
const pubKeyPem = rs.KJUR.asn1.ASN1Util.getPEMStringFromHex(hSPKI, 'PUBLIC KEY');
|
||||
console.log('公钥 PEM:', pubKeyPem.substring(0, 200) + '...');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('ASN.1 解析错误:', e.message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
const rs = require('jsrsasign');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
console.log('=== 调试 SM2 公钥提取 ===');
|
||||
|
||||
if (p7.certs && p7.certs.array && p7.certs.array.length > 0) {
|
||||
const certPem = p7.certs.array[0];
|
||||
|
||||
// 将 PEM 转换为 hex
|
||||
const certHex = rs.pemtohex(certPem);
|
||||
console.log('证书 hex 长度:', certHex.length);
|
||||
console.log('证书 hex 前100字符:', certHex.substring(0, 100));
|
||||
|
||||
// 证书结构: SEQUENCE { tbsCertificate, signatureAlgorithm, signatureValue }
|
||||
// tbsCertificate 结构: SEQUENCE { version, serialNumber, signature, issuer, validity, subject, subjectPublicKeyInfo, ... }
|
||||
|
||||
try {
|
||||
// 获取 tbsCertificate
|
||||
const tbsCert = rs.ASN1HEX.getTLVbyList(certHex, 0, [0]);
|
||||
console.log('\ntbsCertificate 长度:', tbsCert.length);
|
||||
|
||||
// 获取 subjectPublicKeyInfo (在 tbsCertificate 中的索引通常是 6)
|
||||
// 但我们需要先确定正确的索引
|
||||
let spkiIndex = 6;
|
||||
let spki = null;
|
||||
|
||||
// 尝试不同的索引
|
||||
for (let i = 3; i <= 8; i++) {
|
||||
try {
|
||||
const tlv = rs.ASN1HEX.getTLVbyList(tbsCert, 0, [i]);
|
||||
if (tlv && tlv.startsWith('30')) { // SEQUENCE
|
||||
// 检查是否是 subjectPublicKeyInfo
|
||||
// subjectPublicKeyInfo 应该包含 algorithm 和 subjectPublicKey
|
||||
const inner = rs.ASN1HEX.getTLVbyList(tlv, 0, [0]);
|
||||
if (inner && inner.startsWith('30')) {
|
||||
console.log(`索引 ${i} 可能是 subjectPublicKeyInfo`);
|
||||
spki = tlv;
|
||||
spkiIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略错误
|
||||
}
|
||||
}
|
||||
|
||||
if (spki) {
|
||||
console.log('\nsubjectPublicKeyInfo hex:', spki.substring(0, 100));
|
||||
|
||||
// 提取算法 OID
|
||||
try {
|
||||
const algorithmSeq = rs.ASN1HEX.getTLVbyList(spki, 0, [0]);
|
||||
console.log('algorithmSeq:', algorithmSeq);
|
||||
|
||||
// 提取 OID
|
||||
const oidTlv = rs.ASN1HEX.getTLVbyList(algorithmSeq, 0, [0]);
|
||||
console.log('OID TLV:', oidTlv);
|
||||
|
||||
// 解析 OID
|
||||
if (oidTlv && oidTlv.startsWith('06')) {
|
||||
const oidHex = oidTlv.substring(4);
|
||||
console.log('OID hex:', oidHex);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('提取算法 OID 错误:', e.message);
|
||||
}
|
||||
|
||||
// 提取公钥值 (BIT STRING)
|
||||
try {
|
||||
const publicKeyBitString = rs.ASN1HEX.getTLVbyList(spki, 0, [1]);
|
||||
console.log('\n公钥 BIT STRING:', publicKeyBitString.substring(0, 100));
|
||||
|
||||
// BIT STRING 的内容从第4个字符开始 (跳过 tag 03, length, 和 unused bits 00)
|
||||
const publicKeyContent = publicKeyBitString.substring(4);
|
||||
console.log('公钥内容:', publicKeyContent.substring(0, 100));
|
||||
|
||||
// 对于 SM2,公钥通常是 65 字节 (0x04 + 32字节 X + 32字节 Y)
|
||||
console.log('公钥内容长度:', publicKeyContent.length / 2, '字节');
|
||||
|
||||
// 创建公钥 hex
|
||||
console.log('\n公钥 hex (完整):', publicKeyContent);
|
||||
} catch (e) {
|
||||
console.error('提取公钥值错误:', e.message);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('ASN.1 解析错误:', e.message);
|
||||
console.error(e.stack);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 调试 SM2 公钥格式 ===');
|
||||
|
||||
// 测试数据
|
||||
const testData = 'QDJNHHVB_FWQ';
|
||||
const hash = sm3(testData);
|
||||
console.log('测试数据:', testData);
|
||||
console.log('SM3 哈希:', hash);
|
||||
|
||||
// 用户提供的签名(ASN.1 DER 格式)
|
||||
const userSignature = '3044022002d3816303ee2a352477f3227070cc34297bd6e89dc86e2c54840fffc92c3b67022066114b6bfacb00408cc51b8c18d02023f50671844372094d9460bd5f85acac50';
|
||||
|
||||
// 解析签名
|
||||
const rStart = 8;
|
||||
const r = userSignature.substring(rStart, rStart + 64);
|
||||
const sStart = rStart + 64 + 4;
|
||||
const s = userSignature.substring(sStart, sStart + 64);
|
||||
const rawSignature = r + s;
|
||||
console.log('\n原始签名格式:', rawSignature);
|
||||
|
||||
// 用户公钥
|
||||
const userPublicKey = '04bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
console.log('\n完整公钥:', userPublicKey);
|
||||
|
||||
// 去掉 04 前缀
|
||||
const pubKeyWithoutPrefix = userPublicKey.substring(2);
|
||||
console.log('去掉前缀的公钥:', pubKeyWithoutPrefix);
|
||||
|
||||
// 尝试验证
|
||||
console.log('\n验证结果:');
|
||||
try {
|
||||
const result1 = sm2.doVerifySignature(hash, rawSignature, userPublicKey);
|
||||
console.log(' 使用完整公钥:', result1);
|
||||
} catch (e) {
|
||||
console.error(' 完整公钥错误:', e.message);
|
||||
}
|
||||
|
||||
try {
|
||||
const result2 = sm2.doVerifySignature(hash, rawSignature, pubKeyWithoutPrefix);
|
||||
console.log(' 使用去掉前缀的公钥:', result2);
|
||||
} catch (e) {
|
||||
console.error(' 去掉前缀错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
|
||||
console.log('=== 测试公钥格式 ===');
|
||||
|
||||
// 测试数据
|
||||
const data = 'QDJNHHVB_FWQ';
|
||||
const signature = '02D3816303EE2A352477F3227070CC34297BD6E89DC86E2C54840FFFC92C3B6766114B6BFACB00408CC51B8C18D02023F50671844372094D9460BD5F85ACAC50';
|
||||
|
||||
// 完整公钥(带 04 前缀)
|
||||
const fullPublicKey = '04bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
|
||||
// 去掉 04 前缀的公钥
|
||||
const publicKeyWithoutPrefix = fullPublicKey.substring(2);
|
||||
|
||||
console.log('完整公钥:', fullPublicKey);
|
||||
console.log('去掉前缀的公钥:', publicKeyWithoutPrefix);
|
||||
|
||||
// 测试完整公钥
|
||||
console.log('\n使用完整公钥:');
|
||||
try {
|
||||
const result1 = sm2.doVerifySignature(data, signature, fullPublicKey);
|
||||
console.log(' 验证结果:', result1);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 测试去掉前缀的公钥
|
||||
console.log('\n使用去掉前缀的公钥:');
|
||||
try {
|
||||
const result2 = sm2.doVerifySignature(data, signature, publicKeyWithoutPrefix);
|
||||
console.log(' 验证结果:', result2);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 测试带哈希选项
|
||||
console.log('\n使用去掉前缀的公钥 + 哈希:');
|
||||
try {
|
||||
const result3 = sm2.doVerifySignature(data, signature, publicKeyWithoutPrefix, true);
|
||||
console.log(' 验证结果:', result3);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 调试 SM2 签名格式 ===');
|
||||
|
||||
// 生成测试数据
|
||||
const testData = 'QDJNHHVB_FWQ';
|
||||
const hash = sm3(testData);
|
||||
console.log('测试数据:', testData);
|
||||
console.log('SM3 哈希:', hash);
|
||||
|
||||
// 生成密钥对
|
||||
const keypair = sm2.generateKeyPairHex();
|
||||
console.log('\n生成的密钥对:');
|
||||
console.log(' 私钥:', keypair.privateKey);
|
||||
console.log(' 公钥:', keypair.publicKey);
|
||||
|
||||
// 生成签名
|
||||
const sig = sm2.doSignature(hash, keypair.privateKey);
|
||||
console.log('\nsm-crypto 生成的签名:', sig);
|
||||
console.log('签名长度:', sig.length);
|
||||
|
||||
// 验证签名
|
||||
const verifyResult = sm2.doVerifySignature(hash, sig, keypair.publicKey);
|
||||
console.log('验证结果:', verifyResult);
|
||||
|
||||
// 对比用户提供的签名
|
||||
const userSignature = '3044022002d3816303ee2a352477f3227070cc34297bd6e89dc86e2c54840fffc92c3b67022066114b6bfacb00408cc51b8c18d02023f50671844372094d9460bd5f85acac50';
|
||||
console.log('\n用户提供的签名:', userSignature);
|
||||
console.log('用户签名长度:', userSignature.length);
|
||||
|
||||
// 分析签名格式
|
||||
console.log('\n签名格式分析:');
|
||||
console.log('sm-crypto 签名格式:', sig.length === 128 ? '原始 r|s 格式' : '其他格式');
|
||||
console.log('用户签名格式:', userSignature.startsWith('30') ? 'ASN.1 DER 格式' : '其他格式');
|
||||
|
||||
// 尝试转换用户签名格式
|
||||
if (userSignature.startsWith('30')) {
|
||||
console.log('\n尝试将 ASN.1 DER 格式转换为原始格式:');
|
||||
try {
|
||||
// 解析 ASN.1 DER 格式
|
||||
// 格式: 30 len 02 len r 02 len s
|
||||
const rStart = 6; // 30 44 02 20
|
||||
const rLen = parseInt(userSignature.substring(4, 6), 16) * 2;
|
||||
const r = userSignature.substring(rStart, rStart + rLen);
|
||||
|
||||
const sStart = rStart + rLen + 4; // 02 20
|
||||
const sLen = parseInt(userSignature.substring(rStart + rLen + 2, rStart + rLen + 4), 16) * 2;
|
||||
const s = userSignature.substring(sStart, sStart + sLen);
|
||||
|
||||
console.log(' 提取的 r:', r);
|
||||
console.log(' 提取的 s:', s);
|
||||
|
||||
// 组合成原始格式
|
||||
const rawSignature = r + s;
|
||||
console.log(' 转换后的原始格式:', rawSignature);
|
||||
console.log(' 原始格式长度:', rawSignature.length);
|
||||
|
||||
// 尝试验证
|
||||
const userPublicKey = '04bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
const result = sm2.doVerifySignature(hash, rawSignature, userPublicKey);
|
||||
console.log(' 验证结果:', result);
|
||||
|
||||
} catch (e) {
|
||||
console.error(' 转换错误:', e.message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 调试 SM2 签名格式(正确解析)===');
|
||||
|
||||
// 测试数据
|
||||
const testData = 'QDJNHHVB_FWQ';
|
||||
const hash = sm3(testData);
|
||||
console.log('测试数据:', testData);
|
||||
console.log('SM3 哈希:', hash);
|
||||
|
||||
// 用户提供的签名(ASN.1 DER 格式)
|
||||
const userSignature = '3044022002d3816303ee2a352477f3227070cc34297bd6e89dc86e2c54840fffc92c3b67022066114b6bfacb00408cc51b8c18d02023f50671844372094d9460bd5f85acac50';
|
||||
console.log('\n用户提供的签名:', userSignature);
|
||||
|
||||
// 正确解析 ASN.1 DER 格式
|
||||
console.log('\n正确解析 ASN.1 DER 格式:');
|
||||
try {
|
||||
// 30 44 02 20 [r] 02 20 [s]
|
||||
// 30 = 序列
|
||||
// 44 = 长度 68 字节
|
||||
// 02 = 整数
|
||||
// 20 = 长度 32 字节
|
||||
|
||||
// 提取 r 值
|
||||
const rStart = 8; // 30440220
|
||||
const r = userSignature.substring(rStart, rStart + 64); // 32字节 = 64 hex 字符
|
||||
console.log(' r 值:', r);
|
||||
|
||||
// 提取 s 值
|
||||
const sStart = rStart + 64 + 4; // 0220
|
||||
const s = userSignature.substring(sStart, sStart + 64); // 32字节 = 64 hex 字符
|
||||
console.log(' s 值:', s);
|
||||
|
||||
// 组合成原始格式 (r + s)
|
||||
const rawSignature = r + s;
|
||||
console.log(' 转换后的原始格式:', rawSignature);
|
||||
console.log(' 原始格式长度:', rawSignature.length);
|
||||
|
||||
// 用户公钥
|
||||
const userPublicKey = '04bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
console.log('\n用户公钥:', userPublicKey);
|
||||
|
||||
// 尝试验证
|
||||
const result = sm2.doVerifySignature(hash, rawSignature, userPublicKey);
|
||||
console.log('\n验证结果:', result);
|
||||
|
||||
} catch (e) {
|
||||
console.error('解析错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
const rs = require('jsrsasign');
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
// 测试用的原始数据
|
||||
const mockOriginalData = 'QDJNHHVB_FWQ';
|
||||
|
||||
console.log('=== 调试 SM2 PKCS7 验证 ===');
|
||||
console.log('原始数据:', mockOriginalData);
|
||||
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
console.log('\nPKCS7 信息:');
|
||||
console.log('版本:', p7.version);
|
||||
console.log('哈希算法:', p7.hashalgs);
|
||||
console.log('签名者数量:', p7.sinfos ? p7.sinfos.length : 0);
|
||||
|
||||
if (p7.sinfos && p7.sinfos.length > 0) {
|
||||
const signer = p7.sinfos[0];
|
||||
console.log('\n签名者信息:');
|
||||
console.log(' 签名算法:', signer.sigalg);
|
||||
console.log(' 签名值 (hex):', signer.sighex);
|
||||
console.log(' 签名值长度:', signer.sighex ? signer.sighex.length / 2 : 0, '字节');
|
||||
}
|
||||
|
||||
// 提取原始数据(econtent)
|
||||
if (p7.econtent && p7.econtent.hex) {
|
||||
const extractedData = Buffer.from(p7.econtent.hex, 'hex').toString();
|
||||
console.log('\n从 PKCS7 提取的原始数据:', extractedData);
|
||||
console.log('与提供的原始数据匹配:', extractedData === mockOriginalData);
|
||||
}
|
||||
|
||||
// 提取公钥
|
||||
if (p7.certs && p7.certs.array && p7.certs.array.length > 0) {
|
||||
const certPem = p7.certs.array[0];
|
||||
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);
|
||||
|
||||
console.log('\n公钥信息:');
|
||||
console.log(' 公钥 (hex):', publicKeyHex.substring(0, 50) + '...');
|
||||
console.log(' 公钥长度:', publicKeyHex.length / 2, '字节');
|
||||
|
||||
// 尝试验证签名
|
||||
if (p7.sinfos && p7.sinfos.length > 0) {
|
||||
const signer = p7.sinfos[0];
|
||||
|
||||
// 计算 SM3 哈希
|
||||
const hash = sm3(mockOriginalData);
|
||||
console.log('\nSM3 哈希:', hash);
|
||||
|
||||
// 尝试验证
|
||||
console.log('\n尝试使用 sm-crypto 验证:');
|
||||
try {
|
||||
// sm-crypto 的 doVerify 需要 hash 和公钥
|
||||
// 注意:sm-crypto 的 API 可能需要不同的格式
|
||||
const result = sm2.doVerify(hash, signer.sighex, publicKeyHex);
|
||||
console.log('验证结果:', result);
|
||||
} catch (e) {
|
||||
console.error('验证错误:', e.message);
|
||||
|
||||
// 尝试其他格式
|
||||
console.log('\n尝试其他格式...');
|
||||
try {
|
||||
// 可能需要去掉 04 前缀
|
||||
const pubKeyWithoutPrefix = publicKeyHex.substring(2);
|
||||
const result = sm2.doVerify(hash, signer.sighex, pubKeyWithoutPrefix);
|
||||
console.log('验证结果 (去掉前缀):', result);
|
||||
} catch (e2) {
|
||||
console.error('验证错误 (去掉前缀):', e2.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
const rs = require('jsrsasign');
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
// 测试用的原始数据
|
||||
const mockOriginalData = 'QDJNHHVB_FWQ';
|
||||
|
||||
console.log('=== 详细调试 SM2 PKCS7 验证 ===');
|
||||
console.log('原始数据:', mockOriginalData);
|
||||
console.log('原始数据长度:', mockOriginalData.length);
|
||||
console.log('原始数据 UTF-8 编码:', Buffer.from(mockOriginalData, 'utf8').toString('hex'));
|
||||
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
console.log('\nPKCS7 信息:');
|
||||
console.log('版本:', p7.version);
|
||||
console.log('哈希算法:', p7.hashalgs);
|
||||
console.log('签名者数量:', p7.sinfos ? p7.sinfos.length : 0);
|
||||
|
||||
if (p7.sinfos && p7.sinfos.length > 0) {
|
||||
const signer = p7.sinfos[0];
|
||||
console.log('\n签名者信息:');
|
||||
console.log(' 签名算法:', signer.sigalg);
|
||||
console.log(' 签名值 (hex):', signer.sighex);
|
||||
console.log(' 签名值长度:', signer.sighex ? signer.sighex.length / 2 : 0, '字节');
|
||||
|
||||
// 解析签名值(ASN.1 DER 格式)
|
||||
console.log('\n解析签名值:');
|
||||
try {
|
||||
const sigAsn1 = rs.ASN1HEX.getTLVbyList(signer.sighex, 0, []);
|
||||
console.log(' 签名 ASN.1 结构:', sigAsn1);
|
||||
|
||||
// 提取 r 和 s 值
|
||||
const r = rs.ASN1HEX.getTLVbyList(sigAsn1, 0, [0]);
|
||||
const s = rs.ASN1HEX.getTLVbyList(sigAsn1, 0, [1]);
|
||||
console.log(' r 值:', r.substring(4)); // 跳过 tag 和 length
|
||||
console.log(' s 值:', s.substring(4));
|
||||
} catch (e) {
|
||||
console.error(' 解析签名值错误:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 提取公钥
|
||||
if (p7.certs && p7.certs.array && p7.certs.array.length > 0) {
|
||||
const certPem = p7.certs.array[0];
|
||||
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);
|
||||
|
||||
console.log('\n公钥信息:');
|
||||
console.log(' 公钥 (hex):', publicKeyHex);
|
||||
console.log(' 公钥长度:', publicKeyHex.length / 2, '字节');
|
||||
console.log(' 公钥格式:', publicKeyHex.startsWith('04') ? '未压缩格式' : '压缩格式');
|
||||
|
||||
// 尝试验证签名
|
||||
if (p7.sinfos && p7.sinfos.length > 0) {
|
||||
const signer = p7.sinfos[0];
|
||||
|
||||
// 计算 SM3 哈希
|
||||
console.log('\n计算 SM3 哈希:');
|
||||
const hash = sm3(mockOriginalData);
|
||||
console.log(' 原始数据哈希:', hash);
|
||||
|
||||
// 测试不同的公钥格式
|
||||
console.log('\n测试不同的公钥格式:');
|
||||
|
||||
// 1. 使用完整公钥(带 04 前缀)
|
||||
try {
|
||||
const result1 = sm2.doVerifySignature(hash, signer.sighex, publicKeyHex);
|
||||
console.log(' 验证结果(完整公钥):', result1);
|
||||
} catch (e) {
|
||||
console.error(' 验证错误(完整公钥):', e.message);
|
||||
}
|
||||
|
||||
// 2. 使用不带 04 前缀的公钥
|
||||
try {
|
||||
const pubKeyWithoutPrefix = publicKeyHex.substring(2);
|
||||
const result2 = sm2.doVerifySignature(hash, signer.sighex, pubKeyWithoutPrefix);
|
||||
console.log(' 验证结果(不带前缀):', result2);
|
||||
} catch (e) {
|
||||
console.error(' 验证错误(不带前缀):', e.message);
|
||||
}
|
||||
|
||||
// 3. 尝试使用签名值的不同格式
|
||||
console.log('\n测试不同的签名值格式:');
|
||||
try {
|
||||
// 直接使用 sighex
|
||||
const result3 = sm2.doVerifySignature(hash, signer.sighex, publicKeyHex);
|
||||
console.log(' 验证结果(直接使用 sighex):', result3);
|
||||
} catch (e) {
|
||||
console.error(' 验证错误(直接使用 sighex):', e.message);
|
||||
}
|
||||
|
||||
// 4. 测试不同的编码
|
||||
console.log('\n测试不同的编码:');
|
||||
try {
|
||||
// 使用 Buffer 转换
|
||||
const hashBuffer = Buffer.from(mockOriginalData, 'utf8');
|
||||
const hash2 = sm3(hashBuffer);
|
||||
console.log(' Buffer 哈希:', hash2);
|
||||
const result4 = sm2.doVerifySignature(hash2, signer.sighex, publicKeyHex);
|
||||
console.log(' 验证结果(Buffer 编码):', result4);
|
||||
} catch (e) {
|
||||
console.error(' 验证错误(Buffer 编码):', e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 检查 sm-crypto 版本 ===');
|
||||
console.log('sm-crypto 版本:', require('sm-crypto/package.json').version);
|
||||
|
||||
// 测试公钥格式
|
||||
console.log('\n=== 测试公钥格式 ===');
|
||||
|
||||
// 生成一个有效的 SM2 密钥对
|
||||
const keypair = sm2.generateKeyPairHex();
|
||||
console.log('生成的公钥:', keypair.publicKey);
|
||||
console.log('生成的公钥长度:', keypair.publicKey.length);
|
||||
|
||||
// 用户提供的公钥
|
||||
const userPublicKey = 'bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
console.log('\n用户提供的公钥:', userPublicKey);
|
||||
console.log('用户提供的公钥长度:', userPublicKey.length);
|
||||
|
||||
// 测试用户公钥
|
||||
console.log('\n=== 测试用户公钥 ===');
|
||||
try {
|
||||
const data = 'test';
|
||||
const sig = sm2.doSignature(data, keypair.privateKey);
|
||||
|
||||
// 尝试使用生成的公钥验证(应该成功)
|
||||
const verify1 = sm2.doVerifySignature(data, sig, keypair.publicKey);
|
||||
console.log('使用生成的公钥验证:', verify1);
|
||||
|
||||
// 尝试使用用户公钥验证(应该失败)
|
||||
const verify2 = sm2.doVerifySignature(data, sig, userPublicKey);
|
||||
console.log('使用用户公钥验证:', verify2);
|
||||
} catch (e) {
|
||||
console.error('错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 验证用户提供的具体数据 ===');
|
||||
|
||||
// 用户提供的数据
|
||||
const dataHex = '51444A4E484856425F465751';
|
||||
const signatureHex = '02D3816303EE2A352477F3227070CC34297BD6E89DC86E2C54840FFFC92C3B6766114B6BFA CB00408CC51B8C18D02023F50671844372094D9460BD5F85ACAC50'.replace(/\s/g, '');
|
||||
const userId = '1234567812345678';
|
||||
const hashHex = '0F76D50E476E24507187885DF1BC197B48F368F3C03DDF0A5C0C067D2EEF63EE';
|
||||
|
||||
// 从用户的 PKCS7 签名中提取的公钥
|
||||
const publicKeyHex = '04bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
|
||||
// 转换数据
|
||||
const data = Buffer.from(dataHex, 'hex').toString('utf8');
|
||||
console.log('数据:', data);
|
||||
console.log('数据长度:', data.length);
|
||||
console.log('签名:', signatureHex);
|
||||
console.log('签名长度:', signatureHex.length / 2, '字节');
|
||||
console.log('公钥:', publicKeyHex);
|
||||
|
||||
// 测试不同的验证选项
|
||||
console.log('\n测试不同的验证选项:');
|
||||
|
||||
// 尝试 1: 使用原始数据 + DER + SM3 + userId
|
||||
console.log('\n1. 使用原始数据 + DER + SM3 + userId:');
|
||||
try {
|
||||
const result1 = sm2.doVerifySignature(data, signatureHex, publicKeyHex, { der: true, hash: true, userId });
|
||||
console.log(' 验证结果:', result1);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 2: 使用哈希 + DER
|
||||
console.log('\n2. 使用哈希 + DER:');
|
||||
try {
|
||||
const result2 = sm2.doVerifySignature(hashHex, signatureHex, publicKeyHex, { der: true });
|
||||
console.log(' 验证结果:', result2);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 3: 使用原始数据 + DER
|
||||
console.log('\n3. 使用原始数据 + DER:');
|
||||
try {
|
||||
const result3 = sm2.doVerifySignature(data, signatureHex, publicKeyHex, { der: true });
|
||||
console.log(' 验证结果:', result3);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 4: 直接使用哈希
|
||||
console.log('\n4. 直接使用哈希:');
|
||||
try {
|
||||
const result4 = sm2.doVerifySignature(hashHex, signatureHex, publicKeyHex);
|
||||
console.log(' 验证结果:', result4);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 5: 直接使用原始数据
|
||||
console.log('\n5. 直接使用原始数据:');
|
||||
try {
|
||||
const result5 = sm2.doVerifySignature(data, signatureHex, publicKeyHex);
|
||||
console.log(' 验证结果:', result5);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 验证用户提供的 SM2 数据 ===');
|
||||
|
||||
// 用户提供的数据
|
||||
const dataHex = '51444A4E484856425F465751';
|
||||
const signatureHex = '02D3816303EE2A352477F3227070CC34297BD6E89DC86E2C54840FFFC92C3B6766114B6BFA CB00408CC51B8C18D02023F50671844372094D9460BD5F85ACAC50'.replace(/\s/g, '');
|
||||
const userId = '1234567812345678';
|
||||
const hashHex = '0F76D50E476E24507187885DF1BC197B48F368F3C03DDF0A5C0C067D2EEF63EE';
|
||||
|
||||
// 从用户的 PKCS7 签名中提取的公钥
|
||||
const publicKeyHex = '04bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
|
||||
// 转换数据
|
||||
const data = Buffer.from(dataHex, 'hex').toString('utf8');
|
||||
console.log('数据:', data);
|
||||
console.log('数据长度:', data.length);
|
||||
console.log('签名长度:', signatureHex.length / 2, '字节');
|
||||
|
||||
// 去掉公钥的 04 前缀
|
||||
const pubKeyWithoutPrefix = publicKeyHex.substring(2);
|
||||
console.log('公钥(去掉前缀):', pubKeyWithoutPrefix);
|
||||
|
||||
// 测试不同的验证选项
|
||||
console.log('\n测试不同的验证选项:');
|
||||
|
||||
// 尝试 1: 使用哈希 + userId
|
||||
console.log('\n1. 使用哈希 + userId:');
|
||||
try {
|
||||
const result1 = sm2.doVerifySignature(hashHex, signatureHex, pubKeyWithoutPrefix, { hash: true, userId });
|
||||
console.log(' 验证结果:', result1);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 2: 使用原始数据 + userId
|
||||
console.log('\n2. 使用原始数据 + userId:');
|
||||
try {
|
||||
const result2 = sm2.doVerifySignature(data, signatureHex, pubKeyWithoutPrefix, { hash: true, userId });
|
||||
console.log(' 验证结果:', result2);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 3: 使用原始数据 + userId + 公钥
|
||||
console.log('\n3. 使用原始数据 + userId + 公钥:');
|
||||
try {
|
||||
const result3 = sm2.doVerifySignature(data, signatureHex, pubKeyWithoutPrefix, { hash: true, userId, publicKey: pubKeyWithoutPrefix });
|
||||
console.log(' 验证结果:', result3);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 4: 直接使用原始数据
|
||||
console.log('\n4. 直接使用原始数据:');
|
||||
try {
|
||||
const result4 = sm2.doVerifySignature(data, signatureHex, pubKeyWithoutPrefix);
|
||||
console.log(' 验证结果:', result4);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 5: 使用 DER 格式
|
||||
console.log('\n5. 使用 DER 格式:');
|
||||
try {
|
||||
const result5 = sm2.doVerifySignature(data, signatureHex, pubKeyWithoutPrefix, { der: true });
|
||||
console.log(' 验证结果:', result5);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 6: 使用 DER + 哈希 + userId
|
||||
console.log('\n6. 使用 DER + 哈希 + userId:');
|
||||
try {
|
||||
const result6 = sm2.doVerifySignature(data, signatureHex, pubKeyWithoutPrefix, { der: true, hash: true, userId });
|
||||
console.log(' 验证结果:', result6);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
|
||||
console.log('=== 验证用户提供的 SM2 数据 ===');
|
||||
|
||||
// 用户提供的数据
|
||||
const dataHex = '51444A4E484856425F465751';
|
||||
const signatureHex = '02D3816303EE2A352477F3227070CC34297BD6E89DC86E2C54840FFFC92C3B6766114B6BFA CB00408CC51B8C18D02023F50671844372094D9460BD5F85ACAC50'.replace(/\s/g, '');
|
||||
const userId = '1234567812345678';
|
||||
const hashHex = '0F76D50E476E24507187885DF1BC197B48F368F3C03DDF0A5C0C067D2EEF63EE';
|
||||
|
||||
// 从用户的 PKCS7 签名中提取的公钥(去掉 04 前缀)
|
||||
const publicKeyHex = 'bb7754e559f6d158d52fdc4608244f07f12901363a1d6db8fb3219bf8e827efd11d8f18cf9926cfdd61aaf0eea2429e921b7b94f43ca9b2c89213355ad59e731';
|
||||
|
||||
// 转换数据
|
||||
const data = Buffer.from(dataHex, 'hex').toString('utf8');
|
||||
console.log('数据:', data);
|
||||
console.log('数据长度:', data.length);
|
||||
console.log('签名:', signatureHex);
|
||||
console.log('签名长度:', signatureHex.length / 2, '字节');
|
||||
console.log('公钥:', publicKeyHex);
|
||||
console.log('userId:', userId);
|
||||
|
||||
// 计算哈希
|
||||
const calculatedHash = sm3(data);
|
||||
console.log('\n计算的哈希:', calculatedHash);
|
||||
console.log('用户提供的哈希:', hashHex);
|
||||
console.log('哈希是否匹配:', calculatedHash === hashHex);
|
||||
|
||||
// 测试不同的验证选项
|
||||
console.log('\n测试不同的验证选项:');
|
||||
|
||||
// 尝试 1: 直接验证(原始 r|s 格式)
|
||||
console.log('\n1. 直接验证(原始 r|s 格式):');
|
||||
try {
|
||||
const result1 = sm2.doVerifySignature(data, signatureHex, publicKeyHex);
|
||||
console.log(' 验证结果:', result1);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 2: 带 SM3 哈希
|
||||
console.log('\n2. 带 SM3 哈希:');
|
||||
try {
|
||||
const result2 = sm2.doVerifySignature(data, signatureHex, publicKeyHex, { hash: true });
|
||||
console.log(' 验证结果:', result2);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 3: 带 SM3 哈希 + userId
|
||||
console.log('\n3. 带 SM3 哈希 + userId:');
|
||||
try {
|
||||
const result3 = sm2.doVerifySignature(data, signatureHex, publicKeyHex, { hash: true, userId });
|
||||
console.log(' 验证结果:', result3);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 4: 使用哈希值
|
||||
console.log('\n4. 使用哈希值:');
|
||||
try {
|
||||
const result4 = sm2.doVerifySignature(hashHex, signatureHex, publicKeyHex, { hash: true });
|
||||
console.log(' 验证结果:', result4);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 5: 使用哈希值 + userId
|
||||
console.log('\n5. 使用哈希值 + userId:');
|
||||
try {
|
||||
const result5 = sm2.doVerifySignature(hashHex, signatureHex, publicKeyHex, { hash: true, userId });
|
||||
console.log(' 验证结果:', result5);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
|
||||
// 尝试 6: 转换为 DER 格式
|
||||
console.log('\n6. 转换为 DER 格式:');
|
||||
try {
|
||||
// 构造 DER 格式: 30 44 02 20 [r] 02 20 [s]
|
||||
const r = signatureHex.substring(0, 64);
|
||||
const s = signatureHex.substring(64);
|
||||
const derSignature = '30440220' + r + '0220' + s;
|
||||
console.log(' DER 签名:', derSignature);
|
||||
|
||||
const result6 = sm2.doVerifySignature(data, derSignature, publicKeyHex, { der: true, hash: true, userId });
|
||||
console.log(' 验证结果:', result6);
|
||||
} catch (e) {
|
||||
console.error(' 错误:', e.message);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
const forge = require('node-forge');
|
||||
|
||||
const mockP7Sign = `-----BEGIN PKCS7-----
|
||||
MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExDzANBglghkgBZQMEAgEFADA8Bgkq
|
||||
hkiG9w0BBwGgLwQtVGhpcyBpcyB0aGUgdGVzdCBjb250ZW50IGZvciBQS0NTNyBz
|
||||
aWduYXR1cmUuoIIB5jCCAeIwggFLoAMCAQICAQEwDQYJKoZIhvcNAQELBQAwNzEZ
|
||||
MBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTEaMBgGA1UEChMRVGVzdCBPcmdhbml6
|
||||
YXRpb24wHhcNMjYwNDA0MDAxMDIyWhcNMjcwNDA0MDAxMDIyWjA3MRkwFwYDVQQD
|
||||
ExB0ZXN0LmV4YW1wbGUuY29tMRowGAYDVQQKExFUZXN0IE9yZ2FuaXphdGlvbjCB
|
||||
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1e+05xb8T3Lo2v9MZQen5HYffpnc
|
||||
yY9mnT/ygvfxZNM9TeYkq4fACiuS99FONnlHFQdlXEPJluIk1NBFUoLpehAbzOSY
|
||||
Fu0WEjBOVJIg9FIWm7TUojU8yvPsfPGFYTEGEOGAse8AfHw4pl+w5SvxQUF8f2jB
|
||||
XsRY0MrDyb07xC8CAwEAATANBgkqhkiG9w0BAQsFAAOBgQAOEttx/p3xosIm/8sM
|
||||
kIaxR2c/fbYoMbBsX+geaiRu+xNOItbtQpGOhW6Ql981c3EwIjyd34KavplofZIr
|
||||
Slj4jHQFySZaJkegHY+LCAQz9GEg2TMke3MsPJ7nSZS7MUqB2AQt1tLuiXUuRh3V
|
||||
jF4yiqi6lGVmvPJf+y1GXk47KjGB5TCB4gIBATA8MDcxGTAXBgNVBAMTEHRlc3Qu
|
||||
ZXhhbXBsZS5jb20xGjAYBgNVBAoTEVRlc3QgT3JnYW5pemF0aW9uAgEBMA0GCWCG
|
||||
SAFlAwQCAQUAMA0GCSqGSIb3DQEBAQUABIGAMxSC81vzjSiZcJTcSicgCG9879mu
|
||||
p/bikqdHZPyF8UgABjikXXoVJ9IClFRd5/3wRf8ez+hwnxKR8j1vAsDI7U6dXJtr
|
||||
wp0aO7Ua6ecKhI5V0F8nUg5CjEK9FR8vNg0Il8U5AXDuan0iYKvguhWkiuJlvQlV
|
||||
X9ncPP4VRERPw8U=
|
||||
-----END PKCS7-----`;
|
||||
|
||||
const originalData = 'This is the test content for PKCS7 signature.';
|
||||
|
||||
try {
|
||||
const p7 = forge.pkcs7.messageFromPem(mockP7Sign);
|
||||
|
||||
console.log('=== PKCS7 信息 ===');
|
||||
console.log('type:', p7.type);
|
||||
console.log('content:', p7.content ? p7.content.getBytes() : 'null');
|
||||
console.log('certificates count:', p7.certificates ? p7.certificates.length : 0);
|
||||
|
||||
if (p7.certificates && p7.certificates.length > 0) {
|
||||
const cert = p7.certificates[0];
|
||||
console.log('cert subject:', cert.subject.attributes.map(a => `${a.name}=${a.value}`).join(', '));
|
||||
}
|
||||
|
||||
console.log('\n=== 尝试验证 ===');
|
||||
try {
|
||||
// 尝试验证
|
||||
const result = p7.verify();
|
||||
console.log('verify() result:', result);
|
||||
} catch (e) {
|
||||
console.log('verify() error:', e.message);
|
||||
}
|
||||
|
||||
// 手动验证
|
||||
console.log('\n=== 手动验证 ===');
|
||||
const md = forge.md.sha256.create();
|
||||
md.update(originalData, 'utf8');
|
||||
const digest = md.digest().getBytes();
|
||||
console.log('calculated digest (hex):', forge.util.bytesToHex(digest));
|
||||
|
||||
// 获取签名
|
||||
if (p7.rawCapture && p7.rawCapture.signature) {
|
||||
console.log('signature length:', p7.rawCapture.signature.length);
|
||||
console.log('signature (hex):', forge.util.bytesToHex(p7.rawCapture.signature).substring(0, 100) + '...');
|
||||
}
|
||||
|
||||
// 获取公钥
|
||||
if (p7.certificates && p7.certificates.length > 0) {
|
||||
const publicKey = p7.certificates[0].publicKey;
|
||||
if (publicKey) {
|
||||
console.log('publicKey exists:', true);
|
||||
// 尝试用公钥验证
|
||||
try {
|
||||
const verified = publicKey.verify(digest, p7.rawCapture.signature);
|
||||
console.log('publicKey.verify() result:', verified);
|
||||
} catch (e) {
|
||||
console.log('publicKey.verify() error:', e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
const sm2 = require('sm-crypto').sm2;
|
||||
const sm3 = require('sm-crypto').sm3;
|
||||
const forge = require('node-forge');
|
||||
|
||||
console.log('=== 生成 SM2 测试数据 ===');
|
||||
|
||||
// 生成 SM2 密钥对
|
||||
const keypair = sm2.generateKeyPairHex();
|
||||
console.log('私钥:', keypair.privateKey);
|
||||
console.log('公钥:', keypair.publicKey);
|
||||
|
||||
// 测试数据
|
||||
const originalData = 'This is test data for SM2 signature.';
|
||||
console.log('\n原始数据:', originalData);
|
||||
|
||||
// 计算 SM3 哈希
|
||||
const hash = sm3(originalData);
|
||||
console.log('SM3 哈希:', hash);
|
||||
|
||||
// SM2 签名
|
||||
const sig = sm2.doSignature(hash, keypair.privateKey);
|
||||
console.log('SM2 签名:', sig);
|
||||
|
||||
// 验证签名
|
||||
const verifyResult = sm2.doVerify(hash, sig, keypair.publicKey);
|
||||
console.log('签名验证结果:', verifyResult);
|
||||
|
||||
console.log('\n=== 注意 ===');
|
||||
console.log('由于 node-forge 不支持 SM2 算法,无法生成标准的 SM2 PKCS7 签名。');
|
||||
console.log('SM2 PKCS7 签名需要特殊的 OID 和格式,目前仅支持 RSA PKCS7。');
|
||||
console.log('建议:测试2可以使用 RSA 的 PKCS7 数据,或者跳过 SM2 测试。');
|
||||
@@ -0,0 +1,57 @@
|
||||
const forge = require('node-forge');
|
||||
|
||||
console.log('=== 生成测试用的 PKCS7 签名 ===');
|
||||
|
||||
try {
|
||||
// 1. 生成 RSA 密钥对
|
||||
console.log('生成 RSA 密钥对...');
|
||||
const keys = forge.pki.rsa.generateKeyPair(1024);
|
||||
const privateKey = keys.privateKey;
|
||||
const publicKey = keys.publicKey;
|
||||
|
||||
// 2. 创建自签名证书
|
||||
console.log('创建自签名证书...');
|
||||
const cert = forge.pki.createCertificate();
|
||||
cert.publicKey = publicKey;
|
||||
cert.serialNumber = '01';
|
||||
cert.validity.notBefore = new Date();
|
||||
cert.validity.notAfter = new Date();
|
||||
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
|
||||
|
||||
const attrs = [
|
||||
{ name: 'commonName', value: 'test.example.com' },
|
||||
{ name: 'organizationName', value: 'Test Organization' }
|
||||
];
|
||||
cert.setSubject(attrs);
|
||||
cert.setIssuer(attrs);
|
||||
cert.sign(privateKey, forge.md.sha256.create());
|
||||
|
||||
// 3. 创建 PKCS7 签名
|
||||
console.log('创建 PKCS7 签名...');
|
||||
const p7 = forge.pkcs7.createSignedData();
|
||||
p7.content = forge.util.createBuffer('This is the test content for PKCS7 signature.');
|
||||
p7.addCertificate(cert);
|
||||
p7.addSigner({
|
||||
key: privateKey,
|
||||
certificate: cert,
|
||||
digestAlgorithm: forge.pki.oids.sha256
|
||||
});
|
||||
p7.sign();
|
||||
|
||||
// 4. 转换为 PEM 格式
|
||||
const pem = forge.pkcs7.messageToPem(p7);
|
||||
|
||||
console.log('\n=== 生成的 PKCS7 签名 PEM 格式 ===');
|
||||
console.log(pem);
|
||||
|
||||
console.log('\n=== 提取 base64 部分 ===');
|
||||
const base64 = pem.replace(/-----BEGIN PKCS7-----\n?/, '')
|
||||
.replace(/-----END PKCS7-----\n?/, '')
|
||||
.replace(/\n/g, '');
|
||||
console.log(base64);
|
||||
|
||||
console.log('\n=== 完成 ===');
|
||||
} catch (error) {
|
||||
console.error('生成失败:', error);
|
||||
console.error(error.stack);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
const rs = require('jsrsasign');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据(没有头尾)
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
// 转换为 hex
|
||||
const sm2P7Hex = rs.hextorstr(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
console.log('=== 使用 jsrsasign 测试 SM2 PKCS7 ===');
|
||||
console.log('数据长度:', sm2P7Base64.length);
|
||||
|
||||
try {
|
||||
// 使用 CMSParser 解析
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const result = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
console.log('\n解析成功!');
|
||||
console.log('版本:', result.version);
|
||||
console.log('哈希算法:', result.hashalgs);
|
||||
console.log('内容类型:', result.econtent?.type);
|
||||
console.log('证书数量:', result.certs?.length);
|
||||
console.log('签名者数量:', result.sinfos?.length);
|
||||
|
||||
if (result.sinfos && result.sinfos.length > 0) {
|
||||
const signer = result.sinfos[0];
|
||||
console.log('\n签名者信息:');
|
||||
console.log(' 版本:', signer.version);
|
||||
console.log(' 哈希算法:', signer.hashalg);
|
||||
console.log(' 签名算法:', signer.sigalg);
|
||||
console.log(' 签名值 (hex):', signer.sighex?.substring(0, 50) + '...');
|
||||
}
|
||||
|
||||
if (result.certs && result.certs.length > 0) {
|
||||
console.log('\n证书信息:');
|
||||
const cert = result.certs[0];
|
||||
console.log(' 证书 PEM:', cert.substring(0, 100) + '...');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n解析失败:', error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
const forge = require('node-forge');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据(没有头尾)
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
// 包装成 PEM 格式
|
||||
const pemData = `-----BEGIN PKCS7-----\n${sm2P7Base64}\n-----END PKCS7-----`;
|
||||
|
||||
console.log('=== 测试 SM2 PKCS7 数据 ===');
|
||||
console.log('数据长度:', sm2P7Base64.length);
|
||||
console.log('PEM 格式前200字符:', pemData.substring(0, 200));
|
||||
|
||||
try {
|
||||
const p7 = forge.pkcs7.messageFromPem(pemData);
|
||||
console.log('\n解析成功!');
|
||||
console.log('类型:', p7.type);
|
||||
console.log('证书数量:', p7.certificates ? p7.certificates.length : 0);
|
||||
|
||||
if (p7.certificates && p7.certificates.length > 0) {
|
||||
const cert = p7.certificates[0];
|
||||
console.log('证书主题:', cert.subject ? cert.subject.attributes.map(a => `${a.name}=${a.value}`).join(', ') : 'N/A');
|
||||
console.log('证书颁发者:', cert.issuer ? cert.issuer.attributes.map(a => `${a.name}=${a.value}`).join(', ') : 'N/A');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('\n解析失败:', error.message);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
const crypto = require('../src/crypto.js');
|
||||
|
||||
// 用户提供的 SM2 PKCS7 签名数据
|
||||
const sm2P7Base64 = 'MIIDKgYKKoEcz1UGAQQCAqCCAxowggMWAgEBMQ4wDAYIKoEcz1UBgxEFADAMBgoqgRzPVQYBBAIBoIICNzCCAjMwggHWoAMCAQICBgD1tfRoKTAMBggqgRzPVQGDdQUAMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBMB4XDTI2MDQwMjA4MDEzOVoXDTM2MDMzMDA4MDEzOVowTTELMAkGA1UEBhMCQ04xDzANBgNVBAoMBlBCQ0NSQzEtMCsGA1UEAwwkOTRmMWY5MzgtZjBiZC00NzYyLTkyOGUtZjY4YTdjY2UxNDFkMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEu3dU5Vn20VjVL9xGCCRPB/EpATY6HW24+zIZv46Cfv0R2PGM+ZJs/dYarw7qJCnpIbe5T0PKmyyJITNVrVnnMaOBrDCBqTAfBgNVHSMEGDAWgBRUqfVQHMpD+o+YdrPK1JlRJL757zAJBgNVHRMEAjAAME8GA1UdHwRIMEYwRKBCoECkPjA8MQ4wDAYDVQQDDAVjcmw3MTEMMAoGA1UECwwDY3JsMQ8wDQYDVQQKDAZQQkNDUkMxCzAJBgNVBAYTAkNOMAsGA1UdDwQEAwIHgDAdBgNVHQ4EFgQU5bG6U0lYzWtkPJE74M/3HdafKKcwDAYIKoEcz1UBg3UFAANJADBGAiEAuLTE36/Eobcui23bFiPvOU4MOT0O0r9SyyHZ1JuvLwMCIQCejuSk03jyUAkbh1SaPx5n7WlDjI6tx9v9RJ7iw5rlojGBtzCBtAIBATBKMEAxCzAJBgNVBAYTAkNOMQ8wDQYDVQQKDAZQQkNDUkMxIDAeBgNVBAMMF1BCQ0NSQyBTTTIgT3BlcmF0aW9uIENBAgYA9bX0aCkwDAYIKoEcz1UBgxEFADANBgkqgRzPVQGCLQEFAARGMEQCIALTgWMD7io1JHfzInBwzDQpe9bonchuLFSED//JLDtnAiBmEUtr+ssAQIzFG4wY0CAj9QZxhENyCU2UYL1fhaysUA==';
|
||||
|
||||
const rs = require('jsrsasign');
|
||||
|
||||
console.log('=== 使用真实原始数据验证 SM2 PKCS7 ===');
|
||||
|
||||
// 从 PKCS7 中提取原始数据
|
||||
const parser = new rs.KJUR.asn1.cms.CMSParser();
|
||||
const p7 = parser.getCMSSignedData(rs.b64tohex(sm2P7Base64));
|
||||
|
||||
let realOriginalData = null;
|
||||
if (p7.econtent && p7.econtent.hex) {
|
||||
realOriginalData = Buffer.from(p7.econtent.hex, 'hex').toString();
|
||||
console.log('从 PKCS7 提取的原始数据:', realOriginalData);
|
||||
}
|
||||
|
||||
// 使用正确的原始数据进行验证
|
||||
if (realOriginalData) {
|
||||
console.log('\n使用提取的原始数据进行验证:');
|
||||
const result = crypto.verifyPKCS7(sm2P7Base64, realOriginalData);
|
||||
console.log('验证结果:', result);
|
||||
} else {
|
||||
console.log('无法从 PKCS7 中提取原始数据');
|
||||
}
|
||||
|
||||
// 也测试一下不提供原始数据的情况(attach 模式)
|
||||
console.log('\n使用 attach 模式(不提供原始数据):');
|
||||
const result2 = crypto.verifyPKCS7(sm2P7Base64);
|
||||
console.log('验证结果:', result2);
|
||||
Reference in New Issue
Block a user