iTextSharp - 如何获取用于签名的PDF内容,然后在以后签名

And*_*ges 3 c# itext

我正在开发一个客户端 - 服务器应用程序,客户端必须使用签名对PDF文档进行签名并将其上载到服务器.任务由一个事实,即客户不必嵌入签名转换成PDF的手段,他们只能读取原始字节和原始字节的形式生成签名复杂.

我正在尝试实现以下工作流程:

  1. 客户端将未签名的PDF上载到服务器
  2. 服务器打开PDF,提取客户端需要签名的字节,然后将这些字节发回
  3. 客户端接收这些字节,使用客户端证书对其进行签名,并将签名发送到服务器
  4. 服务器将收到的签名嵌入到之前收到的PDF中.

我发现了一些提取字节的代码示例,用于签名并将签名字节嵌入到PDF中(这是我正在使用的主要示例).

问题是这个示例执行一个程序中的所有步骤,它在获取文档哈希后立即嵌入签名而不关闭PdfStamper.我需要一些方法来保存文档添加签名域和获取后sha.Hash,然后在一段时间后(当服务器收到计算签名)打开文档,并嵌入签名值到PDF.

您能否提供一个方法来修改这个代码,以便在步骤(2)和(4)可以是独立的,并且不需要共享实例PdfReaderPdfStamper

And*_*ges 5

自己搞清楚了.这段代码向我指出了正确的方向.

原来服务器上的进程必须如下:

  • 获取未签名的PDF并添加一个空的签名字段
  • 根据文件的修改内容计算需要签名的字节
  • 将带有空签名的已修改PDF保存到临时文件中
  • 将计算的字节发送到客户端
  • 当客户端使用签名响应时,打开临时文件并将签名插入到先前创建的字段中

相关的服务器代码:

public static byte[] GetBytesToSign(string unsignedPdf, string tempPdf, string signatureFieldName)
{
    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, 144, 780), 1, signatureFieldName);
            IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
            MakeSignature.SignExternalContainer(appearance, external, 8192);

            return SHA1Managed.Create().ComputeHash(appearance.GetRangeStream());
        }
    }
}
public static void EmbedSignature(string tempPdf, string signedPdf, string signatureFieldName, byte[] signedBytes)
{
    using (PdfReader reader = new PdfReader(tempPdf))
    {
        using (FileStream os = File.OpenWrite(signedPdf))
        {
            IExternalSignatureContainer external = new MyExternalSignatureContainer(signedBytes);
            MakeSignature.SignDeferred(reader, signatureFieldName, os, external);
        }
    }
}

private class MyExternalSignatureContainer : IExternalSignatureContainer
{
    private readonly byte[] signedBytes;

    public MyExternalSignatureContainer(byte[] signedBytes)
    {
        this.signedBytes = signedBytes;
    }

    public byte[] Sign(Stream data)
    {
        return signedBytes;
    }

    public void ModifySigningDictionary(PdfDictionary signDic)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

旁注:在所有这些iText样本中困扰我的是魔术数字(如此8192处)的存在,没有任何评论.这使得使用这个库变得更加困难和烦人.