使用 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。
但是当我在 Adobe Reader 或 Adobe Acrobat 上检查该文件时,签名无效。
即使在福昕阅读器(最新版本 10.1)上,签名也是无效的。怎么了???
我的英语不太好。对不起!
更新 - 错误!!!
这是我在 Foxit Reader 10.0 上查看时的“output.pdf”文件(有效)-
这是我检查 Adobe 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 或 Adobe 中,它说无效。
改变算法
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 或 Adobe 中,它说无效。
正如我在上面的“问题”部分中所示,签名已损坏。因此,如果某个验证器说签名是有效的,那么您就是其中一个严重的安全漏洞的见证人。
显然福昕已经发现了这个错误并在他们的最新版本中修复了它。
附注
有什么错误吗?? 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_5
和 RSASSA-PSS
。
RSASSA-PKCS1-v1_5
是较旧的方案,它非常简单并且具有一些值得怀疑的安全属性。
RSASSA-PSS
是较新的方案,它更复杂,没有那些有问题的安全属性。
因此,基于 RSA 算法的面向未来的软件应使用RSASSA-PSS
。
有关这些签名方案的详细信息,请参阅RFC 8017。
【讨论】:
谢谢你,@mkl。我们发现了问题。在“btnPrepare”中,我们在签名之前对字符串进行了 2 次哈希处理,这应该会导致错误。 根据确切的签名服务,两个散列调用可能是正确的。但是,在您的情况下,显然签名服务需要原始数据和哈希本身,这会使您的第二次哈希不正确。 (尽管如此,如果您仍然混合使用哈希算法,您可能会得到验证器的混合响应......)以上是关于使用 iTextSharp 时数字签名无效的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 itextsharp.net 将相同的数字签名放置到 PDF 中的多个位置
使用itextsharp将单独签名的哈希放置到PDF中的多个位置