kit.program/kit/test/debug_sm2_pubkey2.js
2026-04-04 17:29:00 +08:00

96 lines
4.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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