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); } } } }