使用 iTextSharp 时数字签名无效
Digital signatures invalid when I use the iTextSharp
这是我的表格 -
代码如下-
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 字符串进行签名。服务器returns一个base64字符串。
我复制该 base64 并将其粘贴到 richtextbox2 中以签名并导出“output.pdf”文件。
然后我在 Foxit Reader(版本 10.0)上检查文件“output.pdf”,签名有效。
但是当我在 Adobe Reader 或 Adobe Acrobat 上检查该文件时,签名无效。
即使在 Foxit Reader(最新版本 10.1)上,签名也无效。怎么了???
我的英语不是很好。抱歉!
更新 - 错误!!!
这是我在 Foxit Reader 10.0(有效)上检查时的文件“output.pdf” -
这是我检查 Adobe Acrobat 的时候(它无效)-
更新...有没有错误??
PKCS#1 or PKCS#7
您的示例 PDF 中至少有两个问题,它们较少是由您的 iText 相关代码引起的,而更多是由您的签名服务或您解决问题的方式引起的。
问题
使用的混合摘要算法
您使用 SHA-256 计算已签名 PDF 字节范围的摘要。因此,SignerInfo
中存储的散列算法是SHA-256。作为 signature/encryption 算法,它仅指 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 class 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 字节部分,或者它使用您的输入作为纯数据来对其进行签名和哈希处理。
Follow-ups
在 LBMinh 的回答中
1/ Can I change my digest algorithms to SHA1 and send to signing server?
2/ If the signing server used my input as plain data, can I send raw data (no hash) to it?
3/ Why when I check the output pdf with Foxit reader (10.0), it says valid, but in newest version of Foxit or Adobe, it says invalid.
改变算法
1/ Can I change my digest algorithms to SHA1 and send to signing server?
当然,您可以使用 SHA-1 而不是 SHA-2 变体,只需在代码中切换算法名称字符串即可。
但是你不应该。 PDF 签名上下文中的 SHA-1 已被证明已损坏,请参阅 shattered.io,因此在国际上被认为已弃用。因此,除非您只签署不需要任何签名的文档,否则切换到 SHA-1 不是一个好主意。任何头脑正常的人都不会相信一份用 SHA-1 哈希签名的文件,除非它非常不重要。
相反,您应该研究如何从您的签名服务请求基于 SHA-2 散列的签名或切换到其他服务。
发送原始数据
2/ If the signing server used my input as plain data, can I send raw data (no hash) to it?
如果它使用您的输入作为 not-yet-hashed 数据进行签名, 这很可能是一个不错的调查选择。在 btnPreparePDF_Click
中,不要消化 byte[] sh
而是使用其内容 as-is.
为什么 Foxit 10 说它有效?
3/ Why when I check the output pdf with Foxit reader (10.0), it says valid, but in newest version of Foxit or Adobe, it says invalid.
正如我在上面“问题”部分中显示的那样,签名已损坏。因此,如果某个验证器说签名有效,那么您就见证了其中存在严重的安全漏洞。
显然 Foxit 已经识别出该错误并在其最新版本中修复了它。
旁注
有没有错误?? 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
是较新的方案,它更复杂并且没有那些有问题的安全属性。
Future-proof基于RSA算法的软件应该使用RSASSA-PSS
.
有关这些签名方案的详细信息,请参阅 RFC 8017。
这是我的表格 -
代码如下-
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 字符串进行签名。服务器returns一个base64字符串。
我复制该 base64 并将其粘贴到 richtextbox2 中以签名并导出“output.pdf”文件。
然后我在 Foxit Reader(版本 10.0)上检查文件“output.pdf”,签名有效。
但是当我在 Adobe Reader 或 Adobe Acrobat 上检查该文件时,签名无效。
即使在 Foxit Reader(最新版本 10.1)上,签名也无效。怎么了???
我的英语不是很好。抱歉!
更新 - 错误!!!
这是我在 Foxit Reader 10.0(有效)上检查时的文件“output.pdf” -
这是我检查 Adobe Acrobat 的时候(它无效)-
更新...有没有错误?? PKCS#1 or PKCS#7
您的示例 PDF 中至少有两个问题,它们较少是由您的 iText 相关代码引起的,而更多是由您的签名服务或您解决问题的方式引起的。
问题
使用的混合摘要算法
您使用 SHA-256 计算已签名 PDF 字节范围的摘要。因此,SignerInfo
中存储的散列算法是SHA-256。作为 signature/encryption 算法,它仅指 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 class 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 字节部分,或者它使用您的输入作为纯数据来对其进行签名和哈希处理。
Follow-ups
在 LBMinh 的回答中
1/ Can I change my digest algorithms to SHA1 and send to signing server?
2/ If the signing server used my input as plain data, can I send raw data (no hash) to it?
3/ Why when I check the output pdf with Foxit reader (10.0), it says valid, but in newest version of Foxit or Adobe, it says invalid.
改变算法
1/ Can I change my digest algorithms to SHA1 and send to signing server?
当然,您可以使用 SHA-1 而不是 SHA-2 变体,只需在代码中切换算法名称字符串即可。
但是你不应该。 PDF 签名上下文中的 SHA-1 已被证明已损坏,请参阅 shattered.io,因此在国际上被认为已弃用。因此,除非您只签署不需要任何签名的文档,否则切换到 SHA-1 不是一个好主意。任何头脑正常的人都不会相信一份用 SHA-1 哈希签名的文件,除非它非常不重要。
相反,您应该研究如何从您的签名服务请求基于 SHA-2 散列的签名或切换到其他服务。
发送原始数据
2/ If the signing server used my input as plain data, can I send raw data (no hash) to it?
如果它使用您的输入作为 not-yet-hashed 数据进行签名, 这很可能是一个不错的调查选择。在 btnPreparePDF_Click
中,不要消化 byte[] sh
而是使用其内容 as-is.
为什么 Foxit 10 说它有效?
3/ Why when I check the output pdf with Foxit reader (10.0), it says valid, but in newest version of Foxit or Adobe, it says invalid.
正如我在上面“问题”部分中显示的那样,签名已损坏。因此,如果某个验证器说签名有效,那么您就见证了其中存在严重的安全漏洞。
显然 Foxit 已经识别出该错误并在其最新版本中修复了它。
旁注
有没有错误?? 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
是较新的方案,它更复杂并且没有那些有问题的安全属性。
Future-proof基于RSA算法的软件应该使用RSASSA-PSS
.
有关这些签名方案的详细信息,请参阅 RFC 8017。