这是一个我很难解决的问题。我们希望我们的供应商能够使用LTV签名签署PDF文档,以便文档的有效性不会过期。我读过Bruno Lowagie的书 iText in Action (第2版),他的白皮书 PDF文档的数字签名,并查看了PAdES个人资料文档(PDF文档的数字签名)
用户使用带有电子ID的手机签署文件。该程序基本上将哈希发送给签署它的第三方服务并发回给我们,我们使用该签名并将其放在PDF文件中。这样做很好,但这个签名只有三年左右有效。
我们收到并添加签名后,如何在PDF中添加DSS和时间戳,以使PDF符合使用iText的PAdES LTV-Profile。我已经看到很多添加签名,添加时间戳和OSCP信息的例子,但这并不完全相同。
以下是一些代码,它们以preSign和postSign方法开头,展示了我们正在做的事情。这有效,但如果可能的话,我在何处以及如何添加代码以添加DSS和时间戳信息:
/// <summary>
/// Creates signature infrastructure to use in the signing process. Start with calling this method in the signature process.
/// </summary>
/// <param name="inStream">Byte stream with the PDF document to be signed</param>
/// <param name="reason">The reason for the signing</param>
/// <param name="location">Signing location</param>
/// <returns>Returns a hash of the signed data</returns>
public void preSign(byte[] inStream, string reason, string location)
{
iTextSharp.text.Document document = new iTextSharp.text.Document();
// Lesum inn PDF skjalið sem á að undirrita inn í iText reader
PdfReader reader = new PdfReader(inStream);
reader.Appendable = true;
Rectangle pageSize = reader.GetPageSizeWithRotation(1);
// Tengjum output stream við iText stamper
_outstream = new MemoryStream();
PdfStamper stamper = PdfStamper.CreateSignature(reader, _outstream, '\0', null, true);
stamper.InsertPage(reader.NumberOfPages + 1, reader.GetPageSize(reader.NumberOfPages));
_sap = stamper.SignatureAppearance;
float llx = pageSize.Width/2 - 350/2;
float lly = pageSize.Height/2 - 150/2;
float urx = llx + 350;
float ury = lly + 150;
_sap.SetVisibleSignature(new iTextSharp.text.Rectangle(llx, lly, urx, ury), reader.NumberOfPages, null);
_sap.Reason = reason;
_sap.Location = location;
_transactionTime = DateTime.Now;
_sap.SignDate = _transactionTime;
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(AppDomain.CurrentDomain.BaseDirectory + "UndirskriftDemo.png");
img.ScaleToFit(new Rectangle(350, 50));
_sap.Image = img;
_sap.Layer2Font = new iTextSharp.text.Font(iTextSharp.text.Font.FontFamily.TIMES_ROMAN, 10.0f, 0, iTextSharp.text.BaseColor.BLACK);
_sap.Layer2Text = _userFullName + " undirritaði skjalið\nmeð rafrænum hætti \nþann " + _transactionTime.ToString("dd.MM.yyyy") + "\nStaður: " + location;
_sap.LocationCaption = "Location caption";
_sap.Contact = "Contact";
_sap.ReasonCaption = "ReasonCaption";
_sap.Layer4Text = "Layer 4 text";
// Create signature infrastructure
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.Reason = _sap.Reason;
dic.Location = _sap.Location;
dic.Contact = _sap.Contact;
dic.Date = new PdfDate(_sap.SignDate);
_sap.CryptoDictionary = dic;
Dictionary<PdfName, int> exc = new Dictionary<PdfName, int>();
exc.Add(PdfName.CONTENTS, (15000 * 2) + 2); // TSA: Content estimated er 15000 í stað 8192
//string tsa_url = ConfigurationManager.AppSettings["TSA_Url"];
//TSAClientBouncyCastle tsc = new TSAClientBouncyCastle(tsa_url);
//LtvTimestamp.Timestamp(_sap, tsc, null); // This can not be called here as then an exception will be thrown.
_sap.PreClose(exc);
Stream data = _sap.GetRangeStream();
_hash = DigestAlgorithms.Digest(data, DigestAlgorithms.SHA1);
}
然后postSign:
public void PostSign(byte[] signatureData)
{
PdfSignatureAppearance sap = _sap;
byte[] paddedSig = new byte[15000];
System.Array.Copy(signatureData, 0, paddedSig, 0, signatureData.Length);
PdfDictionary dic = new PdfDictionary();
dic.Put(PdfName.CONTENTS, new PdfString(paddedSig).SetHexWriting(true));
sap.Close(dic);
}
这些方法就像这样调用:
// Sign the document
SignatureHelper signatureHelper = new SignatureHelper(itemID, employeeItemID, oUser.UserName, oUser.FullName);
signatureHelper.preSign(pdfBytes, "Undirritun til að staðfesta uppruna", "Reykjavík");
byte[] signatureData = signatureHelper.SignFile(pdfBytes, phoneNumber, itemID);
signatureHelper.PostSign(signatureData);
ro.ByteStream = signatureHelper.OutStream;