From 5a033318c0d2fef9c1b998a1a0611c375b24f437 Mon Sep 17 00:00:00 2001 From: cheney Date: Sat, 4 Apr 2026 08:24:27 +0800 Subject: [PATCH] =?UTF-8?q?rsa=20p7=20info=20=20=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kit/package-lock.json | 10 ++ kit/package.json | 1 + kit/src/crypto.js | 200 +++++++++++++++++++++++++++++++++++ kit/test/crypto_test.js | 129 ++++++++++++++++++++++ kit/test/debug_p7.js | 60 +++++++++++ kit/test/generate_test_p7.js | 57 ++++++++++ 6 files changed, 457 insertions(+) create mode 100644 kit/test/crypto_test.js create mode 100644 kit/test/debug_p7.js create mode 100644 kit/test/generate_test_p7.js diff --git a/kit/package-lock.json b/kit/package-lock.json index f395e0e..c0f2535 100644 --- a/kit/package-lock.json +++ b/kit/package-lock.json @@ -14,6 +14,7 @@ "get-port": "^7.0.0", "json5": "^2.2.3", "log4js": "^6.9.1", + "node-forge": "^1.3.1", "physical-cpu-count": "^2.0.0", "sm-crypto": "^0.3.13", "systeminformation": "^5.30.6", @@ -448,6 +449,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", diff --git a/kit/package.json b/kit/package.json index f38f65d..d86c5ce 100644 --- a/kit/package.json +++ b/kit/package.json @@ -18,6 +18,7 @@ "get-port": "^7.0.0", "json5": "^2.2.3", "log4js": "^6.9.1", + "node-forge": "^1.3.1", "physical-cpu-count": "^2.0.0", "sm-crypto": "^0.3.13", "systeminformation": "^5.30.6", diff --git a/kit/src/crypto.js b/kit/src/crypto.js index 296c9a0..e778a1d 100644 --- a/kit/src/crypto.js +++ b/kit/src/crypto.js @@ -1,5 +1,8 @@ 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') module.exports.sm4en3 = function (key, data){ @@ -15,4 +18,201 @@ module.exports.sm4de3 = function (key, data){ sm3key = sm3key.substring(0, 32) let decryptData = sm4.decrypt(data, sm3key) return decryptData +} + + +/** + * 从 PKCS7 签名中获取信息(包含证书、公钥和签名值) + * @param {Buffer|string} p7sign - PKCS7 签名数据 + * @returns {Object} 包含证书、公钥和签名值的对象 + */ +module.exports.getInfoFromPKCS7 = function (p7sign) { + // 处理输入数据 + let pemData + if (Buffer.isBuffer(p7sign)) { + pemData = p7sign.toString('ascii') + } else if (typeof p7sign === 'string') { + // 判断是否是 PEM 格式 + if (p7sign.includes('-----BEGIN PKCS7-----')) { + pemData = p7sign + } else { + // 如果不是 PEM 格式,假设是 base64,包装成 PEM + pemData = `-----BEGIN PKCS7-----\n${p7sign}\n-----END PKCS7-----` + } + } else { + throw new Error('Invalid input type for p7sign') + } + + // 解析 PKCS7 数据 + const p7 = forge.pkcs7.messageFromPem(pemData) + + // 提取证书 + 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 + })), + issuer: certObj.issuer.attributes.map(attr => ({ + name: attr.name, + value: attr.value + })), + serialNumber: certObj.serialNumber, + notBefore: certObj.validity.notBefore, + notAfter: certObj.validity.notAfter, + pem: forge.pki.certificateToPem(certObj) + } + } + + // 提取公钥 - 从证书中提取公钥对象并转换为 PEM + let publicKey = null + if (p7.certificates && p7.certificates.length > 0) { + const certObj = p7.certificates[0] + // 提取公钥对象并转换为 PEM 格式 + if (certObj.publicKey) { + publicKey = forge.pki.publicKeyToPem(certObj.publicKey) + } + } + + // 提取签名值 - 从 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, + 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 pemData + if (Buffer.isBuffer(p7sign)) { + pemData = p7sign.toString('ascii') + } else if (typeof p7sign === 'string') { + // 判断是否是 PEM 格式 + if (p7sign.includes('-----BEGIN PKCS7-----')) { + pemData = p7sign + } else { + // 如果不是 PEM 格式,假设是 base64,包装成 PEM + pemData = `-----BEGIN PKCS7-----\n${p7sign}\n-----END PKCS7-----` + } + } else { + throw new Error('Invalid input type for p7sign') + } + + // 解析 PKCS7 数据 + const p7 = forge.pkcs7.messageFromPem(pemData) + + // 准备验证所需的数据 + 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') + } + } else { + // 当没有提供原始数据时,从 PKCS7 中提取数据进行验证(attach 模式) + if (p7.content) { + verifyData = Buffer.from(p7.content.getBytes(), 'binary') + } else { + throw new Error('No content found in PKCS7 signature for attach mode') + } + } + + // 验证签名 + try { + // 尝试使用 node-forge 验证(适用于 RSA) + return p7.verify() + } catch (error) { + // 如果验证失败,尝试使用 SM2 验证 + try { + // 提取签名值和公钥 + const signInfo = module.exports.getInfoFromPKCS7(p7sign) + if (!signInfo.publicKey || !signInfo.signature) { + throw new Error('Cannot extract public key or signature from PKCS7') + } + + // 使用 SM2 验证签名 + const hash = sm3(verifyData.toString()) + return sm2.doVerify(hash, signInfo.signature, signInfo.publicKey) + } catch (sm2Error) { + console.error('SM2 verification error:', sm2Error) + return false + } + } +} + + +/** + * PKCS7 签名(自动判断 RSA 或 SM2 算法) + * @param {Buffer|string} data - 待签名数据 + * @param {string} privateKey - 私钥 + * @returns {Buffer} PKCS7 签名数据 + */ +module.exports.pkcs7Sign = function (data, privateKey) { + // 处理输入数据 + let inputData + if (Buffer.isBuffer(data)) { + inputData = data + } else if (typeof data === 'string') { + inputData = Buffer.from(data) + } else { + throw new Error('Invalid input type for data') + } + + // 判断私钥类型 + if (privateKey.includes('RSA PRIVATE KEY')) { + // RSA 算法签名 + const pkey = forge.pki.privateKeyFromPem(privateKey) + const p7 = forge.pkcs7.createSignedData() + p7.content = forge.util.createBuffer(inputData.toString('binary')) + p7.addCertificate(forge.pki.certificateFromPem(privateKey)) // 假设私钥包含证书 + p7.addSigner({ + key: pkey, + certificate: forge.pki.certificateFromPem(privateKey), + digestAlgorithm: forge.pki.oids.sha256 + }) + p7.sign() + const pem = forge.pkcs7.messageToPem(p7) + return Buffer.from(pem, 'ascii') + } else if (privateKey.includes('SM2') || privateKey.length === 64) { + // SM2 算法签名 + // 由于 node-forge 不直接支持 SM2 算法 + // 这里需要使用 sm-crypto 库进行 SM2 签名,然后封装到 PKCS7 格式中 + // 注意:这只是一个简化的实现,实际应用中可能需要更复杂的处理 + const hash = sm3(inputData.toString()) + const signature = sm2.doSignature(hash, privateKey) + + // 创建一个简单的 PKCS7 结构来存储 SM2 签名 + // 注意:这不是标准的 PKCS7 SM2 签名实现 + const p7 = forge.pkcs7.createSignedData() + p7.content = forge.util.createBuffer(inputData.toString('binary')) + // 这里需要添加 SM2 证书和签名逻辑 + // 由于复杂性,这里暂时抛出错误 + throw new Error('SM2 PKCS7 signature not fully implemented yet') + } else { + throw new Error('Unsupported private key type') + } } \ No newline at end of file diff --git a/kit/test/crypto_test.js b/kit/test/crypto_test.js new file mode 100644 index 0000000..08f588f --- /dev/null +++ b/kit/test/crypto_test.js @@ -0,0 +1,129 @@ +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); + + // 将 subject 和 issuer 转换为 DN 格式 + function toDN(attrs) { + if (!attrs) return ''; + return attrs.map(attr => `${attr.name}=${attr.value}`).join(', '); + } + + console.log('测试结果:'); + console.log(' cert:'); + console.log(' subject:', toDN(result.cert?.subject)); + console.log(' issuer:', toDN(result.cert?.issuer)); + 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(' 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)'); + // 这里应该使用实际的 PKCS7 签名数据进行测试 + // 由于没有实际数据,这里使用模拟数据 + const mockP7Sign = 'MIIBpAYJKoZIhvcNAQcCoIIBmzCCAZ8CAQExADALBgkqhkiG9w0BBwGgggLuMIIC3wIBADCCAbkGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM9Q7c7X7X7X7X7X7X7X7X7AgEQgIID+DCCA+SgAwIBAgIUY1234567890abcdefghijklmnopqrstuvwxyzMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFI1234567890abcdefghijklmnopqrstuvwxyzMB8GA1UdIwQYMBaAFJ1234567890abcdefghijklmnopqrstuvwxyzMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAj1234567890abcdefghijklmnopqrstuvwxyz'; + const result = crypto.getInfoFromPKCS7(mockP7Sign); + console.log('测试结果:', result); + console.log('✓ getInfoFromPKCS7 接口(SM2)测试通过'); +} catch (error) { + console.error('✗ getInfoFromPKCS7 接口(SM2)测试失败:', error.message); +} + +// 测试 3: verifyPKCS7 接口(RSA) +try { + console.log('\n3. 测试 verifyPKCS7 接口(RSA)'); + // 这里应该使用实际的 PKCS7 签名数据和原始数据进行测试 + // 由于没有实际数据,这里使用模拟数据 + const mockP7Sign = 'MIICdwYJKoZIhvcNAQcCoIICZzCCAm8CAQExADALBgkqhkiG9w0BBwGgggLsMIIC3wIBADCCAbkGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQM9Q7c7X7X7X7X7X7X7X7X7AgEQgIID+DCCA+SgAwIBAgIUY1234567890abcdefghijklmnopqrstuvwxyzMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFI1234567890abcdefghijklmnopqrstuvwxyzMB8GA1UdIwQYMBaAFJ1234567890abcdefghijklmnopqrstuvwxyzMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAj1234567890abcdefghijklmnopqrstuvwxyz'; + const mockOriginalData = 'test data'; + const result = crypto.verifyPKCS7(mockP7Sign, mockOriginalData); + console.log('测试结果:', result); + console.log('✓ verifyPKCS7 接口(RSA)测试通过'); +} catch (error) { + console.error('✗ verifyPKCS7 接口(RSA)测试失败:', error.message); +} + +// 测试 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); +} + +// 测试 5: pkcs7Sign 接口(RSA) +try { + console.log('\n5. 测试 pkcs7Sign 接口(RSA)'); + // 这里应该使用实际的私钥进行测试 + // 由于没有实际数据,这里使用模拟数据 + const mockData = 'test data'; + const mockPrivateKey = '-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz-----END RSA PRIVATE KEY-----'; + const result = crypto.pkcs7Sign(mockData, mockPrivateKey); + console.log('测试结果:', result.toString('base64')); + console.log('✓ pkcs7Sign 接口(RSA)测试通过'); +} catch (error) { + console.error('✗ pkcs7Sign 接口(RSA)测试失败:', error.message); +} + +// 测试 6: pkcs7Sign 接口(SM2) +try { + console.log('\n6. 测试 pkcs7Sign 接口(SM2)'); + // 这里应该使用实际的私钥进行测试 + // 由于没有实际数据,这里使用模拟数据 + const mockData = 'test data'; + const mockPrivateKey = '1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdef'; + const result = crypto.pkcs7Sign(mockData, mockPrivateKey); + console.log('测试结果:', result.toString('base64')); + console.log('✓ pkcs7Sign 接口(SM2)测试通过'); +} catch (error) { + console.error('✗ pkcs7Sign 接口(SM2)测试失败:', error.message); +} + +console.log('\n=== 测试完成 ==='); diff --git a/kit/test/debug_p7.js b/kit/test/debug_p7.js new file mode 100644 index 0000000..e638420 --- /dev/null +++ b/kit/test/debug_p7.js @@ -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)); + } +} diff --git a/kit/test/generate_test_p7.js b/kit/test/generate_test_p7.js new file mode 100644 index 0000000..8e6c201 --- /dev/null +++ b/kit/test/generate_test_p7.js @@ -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); +}