【问题标题】:Digital Signature (PKCS#7 - Deferred Signing) / The document has been altered or corrupted since the signature was applied数字签名(PKCS#7 - 延迟签名)/自应用签名以来文档已被更改或损坏
【发布时间】:2023-04-03 08:08:01
【问题描述】:

我已经解决了所有类似的问题,但找不到应用 itextsharp 延迟签名的案例。

基本上,我的应用程序使用由远程 Web 服务创建的 PKCS#7 签名对 pdf 文档进行签名。

我的应用程序向此 Web 服务发送原始文档的哈希(添加空签名字段后的可签名字节的哈希),并接收 Base64 编码的签名文件。

我将此签名嵌入到先前生成的具有空签名字段的临时 pdf 文件中。

最后我的签名没有得到验证,因为 Adob​​e Reader 说文档已更改或已损坏。

添加空签名字段并获取 Pdf 可签名字节的代码

public static string GetBytesToSign(string unsignedPdf, string tempPdf, string signatureFieldName)
{
    if (File.Exists(tempPdf))
        File.Delete(tempPdf);

    using (PdfReader reader = new PdfReader(unsignedPdf))
    {
        using (FileStream os = File.OpenWrite(tempPdf))
        {
            PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
            PdfSignatureAppearance appearance = stamper.SignatureAppearance;
            appearance.SetVisibleSignature(new Rectangle(36, 748, 250, 400), 1, signatureFieldName);

            IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);

            MakeSignature.SignExternalContainer(appearance, external, 8192);

            byte[] array = SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());

            return Convert.ToBase64String(array);
        }
    }
}

这个操作的结果是生成了tempPdf,我从这个tempPdf 文件中接收到pdf 文档的可签名字节的哈希值。

然后使用下面的代码,我重新打开这个 tempFile 并嵌入 Base64 编码的 PKCS#7 签名。

打开 Temp Pdf 并嵌入收到的签名的代码

public static void EmbedSignature(string tempPdf, string signedPdf, string signatureFieldName, string signature)
{
    byte[] signedBytes = Convert.FromBase64String(signature);

    using (PdfReader reader = new PdfReader(tempPdf))
    {
        using (FileStream os = File.OpenWrite(signedPdf))
        {
            IExternalSignatureContainer external = new MyExternalSignatureContainer(signedBytes);
            MakeSignature.SignDeferred(reader, signatureFieldName, os, external);
        }
    }
}

作为这个操作的结果,我的最终signedPdf 被生成。但是,Adobe 表示签名因更改或损坏而无效。

My Original File

Temporary File Generated For Signing

Final Signed File

我发送到网络服务的 tempFile 文件的哈希是:

z9qIyvtp4cRBZ1SSCQ+P0JVRinz5lvjYjXk3L7YP/IE=

我从网络服务收到的签名是:

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

我比较了 tempFile 和 signedFile 的字节,只有 tempFile 的零(我认为是用于临时签名文件)被 signedFile 中的实际签名替换。

我真的被困在这一点上。我不确定接下来应该去哪里看。

【问题讨论】:

  • 您确定GetBytesToSign 中的return 行真的返回Convert.FromBase64String(array) 而不是Convert.ToBase64String(array)?前者没有意义,array 不是 base64 字符串,因此它不能明智地作为调用转换 from base64 字符串的参数。
  • 抱歉,打错了,已修复。我在 GetBytesToSign 之外进行转换,并在编写问题时将其移动到方法中。
  • Raadol Hallederiz.....

标签: c# pdf hash itext digital-signature


【解决方案1】:

在您从网络服务收到的签名中有:

  39   59: . . . SEQUENCE {
  41    9: . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
         : . . . . . (PKCS #7)
  52   46: . . . . [0] {
  54   44: . . . . . OCTET STRING    
         : . . . . . . 7A 39 71 49 79 76 74 70    z9qIyvtp
         : . . . . . . 34 63 52 42 5A 31 53 53    4cRBZ1SS
         : . . . . . . 43 51 2B 50 30 4A 56 52    CQ+P0JVR
         : . . . . . . 69 6E 7A 35 6C 76 6A 59    inz5lvjY
         : . . . . . . 6A 58 6B 33 4C 37 59 50    jXk3L7YP
         : . . . . . . 2F 49 45 3D                /IE=
         : . . . . . }
         : . . . . }
[...]
1955    9: . . . . . SEQUENCE {
1957    5: . . . . . . OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
         : . . . . . . . (OIW)
1964    0: . . . . . . NULL
         : . . . . . . }
1966   93: . . . . . [0] {
1968   24: . . . . . . SEQUENCE {
1970    9: . . . . . . . OBJECT IDENTIFIER contentType (1 2 840 113549 1 9 3)
         : . . . . . . . . (PKCS #9)
1981   11: . . . . . . . SET {
1983    9: . . . . . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
         : . . . . . . . . . (PKCS #7)
         : . . . . . . . . }
         : . . . . . . . }
1994   28: . . . . . . SEQUENCE {
1996    9: . . . . . . . OBJECT IDENTIFIER signingTime (1 2 840 113549 1 9 5)
         : . . . . . . . . (PKCS #9)
2007   15: . . . . . . . SET {
2009   13: . . . . . . . . UTCTime 22/09/2017 13:18:38 GMT
         : . . . . . . . . }
         : . . . . . . . }
2024   35: . . . . . . SEQUENCE {
2026    9: . . . . . . . OBJECT IDENTIFIER messageDigest (1 2 840 113549 1 9 4)
         : . . . . . . . . (PKCS #9)
2037   22: . . . . . . . SET {
2039   20: . . . . . . . . OCTET STRING    
         : . . . . . . . . . EF 37 38 3B B1 31 AB 96    .78;.1..
         : . . . . . . . . . CE FC 47 1E 32 A7 79 73    ..G.2.ys
         : . . . . . . . . . 5D 95 15 04                ]...
         : . . . . . . . . }
         : . . . . . . . }
         : . . . . . . }
2061   13: . . . . . SEQUENCE {
2063    9: . . . . . . OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
         : . . . . . . . (PKCS #1)
2074    0: . . . . . . NULL
         : . . . . . . }

在这里,您的 base64 编码哈希显示为嵌入的签名数据(偏移量 56..99)。此外,散列算法选择为“SHA-1”(偏移量 1955..1965),签名文档散列是一个 20 字节的值,与 SHA-1 散列值的大小相匹配。此外,RSA 用于签名,如 PKCS#1 1.5 中所述(偏移量 2061..2075)。

因此,您的签名服务似乎没有使用您的输入作为 base64 编码的预先计算的文档哈希值,而是作为使用 SHA1withRSA/2048 进行签名的纯数据。

所以错误不在您的 iText 使用代码中,而是在您的签名服务调用代码中。

【讨论】:

  • 非常感谢。虽然我明确地请求 base64 编码哈希值的签名,但服务正在返回我共享的签名。
  • 所以签名无效是因为签名使用的SHA1算法?
  • 没有。因为您提供给服务的数据已经是文档数据的散列,但服务将它们作为纯数据,它仍然应该散列。
猜你喜欢
  • 2021-05-11
  • 1970-01-01
  • 2018-12-04
  • 2021-06-20
  • 2016-09-16
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多