使用 iTextSharp 时数字签名无效

Posted

技术标签:

【中文标题】使用 iTextSharp 时数字签名无效【英文标题】:Digital signatures invalid when I use the iTextSharp 【发布时间】:2020-10-17 07:37:44 【问题描述】:

这是我的表格 -

以下是代码-

private void btnSign_Click(object sender, EventArgs e)
   
    string sbase64 = richTextBox2.Text;
    byte[] bytes = System.Convert.FromBase64String(sbase64);
    PdfReader reader = new PdfReader("F:\\test1.pdf"); 
    FileStream os = new FileStream("F:\\output.pdf", FileMode.Create);
    IExternalSignatureContainer external1 = new MyExternalSignatureContainer(bytes);
    MakeSignature.SignDeferred(reader, "Signature1", os, external1);
    reader.Close();
    os.Close(); 



首先,我准备一个 PDF 文件 (test.pdf) 以在 PDF 文件上创建签名区域。然后输出文件 test1.pdf 和字符串 SHA-256。

接下来我使用上传到服务器的 SHA-1 字符串进行签名。服务器返回一个base64字符串。

我复制那个base64并将其粘贴到richtextbox2中以签名并导出“output.pdf”文件。

然后我在 Foxit Reader(版本 10.0)上检查该文件“output.pdf”,签名为 VALID。

但是当我在 Adob​​e Reader 或 Adob​​e Acrobat 上检查该文件时,签名无效。

即使在福昕阅读器(最新版本 10.1)上,签名也是无效的。怎么了???

我的英语不太好。对不起!

更新 - 错误!!!

这是我在 Foxit Reader 10.0 上查看时的“output.pdf”文件(有效)-

这是我检查 Adob​​e Acrobat 的时候(无效)-

更新...有什么错误吗?? PKCS#1 or PKCS#7

【问题讨论】:

请分享一个由您的代码签名的示例 PDF 以供分析。 drive.google.com/drive/folders/… 文件“test.pdf”是原始文件,文件“test1.pdf”是文件创建区域标志,文件“output.pdf”是文件签名 drive.google.com/file/d/1WwambxnHy2xHlRCjG-JVb_FAS0g1JRUZ/… 这是由我的代码签名的文件。谢谢!!! 好的,你写的内容实际上有一个问题:"然后输出文件 test1.pdf 和字符串 SHA-256。接下来我使用上传到的 SHA-1 字符串服务器签名...” - 你不应该混合哈希算法。乍一看,签名容器使用 SHA256,而签名值使用 SHA-1。考虑到 SHA-1 因签名而损坏,例如pdfs 你应该使用 SHA-2 算法。 我向您展示了我在此过程中导出的 2 个字符串。它在下面的答案中。谢谢!!! 【参考方案1】:

您的示例 PDF 中至少存在两个问题,它们较少是由您的 iText 相关代码引起的,而更多是由您的签名服务或您解决问题的方式引起的。

问题

使用的混合摘要算法

您使用 SHA-256 来计算签名 PDF 字节范围的摘要。因此,SignerInfo 中存储的哈希算法是 SHA-256。作为签名/加密算法,它仅指 RSA。但在签名字节中明确使用了 SHA-1。

这是一个错误,根据RFC 5652,哈希算法应同时用于对消息数据和签名属性进行哈希处理。

这是SignerInfo 对象的转储

