Node.js不调用外部OpenSSL能否实现原生数据签名
能否在Node.js中实现原生CMS签名替代OpenSSL命令
可以实现,不需要调用外部OpenSSL进程,以下是符合你给出命令要求的实现方案。
你给出的目标命令拆解后需要满足的核心能力:
- 生成CMS签名结构,签名不分离(原始内容嵌入结果)
- 二进制处理输入内容,输出DER格式结果
- 摘要算法使用SHA256
- 结果支持DES加密
实现方案
方案1:纯JS实现(无系统依赖,兼容低版本Node.js)
使用纯JS编写的加密工具库node-forge完成全部逻辑,不需要依赖本地安装的OpenSSL。
- 先安装依赖:
npm install node-forge - 示例代码:
const forge = require('node-forge'); const fs = require('fs'); // 替换为你的实际文件路径 const certPem = fs.readFileSync('./signer.crt', 'utf8'); const privateKeyPem = fs.readFileSync('./private.key', 'utf8'); const rawContent = fs.readFileSync('./input_content'); // 解析证书和私钥 const signerCert = forge.pki.certificateFromPem(certPem); const signerKey = forge.pki.privateKeyFromPem(privateKeyPem); // 初始化PKCS7(CMS)签名对象 const p7 = forge.pkcs7.createSignedData(); // 嵌入原始内容,*对应-nodetach、-binary参数* p7.content = forge.util.createBuffer(rawContent); // 配置签名者信息,指定SHA256摘要算法 p7.addSigner({ key: signerKey, certificate: signerCert, digestAlgorithm: forge.pki.oids.sha256, authenticatedAttributes: [ { type: forge.pki.oids.contentType, value: forge.pki.oids.data }, { type: forge.pki.oids.messageDigest }, { type: forge.pki.oids.signingTime } ] }); p7.addCertificate(signerCert); // 执行签名 p7.sign(); // 转换为DER格式输出,*对应-outform DER参数* const derSignature = forge.asn1.toDer(p7.toAsn1()).getBytes(); // DES加密签名结果,*对应-des参数* const desKey = forge.random.getBytesSync(8); const desIv = forge.random.getBytesSync(8); const desCipher = forge.cipher.createCipher('DES-CBC', desKey); desCipher.start({ iv: desIv }); desCipher.update(forge.util.createBuffer(derSignature)); desCipher.finish(); const encryptedResult = desCipher.output.getBytes(); // 写入结果文件 fs.writeFileSync('./output_signed.der', Buffer.from(encryptedResult, 'binary'));
方案2:Node.js原生模块实现(Node.js >= 16.0.0)
Node.js 16及以上版本内置的crypto模块已支持CMS签名能力,不需要安装第三方依赖:
const { createSign, createCipheriv, randomBytes } = require('crypto'); const fs = require('fs'); // 替换为你的实际文件路径 const signerCert = fs.readFileSync('./signer.crt'); const signerKey = fs.readFileSync('./private.key'); const rawContent = fs.readFileSync('./input_content'); // 生成CMS签名 const sign = createSign('SHA256'); sign.update(rawContent); sign.end(); const derSignature = sign.sign({ key: signerKey, cert: signerCert, type: 'cms', format: 'der', detached: false // *对应-nodetach参数* }); // DES加密签名结果,*对应-des参数* const desKey = randomBytes(8); const desIv = randomBytes(8); const desCipher = createCipheriv('des-cbc', desKey, desIv); const encryptedResult = Buffer.concat([desCipher.update(derSignature), desCipher.final()]); // 写入结果文件 fs.writeFileSync('./output_signed.der', encryptedResult);
结果验证
生成的签名文件可以直接用OpenSSL命令验证有效性:
openssl cms -verify -in ./output_signed.der -inform DER -CAfile ./root_ca.crt
内容的提问来源于stack exchange,提问作者New Leepanyaporn
相关产品推荐
相关产品推荐

