114 lines
5.5 KiB
JavaScript
114 lines
5.5 KiB
JavaScript
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);
|
||
}
|
||
}
|
||
}
|