C#下对PDF文件进行电子图片签名

版权声明:本文为starfd原创文章,转载请标明出处。 https://blog.csdn.net/starfd/article/details/79278321
能够对pdf进行图片签名的,网上找来找去,就一个iText是免费的,但这个免费是AGPL协议,当然它也有商业协议,iText现在有5和7两个版本,这里我采用的是版本5,nuget下载地址为:https://www.nuget.org/packages/iTextSharp/,然后为了多做比较,我这里还找了Spire.PDF进行测试,其免费版本Free.Spire.PDF还是3.2版本,而其收费版本目前为4.2版本,这里先直接说测试结果,免费版本可以进行数字签名,但图片签名不行,只要将图片赋给对应参数,保存时必定报转化异常,而4.2版本代码与3.2的相比需要稍作调整(只是建议性质,不调整也能运行),可以成功保存,另外收费版本的我还找了PDF-Writer,因为它的例子本身就包含了图片签名部分,所以这里不做描述,以下是iText和Spire代码:
    using iTextSharp.text.pdf.security;
    using Org.BouncyCastle.Pkcs;//这是itext自带的,不需要单独添加BouncyCastle包
    using System.Drawing;

    public class PdfDigstSign
    {
        static string pfxPath = "001180530510644.pfx";
        static string pfxPwd = "111111";
        static string sourcePdf = "template.pdf";
        static string imgPath = "password_1.png";
        public static void PDFSignWithIText5Demo()
        {
            string outPutPdf = "ImageStampWithIText5.pdf";
            var reader = new iTextSharp.text.pdf.PdfReader(sourcePdf);
            using (FileStream fs = new FileStream(outPutPdf, FileMode.Create))
            {
                var stamper = iTextSharp.text.pdf.PdfStamper.CreateSignature(reader, fs, '\0', null, true);
                var appearance = stamper.SignatureAppearance;
                appearance.Reason = "签名测试原因";
                appearance.Location = "签名位置";
                appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(200, 200, 300, 300), 1, "itext");
                //itext会自动对图片进行等比例缩放
                appearance.SignatureGraphic = iTextSharp.text.Image.GetInstance(imgPath);
                appearance.CertificationLevel = iTextSharp.text.pdf.PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED;
                appearance.SignatureRenderingMode = iTextSharp.text.pdf.PdfSignatureAppearance.RenderingMode.GRAPHIC;


                using (var stream = File.OpenRead(pfxPath))
                {
                    Pkcs12Store store = new Pkcs12Store(stream, pfxPwd.ToCharArray());
                    string keyAlias = null;
                    foreach (string alias in store.Aliases)
                    {
                        keyAlias = alias;
                        break;
                    }
                    var chains = store.GetCertificateChain(keyAlias).Select(c => c.Certificate).ToList();
                    var signature = new PrivateKeySignature(store.GetKey(keyAlias).Key, DigestAlgorithms.SHA1);
                    MakeSignature.SignDetached(appearance, signature, chains, null, null, null, 0, CryptoStandard.CADES);
                }
            }
        }
        public static void PDFSignWithSpirePDF4_2Demo()
        {
            //必须要商业版才行
            var doc = new Spire.Pdf.PdfDocument();
            doc.LoadFromFile(sourcePdf);
            var page = doc.Pages[0];

            var cert = new Spire.Pdf.Security.PdfCertificate(pfxPath, pfxPwd);
            var signature = new Spire.Pdf.Security.PdfSignature(doc, page, cert, "spire");
            //
            var loApprearance = signature.Appearence;
            var image = Spire.Pdf.Graphics.PdfImage.FromFile(imgPath);
            var template = new Spire.Pdf.Graphics.PdfTemplate(image.Width, image.Height);
            template.Graphics.DrawImage(image, 0, 0,100,100);//spire由代码指定缩放
            loApprearance.Normal = template;
            signature.Bounds = new RectangleF(new PointF(100, 100), new SizeF(100, 100));
            signature.Reason = "签名原因";
            signature.LocationInfo = "签名位置";
            signature.GraphicsMode = Spire.Pdf.Security.GraphicMode.SignNameOnly;
            signature.DocumentPermissions = Spire.Pdf.Security.PdfCertificationFlags.ForbidChanges;
            string output = "ImageStampWithSpirePDF4_2.pdf";
            doc.SaveToFile(output);
        }
    }

上述代码运行完后,两者的签名面板部分稍有不同,具体如下:


之所以生成的略有差异,主要是方法参数不同,在iText中,将PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED修改为PdfSignatureAppearance.NOT_CERTIFIED,两者将显示一致

2018-04-11补充

Spire.Pdf低商业版本(3.x版本)图片签名有bug,只能通过ConfiguerGraphicPath属性指定图片的物理地址来进行图片签名,但这样就不能利用上面例子中template可以为图片指定压缩比来减小PDF大小的好处,所以折中的方式是设置签名方式为如下方式

signature.DigitalSigner = "";
signature.ConfigGraphicType = ConfiguerGraphicType.Text;

利用空字符串来间接的达到只输出显示图片的效果

另外补充 Spire.Pdf免费版不能进行并发操作,商业版才可以


猜你喜欢

转载自blog.csdn.net/starfd/article/details/79278321