. . . . SEQUENCE 
. . . . . INTEGER 1
. . . . . [...SID...]
. . . . . SEQUENCE 
. . . . . . OBJECT IDENTIFIER sha-256 (2 16 840 1 101 3 4 2 1)
. . . . . . . (NIST Algorithm)
. . . . . . NULL
. . . . . . 
. . . . . [0] 
. . . . . . SEQUENCE 
. . . . . . . OBJECT IDENTIFIER contentType (1 2 840 113549 1 9 3)
. . . . . . . . (PKCS #9)
. . . . . . . SET 
. . . . . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
. . . . . . . . . (PKCS #7)
. . . . . . . . 
. . . . . . . 
. . . . . . SEQUENCE 
. . . . . . . OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4)
. . . . . . . . (PKCS #9)
. . . . . . . SET 
. . . . . . . . OCTET STRING    
. . . . . . . . . 2F AA 90 5F A3 3B 2E 74    /.._.;.t
. . . . . . . . . 3F 78 7A C1 85 F8 EF B7    ?xz.....
. . . . . . . . . 20 AE 73 2B F4 2F B2 80     .s+./..
. . . . . . . . . 87 3C 24 50 F9 A8 3F 8B                            
. . . . . . . . 
. . . . . . . 
. . . . . . 
. . . . . SEQUENCE 
. . . . . . OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
. . . . . . . (PKCS #1)
. . . . . . NULL
. . . . . . 
. . . . . OCTET STRING    
. . . . . . [...Signature Bytes...]
. . . . . 
. . . . 

您可以轻松识别 SHA-256 和 RSA OID;这些是由 iText 类 PdfPKCS7 根据您的输入添加的。

这是您签名字节中解密的DigestInfo 对象的转储:

SEQUENCE (2 elem) 
. SEQUENCE (2 elem) 
. . OBJECT IDENTIFIER 1.3.14.3.2.26 sha1 (OIW)
. . NULL
. . 
. OCTET STRING (20 byte) AD002EA501871117250DE3BF42D51B4FD2B1C5A0
. 

您可以清楚地看到 SHA-1 OID;此外,20 字节的哈希值可能是 SHA-1 哈希,但不是 SHA-256 哈希。

显然,签名服务创建了一个 SHA1withRSA 签名来响应您的请求。

有符号哈希值不正确

正如你在上面解密的DigestInfo对象转储中看到的,签名的哈希值为

AD002EA501871117250DE3BF42D51B4FD2B1C5A0

但是即使上面提到的一种假设混合算法使用是可以的,这个值是不正确的,SignerInfo 中签名属性的正确 SHA-1 哈希值是

851AD7BF24D159C02A705FD4ABB20EBA9DE2AD2B

考虑到您只向签名服务发送了 SHA-256 摘要,这种不匹配实际上并不奇怪。可能该服务仅使用了 32 字节 SHA-256 摘要值中的大约 20 字节部分,或者它使用您的输入作为纯数据对其进行签名和哈希处理。

跟进

在 LBMinh 的回答中

1/ 我可以将我的摘要算法更改为 SHA1 并发送到签名服务器吗?

2/ 如果签名服务器使用我的输入作为纯数据,我可以向它发送原始数据(无哈希)吗?

3/ 为什么当我用 Foxit reader (10.0) 检查输出 pdf 时,它说有效,但在最新版本的 Foxit 或 Adob​​e 中,它说无效。

改变算法

1/ 我可以将我的摘要算法更改为 SHA1 并发送到签名服务器吗?

当然,您可以使用 SHA-1 而不是 SHA-2 变体,只需在代码中切换算法名称字符串即可。

但你不应该。 PDF 签名上下文中的 SHA-1 已被证明已被破坏,请参阅shattered.io,因此在国际上被认为已弃用。因此,除非您只签署不需要任何签名的文档,否则切换到 SHA-1 是个坏主意。没有人会相信使用 SHA-1 哈希签名的文档,除非它非常不重要。

相反,您应该研究如何从您的签名服务请求基于 SHA-2 哈希的签名或切换到其他服务。

发送原始数据

2/ 如果签名服务器使用我的输入作为纯数据,我可以向它发送原始数据(无哈希)吗?

如果它使用您的输入作为尚未散列的数据进行签名, 这很可能是一个很好的调查选择。在btnPreparePDF_Click 中,根本不消化byte[] sh,而是按原样使用它的内容。

为什么 Foxit 10 说它有效?

3/ 为什么当我用 Foxit reader (10.0) 检查输出 pdf 时,它说有效,但在最新版本的 Foxit 或 Adob​​e 中,它说无效。

正如我在上面的“问题”部分中所示,签名已损坏。因此,如果某个验证器说签名是有效的,那么您就是其中一个严重的安全漏洞的见证人。

显然福昕已经发现了这个错误并在他们的最新版本中修复了它。


附注

有什么错误吗?? PKCS#1 或 PKCS#7

带有评论“我发现了一些错误”您将以下图片添加到您的问题中

不,这没有错,“RSA with PKCS#1 v.1.5”是“RSAsSA with PKCS#1 v1.5 padding”的缩写,又名RSASSA-PKCS1-v1_5

基本上有两种基于 RSA 算法的相关签名方案,RSASSA-PKCS1-v1_5RSASSA-PSS

RSASSA-PKCS1-v1_5 是较旧的方案,它非常简单并且具有一些值得怀疑的安全属性。

RSASSA-PSS 是较新的方案,它更复杂,没有那些有问题的安全属性。

因此,基于 RSA 算法的面向未来的软件应使用RSASSA-PSS

有关这些签名方案的详细信息,请参阅RFC 8017。

【讨论】:

谢谢你,@mkl。我们发现了问题。在“btnPrepare”中,我们在签名之前对字符串进行了 2 次哈希处理,这应该会导致错误。 根据确切的签名服务,两个散列调用可能是正确的。但是,在您的情况下,显然签名服务需要原始数据和哈希本身,这会使您的第二次哈希不正确。 (尽管如此,如果您仍然混合使用哈希算法,您可能会得到验证器的混合响应......)

以上是关于使用 iTextSharp 时数字签名无效的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 itextsharp.net 将相同的数字签名放置到 PDF 中的多个位置

iTextSharp 异常:未找到 PDF 标头签名

使用itextsharp将单独签名的哈希放置到PDF中的多个位置

在PDF上创建签名字段iTextSharp。用户签名后如何自动保存PDF

签名验证前发件人证书已过期

iTunes 连接错误:您上传的二进制文件无效。签名无效,或未使用 Apple 提交证书签名