iTextSharp - 签名哈希

时间:2016-02-03 14:45:23

标签: pdf hash itextsharp itext

我正在开发WebService,客户可以签署PDF,这是以下步骤:

  1. 客户选择要签名的pdf
  2. Web服务从pdf中提取哈希并将其发送给外部提供商
  3. 外部提供商签署哈希
  4. 外部提供商发回已签名的哈希
  5. Web Service将签名的哈希包含回pdf
  6. 客户已签名PDF
  7. 我在尝试将签名哈希插入/更新到pdf时遇到了一个大问题。

    我正在使用iTextSharp。

    我已经阅读了白皮书" PDF文档的数字签名"来自Bruno Lowagie,这是一个很好的帮助,但我无法弄清楚如何插入签名的哈希,顺便说一下,这是我唯一拥有的,没有证书,没有任何东西。

    请帮助。

    加布里埃尔

1 个答案:

答案 0 :(得分:1)

根据您的评论,您目前的方法如下:

  

基本上我像这样提取pdf文件的哈希值。

private string FileHash(byte[] vGblFilePDF)
{
    using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
    {
        vGblHash = Convert.ToBase64String(sha1.ComputeHash(vGblFilePDF));
    }
    return vGblHash;
}
     

然后我将它发送给提供商提供WS,只添加一个Id号码,然后提供商发回给我(在识别之后)签名的哈希值,我必须插入到pdf中。

这种做法从根本上说是错误的,你已经开始计算错误的哈希了!

首先必须准备PDF ;在此准备步骤中,您将某些结构添加到PDF中,将PDF标记为包含签名,并为稍后插入签名容器保留一个部分;除了保留的部分之外的所有都要进行哈希处理:

Basic structure of a signed PDF

(有关其他文献的背景和指示,参见this answer。)

此后,必须创建一个包含该文档哈希签名的完整PKCS#7 / CMS签名容器并将其插入该保留部分。

这就是大多数iText签名代码(此处为Java)为您所做的事情:

PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = ...;
MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);

(取自C2_01_SignHelloWorld.java相当于C2_01_SignHelloWorld.cs

您只需要提供与您的提供商沟通的ExternalSignature / IExternalSignature实施:

public interface IExternalSignature {

    /**
     * Returns the hash algorithm.
     * @return  the hash algorithm (e.g. "SHA-1", "SHA-256,...")
     */
    String GetHashAlgorithm();

    /**
     * Returns the encryption algorithm used for signing.
     * @return the encryption algorithm ("RSA" or "DSA")
     */
    String GetEncryptionAlgorithm();

    /**
     * Signs it using the encryption algorithm in combination with
     * the digest algorithm.
     * @param message   the message you want to be hashed and signed
     * @return  a signed message digest
     * @throws GeneralSecurityException
     */
    byte[] Sign(byte[] message);
}