how can i obtain information about byte range field

hello everybody

i am silvio forno, and i try to use pdfnet sdk to write an application involving digital signature on PDF file.
I am reding documentation and look at sample code, but, for now, is not clear to me how I can retrieve info on Byte Range field on a existing signature form field or i can put this information in a brand new signature. This because i have to compute an hash of the document before applying the digital signature, and another hash after signature is inserted.
Thanks in advance for any hint or help.

sincerely

silvio forno

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;
}

On a relevant note, we have recently started a project to define a new API that will simply development of custom digital signatures handlers. If you are working with PDFNet and digital signatures you may want to join a beta program and provide your input during the development.

yes i am interested, how can i join this beta program ?
regards

silvio forno

Just an update to this thread. The current version of PDFNet includes high-level signature API. For more info please see:

https://groups.google.com/d/topic/pdfnet-sdk/SGcTSYFjaSk/discussion