加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 23:35:18 所属栏目:百科 来源:网络整理
导读:我正在开发一个客户端 – 服务器应用程序,客户端必须使用签名对PDF文档进行签名并将其上载到服务器.由于客户端无法将签名嵌入到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,'');
            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这里),没有任何评论.这使得使用这个库变得更加困难和烦人.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读