96 lines
4.9 KiB
JavaScript
96 lines
4.9 KiB
JavaScript
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);
|
||
}
|
||
}
|