Hello,
In case you want to create new PDF digital signature annotations, this
can be done using pdfdoc.FiledCreate("mysig",
Field.FieldType.e_signature). To manipulate digital signatures,
including custom metadata, you could use Cos/SDF API. Digital
signature fields can be accessed like other 'widget' annotation types
(e.g. using pdfdoc.GetFieldIterator()).
If the field has e_signature type, you can access its Cos/SDF
dictionary using GetSDFObj() method.
For example,
//C#
field = pdfdoc.FieldFind("MySig");
...
pdftron.SDF.Obj form_dict = field.GetSDFObj(); // get signature value
DictIterator itr = Obj dig_sig = form_dict.FindObj("V");
if (itr != null) {
// Access any key/value pair...
// See Section 8.7 'Digital Signatures' in PDF Reference Manual.
Obj sub = dig_sig.FindObj("SubFilter");
if (sub != null) {
}
// ...
xsig = dig_sig.FindObj("XSigner"); // get a custom property
if (xsig != null) {
dig_sig.PutString("XSigner", "foo@bar.com");
}
// ...
}
Or to traverse all digital signatures in the document:
//C#
FieldIterator itr = doc.GetFieldIterator();
for( ; itr.HasNext(); itr.Next()){
Field field = itr.Current();
Console.WriteLine("Field name: {0}", field.GetName());
Field.FieldType type = field.GetType();
if (type == Field.FieldType.e_signature) {
Obj field_dict = field.GetSDFObj();
// Perform COS/SDF read/write/edit operations on
// the signature dictionary.
}
}
PDF Reference Manual documents parameters in digital signature
dictionary in Sections '12.7.4.5 Signature Fields' and 12.8.
Also the following is sample code snippet that may help you with your
own document signing function. I tried to extract the logic from an
internal project, but it is far from a ready solution. Btw. as part of
the next update PDFNet will include a set of high-level APIs for
digital singature creation + validation so you will not need to write
much code (unless you need something very specific/low-level)
private void SignPDFSketch()
{
PDFDoc doc = _documentViewer.GetDoc();
Field sigField = doc.FieldCreate("Signature2",
Field.Type.e_signature);
Obj field1 = sigField.GetSDFObj();
field1.PutString("DA", "/MyriadPro-Regular 0 Tf 0 Tz 0 g");
field1.PutNumber("F", 132);
field1.PutDict("MK");
field1.PutString("Type", "Annot");
Rect r = new Rect(50, 550, 350, 600);
SDFDoc sdfdoc = doc.GetSDFDoc();
pdftron.PDF.Annots.Widget a =
pdftron.PDF.Annots.Widget.Create(sdfdoc, r, sigField);
Obj obj = CreateSignatureAppearance(doc);
a.SetAppearance(obj);
page = doc.GetPage(1);
page.AnnotPushBack(a);
// Fill our signature dictionary
Obj sig = doc.CreateIndirectDict();
sig.PutName("SubFilter", "adbe.pkcs7.detached");
sig.PutName("Filter", "Adobe.PPKLite");
char[] c = "0".ToCharArray();
string str = new string(c[0], 2000);
sig.PutText("Contents", str);
sig.PutString("M", "D:20081231111920+01'00'");
sig.PutString("Name", "TRN\\jsmith");
sig.PutRect("ByteRange", 111111111, 111111111, 111111111,
111111111);
Obj Prop_Build = sig.PutDict("Prop_Build");
Obj Filter = Prop_Build.PutDict("Filter");
Filter.PutName("Name", "Adobe.PPKLite");
Filter.PutNumber("R", 131102);
Filter.PutString("Date", "May 01 2009 12:13:14");
Obj App = Prop_Build.PutDict("App");
App.PutBool("TrustedMode", true);
Obj OS = App.PutArray("OS");
OS.InsertName(0, "Win");
App.PutName("Name", "Exchange");
App.PutNumber("R", 524546);
App.PutString("REx", "8.1.2");
Obj PubSec = Prop_Build.PutDict("PubSec");
PubSec.PutNumber("R", 131102);
PubSec.PutString("Date", "May 01 2009 12:13:14");
PubSec.PutBool("NonEFontNoWarn", true);
sig.PutName("Type", "Sig");
sigField.SetValue(sig);
sigField.RefreshAppearance();
// Save PDf to memory and update signature entries
byte[] memoryPDF = null;
int memoryPDFSize = 0;
doc.Save(@"C:\Signatures\signed.pdf",
SDFDoc.SaveOptions.e_linearized);
doc.Close();
_documentViewer.Close();
int startPosition = 0;
int byteRangePosition2 = 0;
int byteRangePosition3 = 0;
int byteRangePosition4 = 0;
string originalRange = "[111111111 111111111 111111111
111111111]";
string contents1 = "(0000000000";
string contents2 = "0000000000)";
FileStream file = new FileStream(@"C:\Signatures\signed.pdf",
FileMode.Open, FileAccess.ReadWrite);
memoryPDFSize = (int)file.Length;
memoryPDF = new byte[memoryPDFSize];
file.Read(memoryPDF, 0, memoryPDFSize);
startPosition = FindInBuffer(memoryPDF, contents1, 0);
byteRangePosition2 = startPosition + 1;
contents1 = "<0000000000";
for (int x = 0; x < contents1.Length; ++x)
{
memoryPDF[startPosition] = (byte)contents1[x];
startPosition++;
}
startPosition = FindInBuffer(memoryPDF, contents2, 0);
byteRangePosition3 = startPosition + 10;
byteRangePosition4 = memoryPDFSize - byteRangePosition3;
contents2 = "0000000000>";
for (int x = 0; x < contents2.Length; ++x)
{
memoryPDF[startPosition] = (byte)contents2[x];
startPosition++;
}
startPosition = FindInBuffer(memoryPDF, originalRange, 0);
string newByteRange = "[0 " + byteRangePosition2.ToString() + " "
+ byteRangePosition3.ToString() + " " + byteRangePosition4.ToString()
+ " ]";
if (newByteRange.Length < 41)
{
newByteRange = newByteRange + new string(' ', 41 -
newByteRange.Length);
}
int writePosition = startPosition;
for (int x = 0; x < newByteRange.Length; ++x)
{
memoryPDF[writePosition] = (byte)newByteRange[x];
writePosition++;
}
X509Certificate certificate = new X509Certificate(@"C:\Signatures
\CertExchangeJSmith.cer");
string data = certificate.GetRawCertDataString();
startPosition = FindInBuffer(memoryPDF, contents1, 0);
byteRangePosition2 = startPosition + 1;
contents1 = "<" + data + ">";
if (contents1.Length < 2002)
{
int length = 2002 - contents1.Length;
str = new string('0', length);
contents1 = contents1 = "<" + data + str + ">";
}
for (int x = 0; x < contents1.Length; ++x)
{
memoryPDF[startPosition] = (byte)contents1[x];
startPosition++;
}
file.SetLength(0);
file.Write(memoryPDF, 0, (int)memoryPDF.Length);
file.Flush();
file.Close();
file.Dispose();
}
private int FindInBuffer(byte[] buffer, string stringToFind, int
startPosition)
{
for (int x = startPosition; x < buffer.Length; ++x)
{
if (buffer[x] == (byte)stringToFind[0])
{
int y;
for (y = 1; y < stringToFind.Length; ++y)
{
if ((x + y) >= buffer.Length) { break; }
if (buffer[x + y] != (byte)stringToFind[y]) { break; }
}
if (y == stringToFind.Length) { return (x); }
}
}
return (-1);
}
private Obj CreateSignatureAppearance(PDFDoc doc)
{
ElementBuilder b = new ElementBuilder();
ElementWriter w = new ElementWriter();
w.Begin(doc);
pdftron.PDF.Image img = pdftron.PDF.Image.Create(doc, @"C:
\Signatures\mysig.jpg");
int width = img.GetImageWidth();
int height = img.GetImageHeight();
Element img_element = b.CreateImage(img, 0, 0, width, height);
w.WritePlacedElement(img_element);
Obj stm = w.End();
// Set the bounding box
stm.PutRect("BBox", 0, 0, width, height);
stm.PutName("Subtype", "Form");
w.Dispose();
b.Dispose();
return stm;
}