C# ITextSharp SetVisibleSignature未按预期工作
因此,我一直在使用IText的Java实现,但现在我正在编写一个签名过程到C#的端口,我遇到了一个障碍。因此,当我使用SetVisibleSignature(rect、page、name)重载对文档进行签名时,它会按预期对文档进行签名(只要签名字段不存在),但当我使用重载SetVisibleSignature(name)对现有字段进行签名时,它实际上不会对文档进行签名。我是在做一些愚蠢的事情,还是错过了什么 谢谢你的帮助 更新代码C# ITextSharp SetVisibleSignature未按预期工作,c#,pdf,itextsharp,signing,C#,Pdf,Itextsharp,Signing,因此,我一直在使用IText的Java实现,但现在我正在编写一个签名过程到C#的端口,我遇到了一个障碍。因此,当我使用SetVisibleSignature(rect、page、name)重载对文档进行签名时,它会按预期对文档进行签名(只要签名字段不存在),但当我使用重载SetVisibleSignature(name)对现有字段进行签名时,它实际上不会对文档进行签名。我是在做一些愚蠢的事情,还是错过了什么 谢谢你的帮助 更新代码 using iTextSharp.text; using
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using BouncyCastle = Org.BouncyCastle;
public class DocumentSigner : IDocumentSigner
{
private const string _datetimeFormat = "dd/MM/yyyy hh:mm:ss";
private readonly IDateTimeProvider _dateTimeProvider;
private readonly ISettingManager _settingManager;
public DocumentSigner(IDateTimeProvider dateTimeProvider, ISettingManager settingManager)
{
Guard.ArgumentNotNull(dateTimeProvider, "dateTimeProvider");
Guard.ArgumentNotNull(settingManager, "settingManager");
_dateTimeProvider = dateTimeProvider;
_settingManager = settingManager;
}
public byte[] Sign(Certificate certificate, SigningInformation information, List<SigningBlock> signingBlocks, List<MemberItemSignature> signatureImages, byte[] document, bool certify)
{
document = AddMetaData(information, document);
document = AddSignatureFields(information, signingBlocks, document);
return SignDocument(certificate, information, signingBlocks, signatureImages, document, certify);
}
private byte[] AddMetaData(SigningInformation information, byte[] document)
{
if (information.CustomProperties != null && information.CustomProperties.Any())
{
using (MemoryStream outputStream = new MemoryStream())
{
using (PdfReader reader = new PdfReader(document))
{
using (PdfStamper stamper = new PdfStamper(reader, outputStream, '\0', true))
{
Dictionary<string, string> currentProperties = reader.Info;
foreach (string key in information.CustomProperties.Keys)
{
if (currentProperties.ContainsKey(key))
{
currentProperties[key] = information.CustomProperties[key];
}
else
{
currentProperties.Add(key, information.CustomProperties[key]);
}
}
stamper.MoreInfo = currentProperties;
}
}
return outputStream.ToArray();
}
}
return document;
}
private byte[] AddSignatureFields(SigningInformation information, List<SigningBlock> signingBlocks, byte[] document)
{
for (int i = 0; i < signingBlocks.Count; i++)
{
using (MemoryStream outputStream = new MemoryStream())
{
using (PdfReader reader = new PdfReader(document))
{
using (PdfStamper stamper = new PdfStamper(reader, outputStream, '\0', true))
{
CreateSignatureField(reader, stamper, signingBlocks[i]);
}
}
document = outputStream.ToArray();
}
}
return document;
}
private PdfSignatureAppearance CreatePdfAppearance(PdfStamper stamper, SigningInformation information, bool certify)
{
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Location = information.Location;
appearance.Reason = information.Purpose;
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
CreatePdfAppearanceCertifyDocument(appearance, certify);
return appearance;
}
private void CreatePdfAppearanceCertifyDocument(PdfSignatureAppearance appearance, bool certify)
{
if (certify)
{
appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING;
}
else
{
appearance.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
}
}
private PdfStamper CreatePdfStamper(PdfReader reader, MemoryStream outputStream, byte[] document)
{
return PdfStamper.CreateSignature(reader, outputStream, '\0', null, true);
}
private void CreateSignatureField(PdfReader reader, PdfStamper stamper, SigningBlock signingBlock)
{
if (signingBlock == null)
{
return;
}
if (!DoesSignatureFieldExist(reader, signingBlock.Name))
{
PdfFormField signatureField = PdfFormField.CreateSignature(stamper.Writer);
signatureField.SetWidget(new Rectangle(signingBlock.X, signingBlock.Y, signingBlock.X + signingBlock.Width, signingBlock.Y + signingBlock.Height), null);
signatureField.Flags = PdfAnnotation.FLAGS_PRINT;
signatureField.FieldName = signingBlock.Name;
signatureField.Page = signingBlock.Page;
stamper.AddAnnotation(signatureField, signingBlock.Page);
}
}
private bool DoesSignatureFieldExist(PdfReader reader, string signatureFieldName)
{
if (String.IsNullOrWhiteSpace(signatureFieldName))
{
return false;
}
return reader.AcroFields.DoesSignatureFieldExist(signatureFieldName);
}
private byte[] GetSignatureImage(List<MemberItemSignature> signatureImages, string signingBlockName)
{
MemberItemSignature signature = signingBlockName.Contains("Initial") ? signatureImages.Where(image => image.Use == SignatureUses.Initial).FirstOrDefault() : signatureImages.Where(image => image.Use == SignatureUses.Signature).FirstOrDefault();
if (signature != null)
{
return signature.Image;
}
else
{
return null;
}
}
private byte[] SignDocument(Certificate certificate, SigningInformation information, List<SigningBlock> signingBlocks, List<MemberItemSignature> signatureImages, byte[] document, bool certify)
{
for (int i = 0; i < signingBlocks.Count; i++)
{
using (MemoryStream outputStream = new MemoryStream())
{
using (PdfReader reader = new PdfReader(document))
{
using (PdfStamper stamper = CreatePdfStamper(reader, outputStream, document))
{
SigningBlock signingBlock = signingBlocks[i];
PdfSignatureAppearance appearance = CreatePdfAppearance(stamper, information, certify && i == 0);
SignDocumentSigningBlock(certificate, information, signingBlock, appearance, stamper, GetSignatureImage(signatureImages, signingBlock.Name));
}
}
document = outputStream.ToArray();
}
}
return document;
}
private void SignDocumentSigningBlock(Certificate certificate, SigningInformation information, SigningBlock block, PdfSignatureAppearance appearance, PdfStamper stamper, byte[] signatureImage)
{
X509Certificate2 x509Certificate = new X509Certificate2(certificate.Bytes, certificate.Password, X509KeyStorageFlags.Exportable);
appearance.SetVisibleSignature(block.Name);
SignDocumentSigningBlockWithImage(signatureImage, appearance);
SignDocumentSigningBlockWithText(appearance, x509Certificate);
using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)x509Certificate.PrivateKey)
{
IExternalSignature externalSignature = new PrivateKeySignature(DotNetUtilities.GetRsaKeyPair(rsa).Private, _settingManager["DocumentSigningEncryptionHashAlgorithm"]);
MakeSignature.SignDetached(appearance, externalSignature, new BouncyCastle::X509.X509Certificate[] { DotNetUtilities.FromX509Certificate(x509Certificate) }, null, null, new TSAClientBouncyCastle(_settingManager["DocumentSigningTimestampingServiceAddress"]), Int32.Parse(_settingManager["DocumentSigningEstimatedTimestampSize"]), CryptoStandard.CMS);
}
}
private void SignDocumentSigningBlockWithImage(byte[] signatureImage, PdfSignatureAppearance appearance)
{
if (signatureImage != null && signatureImage.Length > 0)
{
Image signatureImageInstance = Image.GetInstance(signatureImage);
appearance.Image = signatureImageInstance;
appearance.SignatureGraphic = signatureImageInstance;
}
}
private void SignDocumentSigningBlockWithText(PdfSignatureAppearance appearance, X509Certificate2 x509Certificate)
{
if (x509Certificate == null)
{
return;
}
appearance.Layer2Text = SignDocumentSigningBlockWithTextBuildText(x509Certificate);
appearance.Layer2Font = new Font(Font.FontFamily.COURIER, 7.0f, Font.NORMAL, BaseColor.LIGHT_GRAY);
appearance.Acro6Layers = true;
}
private string SignDocumentSigningBlockWithTextBuildText(X509Certificate2 x509Certificate)
{
Dictionary<string, string> fields = SignDocumentSigningBlockWithTextBuildTextIssuerFields(x509Certificate.IssuerName.Name);
string organization = fields.Keys.Contains("O") ? fields["O"] : String.Empty;
string commonName = fields.Keys.Contains("CN") ? fields["CN"] : String.Empty;
string signDate = _dateTimeProvider.Now.ToString(_datetimeFormat);
string expirationDate = x509Certificate.NotAfter.ToString(_datetimeFormat);
return "Digitally signed by " + organization + "\nSignee: " + commonName + "\nSign date: " + signDate + "\n" + "Expiration date: " + expirationDate;
}
private Dictionary<string, string> SignDocumentSigningBlockWithTextBuildTextIssuerFields(string issuer)
{
Dictionary<string, string> fields = new Dictionary<string, string>();
string[] issuerFields = issuer.Split(',');
foreach (string field in issuerFields)
{
string[] fieldSplit = field.Split('=');
string key = fieldSplit[0].Trim();
string value = fieldSplit[1].Trim();
if (!fields.Keys.Contains(key))
{
fields.Add(key, value);
}
else
{
fields[key] = value;
}
}
return fields;
}
}
OP提供的代码引用并访问未知类的多个对象。因此,为了使它能够运行,它必须被削减到自给自足的程度
幸运的是,精简版仍然可以用于重现和分析问题,参见后脚本。从这里开始的任何声明都基于此精简版本的行为
OP观察到的问题可以使用iTextSharp 5.5.7复制(并类似地使用iText 5.5.7),而且非常有趣的是,这两个库的版本5.5.6都无法复制。随着我对Java的深入,我研究了iText中的变化。他们以一种非常忠实的方式被移植到iTextSharp
事实上,这个问题是一个回归,在附加模式下对预先存在的空签名字段进行签名在iText(Sharp)5.5.7中被破坏
在5.5.6和5.5.7之间,PdfSignatureAppearance.preClose
进行了更改。如果对现有签名字段进行签名,则用于操作相关签名字段的第一个小部件的代码(af.getFieldItem(name).getWidget(0)
),现在它可以在关联的合并字典上工作(af.getFieldItem(name).getMerged(0)
)
不幸的是,虽然前者是原始PDF中实际存在的对象,因此调用writer.markUsed
,因为它标记了更改的内容以写入增量更新节,但后者与原始PDF中的对象不对应(它是多个对象的虚拟聚合),因此,调用writer.markUsed
,因为它不再将要写入的更改标记为增量更新
因此,虽然实际签名值仍然写入文件,但它不再连接到指定的签名字段
已完成更改以修复方法行为 在此之前,
preClosed
工作不正确,因为它检索字段字典作为小部件注释。如果字段和小部件dict未合并,则该选项不正确。万一他们合并了,一切都如期进行。后者是数字签名字段最可能的情况,但根据规范它没有义务
(DEV-1448)
这是正确的,对于单独的字段和小部件字典,必须对字段而不是小部件进行某些更改。只是在append模式下,实现不能按预期工作
PS:这是OP代码的精简版本:
public class DocumentSigner
{
private const string _datetimeFormat = "dd/MM/yyyy hh:mm:ss";
public byte[] Sign(ICollection<X509Certificate> chain, ICipherParameters pk, string signingBlock, byte[] document, bool certify, String pattern = null)
{
document = AddMetaData(document);
if (pattern != null)
File.WriteAllBytes(String.Format(pattern, "1"), document);
document = AddSignatureFields(signingBlock, document);
if (pattern != null)
File.WriteAllBytes(String.Format(pattern, "2"), document);
return SignDocument(chain, pk, signingBlock, document, certify);
}
private byte[] AddMetaData(byte[] document)
{
return document;
}
private byte[] AddSignatureFields(string signingBlock, byte[] document)
{
using (MemoryStream outputStream = new MemoryStream())
{
using (PdfReader reader = new PdfReader(document))
{
using (PdfStamper stamper = new PdfStamper(reader, outputStream, '\0', true))
{
CreateSignatureField(reader, stamper, signingBlock);
}
}
document = outputStream.ToArray();
}
return document;
}
private PdfSignatureAppearance CreatePdfAppearance(PdfStamper stamper, bool certify)
{
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Location = "information.Location";
appearance.Reason = "information.Purpose";
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
CreatePdfAppearanceCertifyDocument(appearance, certify);
return appearance;
}
private void CreatePdfAppearanceCertifyDocument(PdfSignatureAppearance appearance, bool certify)
{
if (certify)
{
appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING;
}
else
{
appearance.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
}
}
private PdfStamper CreatePdfStamper(PdfReader reader, MemoryStream outputStream, byte[] document)
{
return PdfStamper.CreateSignature(reader, outputStream, '\0', null, true);
}
private void CreateSignatureField(PdfReader reader, PdfStamper stamper, string signingBlock)
{
if (signingBlock == null)
{
return;
}
if (!DoesSignatureFieldExist(reader, signingBlock))
{
PdfFormField signatureField = PdfFormField.CreateSignature(stamper.Writer);
signatureField.SetWidget(new Rectangle(100, 100, 200, 200), null);
signatureField.Flags = PdfAnnotation.FLAGS_PRINT;
signatureField.FieldName = signingBlock;
signatureField.Page = 1;
stamper.AddAnnotation(signatureField, 1);
}
}
private bool DoesSignatureFieldExist(PdfReader reader, string signatureFieldName)
{
if (String.IsNullOrWhiteSpace(signatureFieldName))
{
return false;
}
return reader.AcroFields.DoesSignatureFieldExist(signatureFieldName);
}
private byte[] GetSignatureImage(string signingBlockName)
{
return null;
}
private byte[] SignDocument(ICollection<X509Certificate> chain, ICipherParameters pk, string signingBlock, byte[] document, bool certify)
{
using (MemoryStream outputStream = new MemoryStream())
{
using (PdfReader reader = new PdfReader(document))
{
using (PdfStamper stamper = CreatePdfStamper(reader, outputStream, document))
{
PdfSignatureAppearance appearance = CreatePdfAppearance(stamper, certify);
SignDocumentSigningBlock(chain, pk, signingBlock, appearance, stamper, GetSignatureImage(signingBlock));
}
}
document = outputStream.ToArray();
}
return document;
}
private void SignDocumentSigningBlock(ICollection<X509Certificate> chain, ICipherParameters pk, string block, PdfSignatureAppearance appearance, PdfStamper stamper, byte[] signatureImage)
{
appearance.SetVisibleSignature(block);
SignDocumentSigningBlockWithImage(signatureImage, appearance);
SignDocumentSigningBlockWithText(appearance, chain.First());
IExternalSignature externalSignature = new PrivateKeySignature(pk, "SHA-256");
MakeSignature.SignDetached(appearance, externalSignature, chain, null, null, new TSAClientBouncyCastle("http://services.globaltrustfinder.com/adss/tsa"), 104000, CryptoStandard.CMS);
}
private void SignDocumentSigningBlockWithImage(byte[] signatureImage, PdfSignatureAppearance appearance)
{
if (signatureImage != null && signatureImage.Length > 0)
{
Image signatureImageInstance = Image.GetInstance(signatureImage);
appearance.Image = signatureImageInstance;
appearance.SignatureGraphic = signatureImageInstance;
}
}
private void SignDocumentSigningBlockWithText(PdfSignatureAppearance appearance, X509Certificate x509Certificate)
{
if (x509Certificate == null)
{
return;
}
appearance.Layer2Text = SignDocumentSigningBlockWithTextBuildText(x509Certificate);
appearance.Layer2Font = new Font(Font.FontFamily.COURIER, 7.0f, Font.NORMAL, BaseColor.LIGHT_GRAY);
appearance.Acro6Layers = true;
}
private string SignDocumentSigningBlockWithTextBuildText(X509Certificate x509Certificate)
{
Dictionary<string, string> fields = SignDocumentSigningBlockWithTextBuildTextIssuerFields(x509Certificate.IssuerDN.ToString());
string organization = fields.Keys.Contains("O") ? fields["O"] : String.Empty;
string commonName = fields.Keys.Contains("CN") ? fields["CN"] : String.Empty;
string signDate = System.DateTime.Now.ToString(_datetimeFormat);
string expirationDate = x509Certificate.NotAfter.ToString();
return "Digitally signed by " + organization + "\nSignee: " + commonName + "\nSign date: " + signDate + "\n" + "Expiration date: " + expirationDate;
}
private Dictionary<string, string> SignDocumentSigningBlockWithTextBuildTextIssuerFields(string issuer)
{
Dictionary<string, string> fields = new Dictionary<string, string>();
string[] issuerFields = issuer.Split(',');
foreach (string field in issuerFields)
{
string[] fieldSplit = field.Split('=');
string key = fieldSplit[0].Trim();
string value = fieldSplit[1].Trim();
if (!fields.Keys.Contains(key))
{
fields.Add(key, value);
}
else
{
fields[key] = value;
}
}
return fields;
}
}
公共类文档签名器
{
私有常量字符串_datetimeFormat=“dd/MM/yyyy hh:MM:ss”;
公共字节[]符号(ICollection链,ICipherParameters pk,字符串签名块,字节[]文档,bool certifite,字符串模式=null)
{
文档=添加元数据(文档);
if(模式!=null)
File.writealBytes(String.Format(模式,“1”),文档);
文件=添加签名字段(签名块、文件);
if(模式!=null)
File.writealBytes(String.Format(模式,“2”),文档);
返回签名文件(链、主键、签名块、文件、证明);
}
专用字节[]添加元数据(字节[]文档)
{
归还文件;
}
专用字节[]AddSignatureFields(字符串签名块,字节[]文档)
{
使用(MemoryStream outputStream=new MemoryStream())
{
使用(PDF阅读器=新PDF阅读器(文档))
{
使用(PdfStamper压模=新的PdfStamper(读卡器,输出流,'\0',真))
{
CreateSignatureField(读卡器、压模、签名块);
}
}
document=outputStream.ToArray();
}
归还文件;
}
私人PDFSignaturePearance CreatePDFaAppearance(PdfStamper压模,bool认证)
{
PDFSignaturePearance外观=母版。SignaturePearance;
外观.Location=“信息.Location”;
外观.Reason=“信息.目的”;
外观.SignatureRenderingMode=PdfSignatureAppearance.RenderingMode.DESCRIPTION;
CreatePDFaAppearanceCertifyDocument(外观、认证);
返回外观;
}
私有无效CreatePDFaAppearanceCertifyDocument(PdfSignatureAppearance外观,bool certify)
{
如果(证明)
{
外观.CertificationLevel=PdfSignatureAppearance.CERTIFIED\u表格\u填写;
}
其他的
{
appearance.CertificationLevel=PdfSignatureAppearance.NOT_CERTIFIED;
}
}
专用PdfStamper CreatePdfStamper(PdfReader读取器、MemoryStream outputStream、byte[]文档)
{
返回PdfStamper.CreateSignature(读取器,outputStream,'\0',null,true);
}
私有void CreateSignatureField(PDF读卡器、PdfStamper压模、字符串签名块)
{
if(signingBlock==null)
{
返回;
}
如果(!DoesSignatureFieldExist(读卡器、签名块))
{
PdfFormField signatureField=PdfFormField.CreateSignature(stamper.Writer);
SetWidget(新矩形(100100200200),null);
signatureField.Flags=PdfAnnotation.Flags\u打印;
签名纸
public class DocumentSigner
{
private const string _datetimeFormat = "dd/MM/yyyy hh:mm:ss";
public byte[] Sign(ICollection<X509Certificate> chain, ICipherParameters pk, string signingBlock, byte[] document, bool certify, String pattern = null)
{
document = AddMetaData(document);
if (pattern != null)
File.WriteAllBytes(String.Format(pattern, "1"), document);
document = AddSignatureFields(signingBlock, document);
if (pattern != null)
File.WriteAllBytes(String.Format(pattern, "2"), document);
return SignDocument(chain, pk, signingBlock, document, certify);
}
private byte[] AddMetaData(byte[] document)
{
return document;
}
private byte[] AddSignatureFields(string signingBlock, byte[] document)
{
using (MemoryStream outputStream = new MemoryStream())
{
using (PdfReader reader = new PdfReader(document))
{
using (PdfStamper stamper = new PdfStamper(reader, outputStream, '\0', true))
{
CreateSignatureField(reader, stamper, signingBlock);
}
}
document = outputStream.ToArray();
}
return document;
}
private PdfSignatureAppearance CreatePdfAppearance(PdfStamper stamper, bool certify)
{
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Location = "information.Location";
appearance.Reason = "information.Purpose";
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
CreatePdfAppearanceCertifyDocument(appearance, certify);
return appearance;
}
private void CreatePdfAppearanceCertifyDocument(PdfSignatureAppearance appearance, bool certify)
{
if (certify)
{
appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING;
}
else
{
appearance.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
}
}
private PdfStamper CreatePdfStamper(PdfReader reader, MemoryStream outputStream, byte[] document)
{
return PdfStamper.CreateSignature(reader, outputStream, '\0', null, true);
}
private void CreateSignatureField(PdfReader reader, PdfStamper stamper, string signingBlock)
{
if (signingBlock == null)
{
return;
}
if (!DoesSignatureFieldExist(reader, signingBlock))
{
PdfFormField signatureField = PdfFormField.CreateSignature(stamper.Writer);
signatureField.SetWidget(new Rectangle(100, 100, 200, 200), null);
signatureField.Flags = PdfAnnotation.FLAGS_PRINT;
signatureField.FieldName = signingBlock;
signatureField.Page = 1;
stamper.AddAnnotation(signatureField, 1);
}
}
private bool DoesSignatureFieldExist(PdfReader reader, string signatureFieldName)
{
if (String.IsNullOrWhiteSpace(signatureFieldName))
{
return false;
}
return reader.AcroFields.DoesSignatureFieldExist(signatureFieldName);
}
private byte[] GetSignatureImage(string signingBlockName)
{
return null;
}
private byte[] SignDocument(ICollection<X509Certificate> chain, ICipherParameters pk, string signingBlock, byte[] document, bool certify)
{
using (MemoryStream outputStream = new MemoryStream())
{
using (PdfReader reader = new PdfReader(document))
{
using (PdfStamper stamper = CreatePdfStamper(reader, outputStream, document))
{
PdfSignatureAppearance appearance = CreatePdfAppearance(stamper, certify);
SignDocumentSigningBlock(chain, pk, signingBlock, appearance, stamper, GetSignatureImage(signingBlock));
}
}
document = outputStream.ToArray();
}
return document;
}
private void SignDocumentSigningBlock(ICollection<X509Certificate> chain, ICipherParameters pk, string block, PdfSignatureAppearance appearance, PdfStamper stamper, byte[] signatureImage)
{
appearance.SetVisibleSignature(block);
SignDocumentSigningBlockWithImage(signatureImage, appearance);
SignDocumentSigningBlockWithText(appearance, chain.First());
IExternalSignature externalSignature = new PrivateKeySignature(pk, "SHA-256");
MakeSignature.SignDetached(appearance, externalSignature, chain, null, null, new TSAClientBouncyCastle("http://services.globaltrustfinder.com/adss/tsa"), 104000, CryptoStandard.CMS);
}
private void SignDocumentSigningBlockWithImage(byte[] signatureImage, PdfSignatureAppearance appearance)
{
if (signatureImage != null && signatureImage.Length > 0)
{
Image signatureImageInstance = Image.GetInstance(signatureImage);
appearance.Image = signatureImageInstance;
appearance.SignatureGraphic = signatureImageInstance;
}
}
private void SignDocumentSigningBlockWithText(PdfSignatureAppearance appearance, X509Certificate x509Certificate)
{
if (x509Certificate == null)
{
return;
}
appearance.Layer2Text = SignDocumentSigningBlockWithTextBuildText(x509Certificate);
appearance.Layer2Font = new Font(Font.FontFamily.COURIER, 7.0f, Font.NORMAL, BaseColor.LIGHT_GRAY);
appearance.Acro6Layers = true;
}
private string SignDocumentSigningBlockWithTextBuildText(X509Certificate x509Certificate)
{
Dictionary<string, string> fields = SignDocumentSigningBlockWithTextBuildTextIssuerFields(x509Certificate.IssuerDN.ToString());
string organization = fields.Keys.Contains("O") ? fields["O"] : String.Empty;
string commonName = fields.Keys.Contains("CN") ? fields["CN"] : String.Empty;
string signDate = System.DateTime.Now.ToString(_datetimeFormat);
string expirationDate = x509Certificate.NotAfter.ToString();
return "Digitally signed by " + organization + "\nSignee: " + commonName + "\nSign date: " + signDate + "\n" + "Expiration date: " + expirationDate;
}
private Dictionary<string, string> SignDocumentSigningBlockWithTextBuildTextIssuerFields(string issuer)
{
Dictionary<string, string> fields = new Dictionary<string, string>();
string[] issuerFields = issuer.Split(',');
foreach (string field in issuerFields)
{
string[] fieldSplit = field.Split('=');
string key = fieldSplit[0].Trim();
string value = fieldSplit[1].Trim();
if (!fields.Keys.Contains(key))
{
fields.Add(key, value);
}
else
{
fields[key] = value;
}
}
return fields;
}
}