You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何验证带PKCS#7分离签名(p7s)的JSON文件?代码报错求助

解决PKCS#7(p7s)签名验证的长度不匹配问题

你遇到的Signature length not correct错误,核心原因是p7s是完整的PKCS#7/CMS签名容器——它不止包含原始签名字节,还封装了签名算法、证书链、签名属性等元数据,直接把整个p7s文件字节传给Signature.verify()会导致长度不匹配(RSA-2048签名固定256字节,而p7s容器要大得多)。

解决方案

不需要手动提取签名字节,直接用CMS签名验证API结合BouncyCastle提供者解析p7s文件并完成验证,步骤如下:

  1. 添加BouncyCastle依赖(Maven示例):
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
  1. 修改验证代码:
    替换原有Signature相关逻辑,改用CMSSignedData处理p7s文件,同时用你持有的公证书验证签名有效性:
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.ByteArrayInputStream;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collection;

public void getFiles(@RequestParam("json") MultipartFile json,
                     @RequestParam("json-sig") MultipartFile jsonSig) throws Exception {
    // 注册BouncyCastle安全提供者
    Security.addProvider(new BouncyCastleProvider());

    // 加载持有的公证书
    String certificateStr = CERTIFIFATE;
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    byte[] certBytes = Base64.getDecoder().decode(certificateStr);
    X509Certificate publicCert = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certBytes));

    // 解析p7s签名文件为CMS签名数据
    CMSSignedData cmsSignedData = new CMSSignedData(jsonSig.getBytes());

    // 获取签名信息集合
    SignerInformationStore signerStore = cmsSignedData.getSignerInfos();
    Collection<SignerInformation> signers = signerStore.getSigners();
    if (signers.isEmpty()) {
        throw new IllegalArgumentException("p7s文件中未找到有效签名");
    }

    // 验证签名及原始文件一致性
    boolean isVerified = false;
    for (SignerInformation signer : signers) {
        // 用持有的公证书验证签名有效性
        if (signer.verify(publicCert, BouncyCastleProvider.PROVIDER_NAME)) {
            // 验证原始JSON与签名绑定的内容是否一致
            byte[] signedContent = (byte[]) cmsSignedData.getSignedContent().getContent();
            if (java.util.Arrays.equals(signedContent, json.getBytes())) {
                isVerified = true;
                break;
            }
        }
    }

    // isVerified即为最终验证结果,可根据业务逻辑处理
    System.out.println("签名验证结果:" + isVerified);
}

关键说明

  • 注册BouncyCastle是为了兼容更多CMS签名特性,避免解析失败;
  • 遍历签名集合是因为p7s可能包含多个签名,只需匹配你持有的公证书对应的签名即可;
  • 额外比对原始JSON与签名绑定内容,防止签名被篡改或关联错误文件;
  • 可根据业务需求调整异常处理逻辑,比如签名不存在、证书不匹配等场景的提示。

内容的提问来源于stack exchange,提问作者Adam Jedrzejko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:05:23