【问题标题】:placing the separately signed hash to Multiple places in PDF using itextsharp使用 itextsharp 将单独签名的哈希放置到 PDF 中的多个位置
【发布时间】:2018-02-23 08:12:45
【问题描述】:

我想在 PDF 的多个位置放置相同的外部签名哈希(签名值)。

我已经参考了页面'how-to-place-the-same-digital-signatures-to-multiple-places-in-pdf-using-itextsh' 并尝试实施 mkl 提供的解决方法(请参阅这个How to place the Same Digital signatures to Multiple places in PDF using itextsharp.net)。

而且它有效。我将它移植到使用 Web 服务/api 在外部对签名者字节进行签名,它也可以工作。现在由于一项要求,我改变了计算哈希的方式。

现在而不是(旧的):

byte[] hash = DigestAlgorithms.Digest(data, "SHA256");
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);

我正在尝试使用(新的):

        int contentEstimated=8192;
        HashAlgorithm sha = new SHA256CryptoServiceProvider();
        int read = 0;
        byte[] buff = new byte[contentEstimated];
        while ((read = data.Read(buff, 0, contentEstimated)) > 0)
        {
            sha.TransformBlock(buff, 0, read, buff, 0);
        }
        sha.TransformFinalBlock(buff, 0, 0);
        byte[] hash = Org.BouncyCastle.Utilities.Encoders.Hex.Encode(sha.Hash);

        string hashtext = Encoding.UTF8.GetString(hash, 0, hash.Length); //for writing it to file or sharing it to another api
        byte[] hash1 = StringToByteArray(hashtext);

        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash1, null, null, CryptoStandard.CMS); or 
        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS); //tried both

如果我尝试在现有实现中使用它,则签名会因错误“文档自签名后已被更改或损坏”而无效。你能告诉我我在哪里做错了吗?

在大多数引用的页面中,他们都使用了这种带有嵌入函数的哈希生成方法,其中计算的哈希被嵌入到 pdf 中,

    byte[] paddedSig = new byte[csize];
    System.Array.Copy(pk, 0, paddedSig, 0, pk.Length);
    PdfDictionary dic2 = new PdfDictionary();
    dic2.Put(PdfName.CONTENTS, new PdfString(paddedSig).SetHexWriting(true));
    appearance.Close(dic2);

谢谢。 - 谭美

【问题讨论】:

  • 它应该只使用sha.Hash
  • 是的.. 它与 sha.hash 一起使用。但是,如果试图通过 sha.hash 获取哈希字符串,则它不起作用。我试过.. string hashtext1 = Convert.ToBase64String(hash);字符串 hashtext = Encoding.UTF8.GetString(hash, 0, hash.Length);有了这个,我想要一个 64 字节的哈希字符串。有可能吗?
  • 更改实现的基本前提是获得 64 字节长的哈希。我正在寻找以某种方式生成文档哈希的方法,----- 1 - 将其转换为一个 64 字节长的字符串和 2 - 使用哈希字节数组在上述实现中获取有效签名
  • 你不能在哈希中放任何你想要的东西,记住哈希是重新创建的,以便在验证完成时进行比较。如果您需要 64 字节长的哈希,请尝试 SHA512。
  • 正如@Paulo 所说,您放入getAuthenticatedAttributeBytes 的哈希值参数需要是对文档数据应用摘要算法的结果。不过,您可以选择摘要算法,而 SHA512 将产生 64 字节的值。但是,不要忘记相应地调整您在 PdfPKCS7 构造函数中使用的摘要算法名称。另一方面,如果 sha512 不是您想要的,您可能应该解释一下您的 64 字节要求的背景......

标签: pdf c#-4.0 itext signing


【解决方案1】:

在 cmets 中,OP 澄清说他希望将解决方案 here 调整为使用接受文档哈希的外部签名服务(更准确地说是十六进制格式文档的 SHA256 哈希值)并返回一个成熟的 CMS 签名容器。

在这种情况下原来的AllPagesSignatureContainer方法Sign

public byte[] Sign(Stream data)
{
    String hashAlgorithm = externalSignature.GetHashAlgorithm();
    PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, false);
    IDigest messageDigest = DigestUtilities.GetDigest(hashAlgorithm);
    byte[] hash = DigestAlgorithms.Digest(data, hashAlgorithm);
    byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
    byte[] extSignature = externalSignature.Sign(sh);
    sgn.SetExternalDigest(extSignature, null, externalSignature.GetEncryptionAlgorithm());
    return sgn.GetEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS);
}

必须更改为不使用PdfPKCS7 sgn 自己创建CMS 容器,而仅计算文档哈希,将其发送到服务并使用服务返回的容器:

public byte[] Sign(Stream data)
{
    String hashAlgorithm = externalSignature.GetHashAlgorithm();
    IDigest messageDigest = DigestUtilities.GetDigest(hashAlgorithm);
    byte[] hash = DigestAlgorithms.Digest(data, hashAlgorithm);
    byte[] hexHash = Org.BouncyCastle.Utilities.Encoders.Hex.Encode(hash);
    string hexHashString = Encoding.UTF8.GetString(hexHash , 0, hexHash.Length);
    var response = [... call service with document hash hexHashString ...];
    byte[] signatureContainer = [... extract binary CMS container from response ...];
    return signatureContainer;
}

OP 没有提到任何关于响应格式的内容,所以我不能多说 response 部分提取二进制 CMS 容器。它可能包括选择较大响应结构的一个属性,它可能包括解码编码值(可能是十六进制编码字符串),...

【讨论】:

  • 需要对其进行解码并且它有效。在返回容器之前我错过了这一点,我没有删除“SetExternalDigest”语句。这就是为什么我得到损坏的签名。万分感谢。 - 坦梅
猜你喜欢
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 2016-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
相关资源
最近更新 更多