2016-02-03 47 views
0

我正在开发一个WebService是一个客户端可以签署一份PDF,这个步骤如下:iTextSharp的 - 签名哈希

  1. 客户选择PDF签署
  2. Web服务从PDF中提取的散列并将其发送给外部提供商
  3. 外部提供标志哈希
  4. 外部提供发回签署哈希
  5. Web服务包括签署哈希回PDF
  6. 客户端有签署的PDF

我会遇到一个很大的问题,试图插入/更新签名哈希到pdf中。

我正在使用iTextSharp。

我已经阅读Bruno Lowagie的白皮书“PDF文档的数字签名”,这是一个很大的帮助,但我无法弄清楚如何插入签名的散列,顺便说一句,是我唯一的东西,没有证书,没什么。

请帮忙。

加布里埃尔

+1

您是否保留了原始的'PdfStamper'和'SignatureAppearanc e'?至少没有你的代码的关键部分,它很难帮助你。 – mkl

+0

就是这样,提供者只要求散列。没有签名外观,没有什么。 基本上我提取PDF文件的哈希像这样。 [CODE] 私人字符串FileHash(字节[] vGblFilePDF) { \t使用(SHA1CryptoServiceProvider SHA1 =新SHA1CryptoServiceProvider()) \t { \t \t vGblHash = Convert.ToBase64String(sha1.ComputeHash(vGblFilePDF)); \t} \t return vGblHash; } 然后我把它发送给提供者,发送一个WS,只添加一个Id号码,然后提供者发送回(在识别之后)签名哈希,我必须插入到pdf中。 我知道缺少一些东西。问候。 – Gabriel

回答

0

根据你对自己目前的做法如下:

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

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

然后我把它发送给供应商trought一个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); 

你只需要提供一个ExternalSignature/IExternalSignature(从C2_01_SignHelloWorld.java相当于C2_01_SignHelloWorld.cs拍摄)实施与您的提供商沟通:

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); 
} 
+0

非常感谢您的回答。如果我理解正确的行ExternalSignature签名= ...;将是签名散列。但是,在MakeSignature.signDetached(外观,摘要,签名,链,null,null,null,0,subfilter)行中,我需要一个我没有的证书(链变量)。最好的办法就是IText白皮书第116页至第120页的例子,但我错过了一些数据(已经与我的提供商交谈)。非常感谢你的帮助!! – Gabriel

+0

无论如何您都需要证书,无论是明确还是隐含地使用签名提供程序,该签名提供程序都会发回已包含签名者证书的完整PKCS#7/CMS签名容器。证书毕竟表明签名者的身份... – mkl

+0

“*如果我理解正确的话'ExternalSignature signature = ...;'将是签名的哈希。*” - 不完全...它将是具有方法byte [] Sign(byte [] message)的类的实例;'which(when called)返回散列的签名字节。 – mkl