C# 使用itextSharp 5.3.3对Pdf文档进行数字签名和验证

C# 使用itextSharp 5.3.3对Pdf文档进行数字签名和验证,c#,pdf-generation,itextsharp,itext,digital-certificate,C#,Pdf Generation,Itextsharp,Itext,Digital Certificate,我正在尝试使用iTextSharp 5.3.3对服务器(c#)上的pdf文档进行数字签名和验证 我使用DigiSign(在线工具)生成了.Pfx文件,然后使用windows生成了证书(.cer)文件 // ///使用iTextSharp库签署PDF文档 /// ///要签名的源pdf文档的路径 ///生成已签名pdf文档的路径 ///包含.pfx格式的私钥/公钥的流,用于对文档进行签名 ///私钥的密码 ///描述签名原因的字符串将作为签名的一部分嵌入 ///签署文件的地点将作为签名的一部分嵌

我正在尝试使用iTextSharp 5.3.3对服务器(c#)上的pdf文档进行数字签名和验证

我使用DigiSign(在线工具)生成了.Pfx文件,然后使用windows生成了证书(.cer)文件

//
///使用iTextSharp库签署PDF文档
/// 
///要签名的源pdf文档的路径
///生成已签名pdf文档的路径
///包含.pfx格式的私钥/公钥的流,用于对文档进行签名
///私钥的密码
///描述签名原因的字符串将作为签名的一部分嵌入
///签署文件的地点将作为签名的一部分嵌入
public static void signPdfFile(字符串sourceDocument、字符串destinationPath、流privateKeyStream、字符串keyPassword、字符串原因、字符串位置)
{
Pkcs12Store pk12=新的Pkcs12Store(privateKeyStream,keyPassword.ToCharArray());
privateKeyStream.Dispose();
//然后遍历证书条目以查找私钥条目
字符串别名=null;
foreach(pk12.alias中的字符串tAlias)
{
if(pk12.IsKeyEntry(tAlias))
{
别名=塔利亚斯;
打破
}
}
var pk=pk12.GetKey(别名).Key;
//读卡器和压模
PdfReader reader=新PdfReader(源文档);
使用(FileStream fout=newfilestream(destinationPath,FileMode.Create,FileAccess.ReadWrite))
{
使用(PdfStamper stamper=PdfStamper.CreateSignature(读卡器,fout,'\0'))
{
//外表
PDFSignaturePearance外观=母版。SignaturePearance;
//appearance.Image=new iTextSharp.text.pdf.PdfImage();
外表。理性=理性;
外观。位置=位置;
外观.SetVisibleSignature(新的iTextSharp.text.矩形(20,10170,60),1,“Icsi供应商”);
//数字签名
IExternalSignature es=新私有密钥签名(pk,“SHA-256”);
MakeSignature.signDistached(外观,es,新X509Certificate[]{pk12.GetCertificate(别名).Certificate},null,null,null,0,CryptoStandard.CMS);
压模关闭();
}
}
}
文件签署后,我需要验证文件。我使用下面的代码,但得到错误

/// <summary>
/// Verifies the signature of a prevously signed PDF document using the specified public key
/// </summary>
/// <param name="pdfFile">a Previously signed pdf document</param>
/// <param name="publicKeyStream">Public key to be used to verify the signature in .cer format</param>
/// <exception cref="System.InvalidOperationException">Throw System.InvalidOperationException if the document is not signed or the signature could not be verified</exception>
public static void verifyPdfSignature (string pdfFile, Stream publicKeyStream)
{
    var parser=new X509CertificateParser();
    var certificate=parser.ReadCertificate(publicKeyStream);
    publicKeyStream.Dispose();

    PdfReader reader = new PdfReader(pdfFile);
    AcroFields af = reader.AcroFields;
    var names = af.GetSignatureNames();

    if (names.Count == 0)
    {
        throw new InvalidOperationException("No Signature present in pdf file.");
    }

    foreach (string name in names)
    {
        if (!af.SignatureCoversWholeDocument(name))
        {
            throw new InvalidOperationException(string.Format("The signature: {0} does not covers the whole document.", name));
        }

        PdfPKCS7 pk = af.VerifySignature(name);
        var cal = pk.SignDate;
        var pkc = pk.Certificates;

        if (!pk.Verify())
        {
            throw new InvalidOperationException("The signature could not be verified.");
        }
        if (!pk.VerifyTimestampImprint())
        {
            throw new InvalidOperationException("The signature timestamp could not be verified.");
        }

        IList<VerificationException>[] fails = CertificateVerification.VerifyCertificates(pkc, new X509Certificate[] { certificate }, null, cal);
        if (fails != null)
        {
            throw new InvalidOperationException("The file is not signed using the specified key-pair.");
        }
    }
}
//
///使用指定的公钥验证先前签名的PDF文档的签名
/// 
///先前签署的pdf文档
///用于验证.cer格式签名的公钥
///如果文档未签名或签名无法验证,则引发System.InvalidOperationException
public static void verifyPdfSignature(字符串pdfFile、流publicKeyStream)
{
var parser=new X509CertificateParser();
var certificate=parser.ReadCertificate(publicKeyStream);
publicKeyStream.Dispose();
PDF阅读器=新的PDF阅读器(pdfFile);
AcroFields af=reader.AcroFields;
var name=af.GetSignatureNames();
如果(names.Count==0)
{
抛出新的InvalidOperationException(“pdf文件中没有签名”);
}
foreach(名称中的字符串名称)
{
如果(!af.SignatureOverwholeDocument(名称))
{
抛出新的InvalidOperationException(string.Format(“签名:{0}不包括整个文档。”,name));
}
PdfPKCS7 pk=af.VerifySignature(名称);
var cal=pk.SignDate;
var pkc=pk.证书;
如果(!pk.Verify())
{
抛出新的InvalidOperationException(“无法验证签名”);
}
如果(!pk.verifytimestamprimp())
{
抛出新的InvalidOperationException(“无法验证签名时间戳”);
}
IList[]失败=CertificateVerification.VerifyCertificates(pkc,新X509Certificate[]{certificate},null,cal);
如果(失败!=null)
{
抛出新的InvalidOperationException(“文件未使用指定的密钥对签名”);
}
}
}
我在验证时遇到两个错误:

  • 一个位于(!pk.verifytimestamprimp())-->无法验证签名时间戳
  • 另一个位于CertificateVerification.VerifyCertificates-->NullReference错误

  • 非常感谢您在这方面提供的帮助。

    作为旁注:iTextSharp 5.3.3-如何更新到当前版本,即5.5.x?如果我没记错的话,5.3.x版本是iText签名API大更新的时候。因此,您可能会处理长期固定的故障。谢谢mkl..我已更改为5.5.0,工作正常..mkl..您可以检查这个问题吗。我找不到任何关于这个的信息。你能检查一下这个问题吗?我不了解iText(夏普)中非拉丁字体的细节,因此无法给出明确的答案。然而,据我所知,经常有人要求提供与此类字体的特殊性相关的功能,但几乎没有人愿意为此类开发付费或帮助开发该功能。因此,我怀疑你们正在寻找的功能目前是否已经实现。你们能分享DigiSign的网站吗?我还需要为文档签名创建一个pfx。我需要直接访问在线服务或任何SDK来帮助我创建pfx。它也可以是试用版。
    /// <summary>
    /// Verifies the signature of a prevously signed PDF document using the specified public key
    /// </summary>
    /// <param name="pdfFile">a Previously signed pdf document</param>
    /// <param name="publicKeyStream">Public key to be used to verify the signature in .cer format</param>
    /// <exception cref="System.InvalidOperationException">Throw System.InvalidOperationException if the document is not signed or the signature could not be verified</exception>
    public static void verifyPdfSignature (string pdfFile, Stream publicKeyStream)
    {
        var parser=new X509CertificateParser();
        var certificate=parser.ReadCertificate(publicKeyStream);
        publicKeyStream.Dispose();
    
        PdfReader reader = new PdfReader(pdfFile);
        AcroFields af = reader.AcroFields;
        var names = af.GetSignatureNames();
    
        if (names.Count == 0)
        {
            throw new InvalidOperationException("No Signature present in pdf file.");
        }
    
        foreach (string name in names)
        {
            if (!af.SignatureCoversWholeDocument(name))
            {
                throw new InvalidOperationException(string.Format("The signature: {0} does not covers the whole document.", name));
            }
    
            PdfPKCS7 pk = af.VerifySignature(name);
            var cal = pk.SignDate;
            var pkc = pk.Certificates;
    
            if (!pk.Verify())
            {
                throw new InvalidOperationException("The signature could not be verified.");
            }
            if (!pk.VerifyTimestampImprint())
            {
                throw new InvalidOperationException("The signature timestamp could not be verified.");
            }
    
            IList<VerificationException>[] fails = CertificateVerification.VerifyCertificates(pkc, new X509Certificate[] { certificate }, null, cal);
            if (fails != null)
            {
                throw new InvalidOperationException("The file is not signed using the specified key-pair.");
            }
        }
    }