Node.js下用Diia的PFX证书签PDF失败:不支持MAC算法1.2.804.2.1.1.1.1.2.1
解决Diia PFX证书签名PDF的MAC算法不支持问题及.dat文件使用指南
一、解决MAC算法不支持报错
报错Error: PKCS#12 uses unsupported MAC algorithm: 1.2.804.2.1.1.1.1.2.1是因为你的PFX证书使用了乌克兰GOST标准的MAC算法,当前signpdf依赖的加密库不支持该算法,可通过以下两种方案解决:
方案1:用OpenSSL转换证书格式
通过OpenSSL重新导出PFX证书,指定通用支持的MAC算法(如SHA256):
- 将原PFX转换为PEM格式:
openssl pkcs12 -in original.pfx -out temp.pem -nodes
- 重新打包为PFX并指定SHA256作为MAC算法:
openssl pkcs12 -export -in temp.pem -out new.pfx -macalg sha256
之后用转换后的new.pfx替换代码中获取到的signer.asset.certFile即可。
方案2:替换加密库支持GOST算法
如果无法转换证书,可以使用支持GOST算法的Node.js库(如node-gost)自定义签名逻辑,替换signpdf默认的P12Signer。这种方式需要修改签名实现,复杂度较高,适合有加密开发经验的场景。
二、.dat文件的使用
Diia提供的.dat文件是根/中间证书链文件,用于验证签名合法性,需将其加入PDF签名的证书链中:
- 读取.dat文件并解析证书:
const fs = require('fs'); const { Certificate } = require('@fidm/x509'); // 读取dat文件(替换为你的文件路径,或从配置/存储中获取) const datCertBuffer = fs.readFileSync('./diia_ca.dat'); // 解析为证书原始数据 const caCert = Certificate.fromPEM(datCertBuffer).raw;
- 在签名时传入证书链:
修改签名代码,添加certificateChain参数:
const signed = await signpdf.sign(pdfToSign, signer, { certificateChain: [caCert], });
三、整合后的代码示例
const assetAccessCode = await this.configFacade.get(SIGN_CERTIFICATE_ASSET_ACCESS_CODE); const assetId = await this.configFacade.get(SIGN_CERTIFICATE_ASSET_ID); const fs = require('fs'); const { Certificate } = require('@fidm/x509'); let signerAsset = await send(this.secureStorage, 'assetGet', { assetAccessCode, assetId, clientId }).catch((error) => { this.logger.error(`Secure Storage request:${JSON.stringify({ assetAccessCode, assetId, clientId })}`); this.logger.error(`Secure Storage unavailable:${JSON.stringify(error)}`); throw Error(error); }); // 使用转换后的PFX证书内容 const convertedPfxBuffer = Buffer.from(signerAsset.asset.certFile); const pdfToSign = plainAddPlaceholder({ pdfBuffer, reason: ' ', contactInfo: ' ', name: ' ', location: 'UK', }); const signer = new P12Signer(convertedPfxBuffer, { passphrase: signerAsset.asset.password, asn1StrictParsing: true, }); // 加载并解析.dat证书链 const datCertBuffer = fs.readFileSync('./diia_ca.dat'); const caCert = Certificate.fromPEM(datCertBuffer).raw; const signed = await signpdf.sign(pdfToSign, signer, { certificateChain: [caCert], }); return signed;
内容的提问来源于stack exchange,提问作者Анна Верба
相关产品推荐
相关产品推荐

