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

我正在开发一个客户端 – 服务器应用程序,客户端必须使用签名对PDF文档进行签名并将其上载到服务器.由于客户端无法将签名嵌入到PDF中,因此它们只能读取原始字节并以原始字节的形式生成签名,这使得任务变得复杂.

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

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

我发现了一些提取字节的代码示例,用于签名并将签名字节嵌入PDF(this is the main sample I’m using).

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

您能否建议一种修改代码方法,以便步骤(2)和(4)可以独立,并且不需要PdfReader和pdfstamper的共享实例?

解决方法

自己搞清楚了. This piece of code向我指出了正确的方向.

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

>获取未签名的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,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)
    {
    }
}

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

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...