当前位置: 首页 > 知识库问答 >
问题:

使用异步调用对哈希签名

景才英
2023-03-14

我正在使用iText7执行PDF和签名操作。我的场景是,我在本地机器上计算哈希,并将这个哈希发送到签名服务器,作为响应,得到签名的PKCS1(原始签名),然后我将这个签名嵌入到PDF中。我的代码片段如下:

1:从智能卡设备读取公共证书。

3:初始化PdfSigner并设置签名外观:

PdfSigner pdfSigner = new PdfSigner(pdfReader, outputStream, new StampingProperties().UseAppendMode());
 pdfSigner.SetFieldName("Signature1");
 pdfSigner.GetDocument().GetCatalog().SetModified();
ImageData imageData = ImageDataFactory.Create(handSignatureBytes);
PdfSignatureAppearance signatureAppearance = pdfSigner.GetSignatureAppearance();
 signatureAppearance.SetContact("contactInfo");
 signatureAppearance.SetLocation("locationInfo");
 signatureAppearance.SetPageNumber(1);
 signatureAppearance.SetReason("signingReason");
 signatureAppearance.SetSignatureGraphic(imageData);
 signatureAppearance.SetRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
 signatureAppearance.SetSignatureCreator("Malik");
 signatureAppearance.SetCertificate(x509Certificate);

4:我已经实现了IExternalSignatureContainer接口来获取文档哈希:

public class PreSigning : IExternalSignatureContainer
 {
 protected PdfDictionary sigDic;
 private byte[] hash;
public PreSigning(PdfName filter, PdfName subFilter)
 {
 sigDic = new PdfDictionary();
 sigDic.Put(PdfName.Filter, filter);
 sigDic.Put(PdfName.SubFilter, subFilter);
 }
public void ModifySigningDictionary(PdfDictionary signDic)
 {
 signDic.PutAll(sigDic);
 }
public byte[] Sign(Stream data)
 {
 this.hash = DigestAlgorithms.Digest(data, DigestAlgorithms.GetMessageDigest("SHA256"));
 return new byte[0];
 }
public byte[] getHash()
 {
 return hash;
 }
public void setHash(byte[] hash)
 {
 this.hash = hash;
 }
 }

5:获取文档哈希:

