用于签名创建的小钥匙

问题描述 投票:0回答:1

我正在尝试使用对 PDF 哈希进行签名的第三方 API 来对 PDF 文档进行签名。但是,当我使用签名验证工具测试签名的PDF时,遇到以下错误。

密钥大小为 256 的 RSA 算法对于签名创建来说太小了!

这里是该工具创建的详细错误报告。

在 Acrobat reader 中打开 PDF 时,我还可以在签名中看到未定义的错误。

这是我的流程概要:

  1. 我使用 SHA-256 生成 PDF 文档的哈希值。
  2. 我将此哈希值发送到 API,API 使用 RSA 私钥对其进行签名。
  3. 我将签名附加到 PDF 并使用签名验证工具对其进行测试。 签名生成工作不会引发任何错误,但验证工具会标记上述问题。

这是内容签名者的代码,负责对内容进行签名:

 private ContentSigner createContentSigner() {
    return new ContentSigner() {
      // This stream will be filled by the saveIncrementalForExternalSigning method. It holds the bytes of the PDF file.
      private final ByteArrayOutputStream stream = new ByteArrayOutputStream();

      @Override
      public byte[] getSignature() {
        try {
          MessageDigest digest = MessageDigest.getInstance("SHA-256");

          // Hash the bytes of the PDF file.
          byte[] hashBytes = digest.digest(stream.toByteArray());
          // The hash is encoded in Base64 as this is the format expected by the server.
          String hash = Base64.getEncoder().encodeToString(hashBytes);

          // Send the hash to the server and retrieve the signed hash.
          // The response is Base64 encoded, so it needs to be decoded for the CMS signature.
          return java.util.Base64.getDecoder().decode(webAPIService.getSignedHash(hash));
        } catch (Exception e) {
          throw new RuntimeException("Exception while signing", e);
        }
      }

      @Override
      public OutputStream getOutputStream() {
        return stream;
      }

      @Override
      public AlgorithmIdentifier getAlgorithmIdentifier() {
        // The algorithm identifier for SHA-256.
        return new AlgorithmIdentifier(new ASN1ObjectIdentifier("1.2.840.113549.1.1.11"));
      }
    };
  }

有没有一种方法可以在不向 API 维护者请求更大密钥大小的情况下签署该 PDF?

java pdf pdfbox
1个回答
0
投票

感谢您提供 PDF 示例。问题的原因是你的假设之一是错误的:

我将此哈希值发送到 API,API 使用 RSA 私钥对其进行签名。

不,API 使用 ECDSA 私钥对其进行签名!

因此,您在

ContentSigner
方法
getAlgorithmIdentifier
中返回了错误的签名算法OID,因此您创建和嵌入的签名容器不一致,即标记为RSA签名的ECDSA签名。

eSig DSS 确定出现问题并报告“签名不完整!”

“密钥大小为 256 的 RSA 算法对于签名创建来说太小了!”消息是不同检查的输出,在当前情况下只是转移注意力。

如果您确实想要 RSA 签名,则必须与您的签名提供商联系并要求基于 RSA 密钥对的不同私钥和证书。

如果 ECDSA 也适合您,您只需从

getAlgorithmIdentifier
返回适当的 OID。


您可以验证该证书确实适用于 ECDSA 密钥对,只需在证书查看器(例如在 Adobe Acrobat 中)中检查它即可:

certificate details screen shot

或者,您可以检查签名的 eSig DSS 诊断数据:

        <Certificate Id=...>
            ...
            <PublicKeySize>256</PublicKeySize>
            <PublicKeyEncryptionAlgo>ECDSA</PublicKeyEncryptionAlgo>

PS:如果您想知道为什么 Adobe Acrobat 不报告错误但验证您的签名:Acrobat 的加密验证例程忽略

SignerInfo
中的签名算法 OID,它们根据 中的公钥确定要使用的算法证书和签名的其他详细信息。所以他们在这里将签名验证为 ECDSA 签名!

但遗憾的是,Acrobat 仍将

SignerInfo
中与签名算法 OID 关联的算法报告为签名算法:

Advanced signature properties screen shot

因此,对 Acrobat 报告的加密结果要非常谨慎,它们仅部分可信。

© www.soinside.com 2019 - 2024. All rights reserved.