【问题标题】:Adding a Digital signature to a PDF with iTextSharp使用 iTextSharp 向 PDF 添加数字签名
【发布时间】:2018-11-17 04:07:06
【问题描述】:

背景

我使用 iTextSharp 已经有一段时间了。我创建了一个带有两个可签名 PdfFormFields 的 pdf 文档。如果我打开 pdf 文档,我可以手动手动签署每个字段。我希望通过 iTextSharp 完成。

我目前正在从 X509Store 检索证书。到目前为止,我可以弄清楚。

问题

谁能告诉我如何使用这个 X509Certificate2 签署一个已经存在的签名 AcroField。

参考文献

访问了以下参考资料,但找不到我正在寻找的答案。 Signing a pdf document

这个链接让我最接近我相信,但使用的几行是无效的,我不知道我是否可以通过包含其他一些库来修复它。 https://www.dotnetportal.cz/blogy/15/Null-Reference-Exception/5250/Digitalni-podepisovani-PDF-souboru-v-C-cast-2

【问题讨论】:

  • 首先,您是否检查过该表单是 AcroForm 还是 XFA 表单?
  • 这是一个 AcroForm,但这只是因为我得到了 AcroForm 的最佳示例。
  • 您是否尝试过类似this answer 的方法?如果可行,我建议使用它并进行一些改进(特别是不要使用 SHA-1,而是使用 SHA-2 和 SHA-3 系列的成员)。
  • @StephanV.dWesthuizen 你有解决办法吗?我们正在寻找类似的流程。
  • @cableload 我找不到解决方案。我们正在使用第三方公司来处理我们的签名,并希望在不必使用他们的外部签名程序的情况下签署我们的文件。这个项目对时间很敏感,所以我不能在这个问题上坐太久。我决定在我们的应用程序中使用他们的 API,而不是每次都使用外部程序来签署文档。谢谢你的帮助mkl。该公司的名称是 DocuSign。虽然它不是免费的。这是他们网站的链接:docusign.com

标签: c# pdf itext digital-signature x509certificate2


【解决方案1】:

你需要的一切:

appearance.SetVisibleSignature("---> ExistSignatureName <-----");
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);

完整代码:

private static void SignPdf(string filename, string folderPdf, string pathToNewSignFile, string pathToCerts, string nameCert, string passCert)
{      
    var pathToCert = GetFullNameFile(pathToCerts, nameCert); //Oh.. I did not know about the Path.Combine function.

    if (!File.Exists(pathToCert))
    {
        logger.Error("Certificate not exist " + pathToCert);
        return;
    }

    var pass = passCert.ToCharArray();

    FileStream fs;
    try
    {
        fs = new FileStream(pathToCert, FileMode.Open);
    }
    catch (Exception ex)
    {
        logger.Error(ex, "Could not open cert" + pathToCert);
        return;
    }

    var store = new Pkcs12Store(fs, pass);

    fs.Close();

    var alias = "";

    // searching for private key
    foreach (string al in store.Aliases)
        if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
            alias = al;
            break;
        }

    var pk = store.GetKey(alias);

    ICollection<X509Certificate> chain = store.GetCertificateChain(alias).Select(c => c.Certificate).ToList();

    var parameters = pk.Key as RsaPrivateCrtKeyParameters;

    var pathPdf = GetFullNameFile(folderPdf, filename); //Oh.. I did not know about the Path.Combine function.

    var pathToSigPdf = GetFullNameFile(pathToNewSignFile, filename);

    if (!File.Exists(pathPdf))
    {
        logger.Error("Could not open file" + pathPdf + "  File not exist");
        return;
    }

    var reader = new PdfReader(pathPdf);


    FileStream fileStreamSigPdf;
    try
    {
        fileStreamSigPdf = new FileStream(pathToSigPdf, FileMode.Create);
    }
    catch (Exception ex)
    {
        logger.Error(ex, "Could not create file" + pathToSigPdf);
        return;
    }

    var stamper = PdfStamper.CreateSignature(reader, fileStreamSigPdf, '\0', null, true);

    var appearance = stamper.SignatureAppearance;
    appearance.Reason = "Утверждено";

    appearance.SetVisibleSignature("---> ExistSignatureName <-----");

    IExternalSignature pks = new PrivateKeySignature(parameters, DigestAlgorithms.SHA256);
    MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);

    fileStreamSigPdf.Close();
    reader.Close();
    stamper.Close();

    logger.Info("Signed successfully " + filename);
}

我们公司有一个网络服务器。 1.获取哈希字段 2. 在加密插件的帮助下,我们对哈希进行签名 3. 在字段中插入签名

第 1 步。

public string PrepareSignatureAndGetHash()
    {
        var hash = string.Empty;

        using (var reader = new PdfReader("PathTemplate"))
        {
            using (var fileStream = File.OpenWrite("PathToTemp"))
            {
                using (var stamper = PdfStamper.CreateSignature(reader, fileStream, '0', null, true))
                {
                    var signatureAppearance = stamper.SignatureAppearance;
                    signatureAppearance.SetVisibleSignature("ExistSignatureName");
                    IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
                    signatureAppearance.Reason = "Sig";
                    signatureAppearance.Layer2Text = "Super SIG";

                    signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;

                    MakeSignature.SignExternalContainer(signatureAppearance, external, 8192);


                    using (var contentStream = signatureAppearance.GetRangeStream())
                    {
                        hash = string.Join(string.Empty, SHA1.Create().ComputeHash(contentStream).Select(x => x.ToString("X2")));
                    }
                }
            }
        }

    return hash;
}

第 2 步。

public void SigSignature(string base64String)
{
    using (var reader = new PdfReader("PathToTemp"))
    {
        using (var fileStream = File.OpenWrite("PathToSig"))
        {
            var byteSig = Convert.FromBase64String(base64String);
            IExternalSignatureContainer external = new MfuaExternalSignatureContainer(byteSig);

            MakeSignature.SignDeferred(reader, "ExistSignatureName", fileStream, external);
        }
    }
}

private class MfuaExternalSignatureContainer : IExternalSignatureContainer
{
    private readonly byte[] _signedBytes;

    public MfuaExternalSignatureContainer(byte[] signedBytes)
    {
        _signedBytes = signedBytes;
    }

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

    public void ModifySigningDictionary(PdfDictionary signDic)
    {
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    相关资源
    最近更新 更多