PreSigning external = new PreSigning(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
 pdfSigner.SignExternalContainer(external, estimatedSize);
byte[] documentHash = external.getHash();
PdfPKCS7 pdfPKCS7 = new PdfPKCS7(null, x509CertificatesChain, "SHA256", false);
 dataToBeSigned = pdfPKCS7.GetAuthenticatedAttributeBytes(documentHash, PdfSigner.CryptoStandard.CMS, null, null);
byte[] dataToSignHash = DigestAlgorithms.Digest(new MemoryStream(dataToBeSigned), DigestAlgorithms.GetMessageDigest("SHA256"));

7:我保留了来自PdfSigner的outputStream用于签名嵌入阶段:

documentStreamBytes = ((MemoryStream)outputStream).ToArray();

8:将待签名的数据哈希发送到签名服务器。

9:从签名服务器获取PKCS1数据以响应:

byte[] PKCS1 = Convert.FromBase64String(preSigningResponse.signedHash);
PdfPKCS7 pdf = new PdfPKCS7(null, x509CertificatesChain, "SHA256", false);
pdf.SetExternalDigest(PKCS1, null, "RSA");
byte[] pkcs7Data = pdf.GetEncodedPKCS7(documentHash, PdfSigner.CryptoStandard.CMS, null, null, null);

11:从DocumentStreamBytes获取原始文档:

Stream pdfReaderStream = new MemoryStream(documentStreamBytes);
PdfReader reader = new PdfReader(pdfReaderStream);
PdfDocument originalDocument = new PdfDocument(reader, new PdfWriter(new MemoryStream()));

12:我已经使用PDFSigner.SignDeferred()方法实现了用于签名嵌入的IExternalSignatureContainer:

public class PostSigning : IExternalSignatureContainer
 {
 protected byte[] _sig;
 public PostSigning (byte[] sign)
 {
 _sig = sign;
 }
 public void ModifySigningDictionary(PdfDictionary signDic)
 {
 }
public byte[] Sign(Stream data)
 {
 return _sig;
 }
 }

13:调用pdfSigner.SignDeferred()方法获取最终文档:

Stream resultStream = new MemoryStream();
IExternalSignatureContainer externalSignatureContainer = new PostSigning(pkcs7Data);
PdfSigner.SignDeferred(originalDocument, "Signature1", resultStream, externalSignatureContainer);
byte[] finalDoc = ((MemoryStream)resultStream).ToArray();

有谁能帮助我使用iText7解决这个问题吗

共有1个答案

赫连黎昕
2023-03-14

您的代码中有许多问题。

最重要的是:在第二部分(将返回的PKCS1嵌入到PDF中)中,您将从原始文件重新开始,并在其中创建一个新的签名字段。这将导致PDF与您在第一部分中准备的PDF略有不同;因此,您在两部分之间检索到的签名值显然不能用于此新PDF。

你必须改变你的体系结构。

如果您希望保留您的两步方法,您必须将您在第一部分中创建的文件保留在outputStream中,并在第二部分中重新使用它。并且要填写检索到的签名,必须使用PDFSigner.SignDeferred而不是以新的PDFSigner开始。

或者,您可以一步完成,将签名服务器调用放入自定义的iExternalSignatureContainer实现中。

在第一部分中,您似乎将OutputStream内容设置为要签名的数据(实际上,您甚至将其放入了一个字段,该字段的名称为ResponseObject.Base64Hash,它应该只包含一个哈希值;我根本不理解这一点)。但要签名的字节不是完整的outputstream内容,则必须排除其中用于最终签名值的占位符。

您必须只在没有该占位符的结果PDF上签名。如果您通过重写byte[]Sign(Stream data)方法并获取其Stream参数来扩展它,则可以获得它,而不是externalblanksignaturecontainer。此流正好包含要签名的字节。

您提到从签名服务器获取签名的Pkcs1。但是,您需要的是一个CMS签名容器。

如果您的签名服务器还提供返回CMS(或PKCS#7)签名容器,请使用这种调用。

否则,您必须自己构建一个CMS容器,例如使用iTextpdfpkcs7类或BouncyCastle机制。

 类似资料:
  • 我正在尝试用DSS签署PDF文档,我的问题是我无法在服务器a中计算文档的哈希值,然后在服务器B中签署它。 知道服务器A包含PDF文档,我们在服务器B中检索用于签名的证书 我的问题是如何在不需要证书的情况下计算服务器a中文档的哈希值。然后在服务器B上发送签名? 更新: ******散列的准备和计算******** ******散列签名******** ********PDF错误:*********

  • 我有一个应用程序生成一个PDF,需要签名。 我们没有用于签署文档的证书,因为它们在HSM中,而我们可以使用证书的唯一方法是使用WebService。 这是我们的代码,首先,我们得到签名外观,并计算散列 在这一点上,我们得到一个已签名的PDF,但签名无效。Adobe称“文档自签署以来已被更改或损坏”。 我已经通过使用外部服务和iText,PDF签名iText pkcs7多签名和是否可能签署一个PDF

  • 我可以通过外部签名使用itextpdf库对文档进行签名。 但问题是,最终用户不想发送他的文档,因为它可能包含任何敏感数据。因此,我要求最终用户给出文档哈希,以便与外部服务签署哈希,并将签署后的哈希发回。 但是,问题来了,当他们试图使用itextpdf()用给定的签名散列对文档进行签名时,PDF文档被签名了。但在验证签名时,表明签名是无效的。 因此,问题的发生是因为每次使用(itextpdf库)打开

  • 我使用OpenSSL创建了一个自签名证书,如下所示: 然后,我在C#.NET4.0中编写了以下代码: 使用一些文章和答案中的解决方案,我有类,我试图在其中实现和注册签名描述: 我已经验证了hash的长度为字节,它返回一个。但是如果我使用var(20字节长),尽管中指定的算法是,但它可以工作,并使用算法对哈希进行签名。 另外,如果我打印,它的值是http://www.w3.org/2000/09/x

  • 问题内容: 我感觉自己快要到了,但是对异步的不完全理解使我无法解决这个问题。我基本上是在尝试使用bcrypt哈希密码,并决定将hashPassword函数分离出来,以便可以在应用程序的其他部分中使用它。 不断返回undefined … 问题答案: 剂量等待因为不退诺。请使用以下方法,该方法将Promise包裹起来才能使用。

  • 问题内容: 我需要一个Python / C / C ++ / Java实现,可以 暂停散列进步 和 商店 ,在这样一个文件进度的进展是 可恢复 从该文件在稍后阶段。 无论上面列出的是哪种语言编写的,它都应该可以在Python中正常工作。建议您提供它以便与“ hashlib”一起良好地工作,但这不是必需的。同样,如果已经存在这样的事物,那么到此的链接就足够了。 对于一个想法 ,您的实现应该实现什么。