Digital Signature Add Integrity check , Get total number of revisions and export pdf version per each signature.

i need a way to check document integrity also function to get total number of revisions that should be equal to total number of signatures in pdf file .... also the ability to export the pdf version as a pdf file per signature.



Image_5076_1696253669255


21 Replies

RB Ravikumar Baladhandapani Syncfusion Team October 6, 2023 04:05 PM UTC

We do not have support to export the pdf based on this version. Currently, we have support to retrieve the revisions the document and signature field.

Please refer the below  UG documentation for your reference.

https://help.syncfusion.com/file-formats/pdf/working-with-digitalsignature#retrieve-signed-revision-information-from-digital-signature

https://help.syncfusion.com/file-formats/pdf/working-with-digitalsignature#digital-signature-validation

Please let us know, if you need any further assistance on this



JA Jacobs replied to Ravikumar Baladhandapani October 8, 2023 05:36 AM UTC

i checked the link you provided but i couldn't get any useful information from the provided properties

PdfLoadedDocument.Revisions.StartPosition & PdfLoadedSignatureField.Revision

, also i am fully aware of the ValidateSignature function.


but this is not what i am asking for , i need a function to check the whole document integrity not per signature and another function to get the total number of revisions per document which should only increase when adding digital signatures not any other form field types and the ability to export pdf document per revision (per signature)



KS Karmegam Seerangan Syncfusion Team October 9, 2023 12:37 PM UTC

Currently we are analyzing this. We will provide further analysis details on October 11, 2023.



RB Ravikumar Baladhandapani Syncfusion Team October 11, 2023 02:34 PM UTC

As mentioned in the previous update, we do not have support to export the PDF based on this version. Additionally, we have thoroughly examined the document integrity during the validation of the signature.


Could you kindly provide us with your exact requirement? This information will be helpful for further investigation into the matter.



JA Jacobs November 8, 2023 01:32 PM UTC

number of revisions should be equal to number of signatures ... so if there is one signature it should be 1 signature ,

if user added an annotation after the existing signature then number of revisions should be 2 (not equal to number of signatures) and this means that the document has unsigned changes and the the existing signature does not cover the whole document.

if a second signature is added after the annotation , number of revisions should remain 2 (equal to number of signatures) but this time the second signature covers the whole document.

The PdfLoadedSignatureField.Revision in syncfusion is not indicating this and i checked it with an empty pdf file with no signatures at all and it gives 2 revisions.


you can check this link 

https://itextpdf.com/sites/default/files/2018-12/digitalsignatures20130304.pdf Page (124)

and the updated version https://itextpdf.com/blog/technical-notes/avoiding-pdf-digital-signature-vulnerabilities-itext


They both talk about document integrity and if signature covers whole document or not.


Waiting for your reply.




RB Ravikumar Baladhandapani Syncfusion Team November 9, 2023 04:59 PM UTC

Could you please share the input PDF document that you tested with to get the revision details using Syncfusion library? It will be helpful for our further investigation.



JA Jacobs November 9, 2023 05:01 PM UTC

The issue is not with one pdf ... it is with any pdf with or without signatures



RB Ravikumar Baladhandapani Syncfusion Team November 10, 2023 12:51 PM UTC

We are currently analyzing the reported behavior with the provided details on our end, and we will provide further details on November 15th, 2023.



KS Karmegam Seerangan Syncfusion Team November 23, 2023 07:42 AM UTC

Our PdfRevision feature gives you all the details about changes made to the document. The PdfLoadedSignatureField.Revision tells you specifically about the index of signed revisions in the loaded document. We've shared a workaround solution to help you get the specific details you need about revisions.

 

 

static void Main(string[] args)

{

    PdfLoadedDocument loadedDocument = new PdfLoadedDocument(@"C:\PdfAutomation\PDF\Data\EPIC_841187\EPIC_841187_Multichain.pdf");

 

    Dictionary<string, int> fieldSignatures;

    int totalRevisions = GetSignatureTotalRevision(loadedDocument.Form.Fields, out fieldSignatures);

    for (int i = 0;i<loadedDocument.Form.Fields.Count;i++)

    {

 

        PdfLoadedSignatureField pdfLoadedSignatureField = loadedDocument.Form.Fields[i] as PdfLoadedSignatureField;

if(pdfLoadedSignatureField != null)

        {

            Console.WriteLine("Signature Field Name: " + pdfLoadedSignatureField.Name);  

            Console.WriteLine("Document Revision: " + fieldSignatures[pdfLoadedSignatureField.Name] + " of " + totalRevisions);

        }

    }

}

 

private static int GetSignatureTotalRevision(PdfLoadedFormFieldCollection fields, out Dictionary<string, int> fieldSignatures)

{

    fieldSignatures = new Dictionary<string, int>();

    int totalRevisions = 0;

    Dictionary<int, PdfLoadedSignatureField> keyValuePairs = new Dictionary<int, PdfLoadedSignatureField>();

    foreach(PdfLoadedSignatureField signatureField in fields)

    {

if (signatureField.Signature != null && signatureField.IsSigned)

        {

            totalRevisions++;

            keyValuePairs[signatureField.Revision] = signatureField;

        }

    }

 

    if(keyValuePairs.Count > 0)

    {

int[] sort = keyValuePairs.Keys.ToArray();

        System.Array.Sort(sort);

        Dictionary<string, int> valuePairs = new Dictionary<string, int>();

int count = 1;

foreach(int revision in sort)

        {

            PdfLoadedSignatureField pdfLoadedSignatureField = keyValuePairs[revision];

            valuePairs[pdfLoadedSignatureField.Name] = count++;                   

        }

        fieldSignatures = valuePairs;

    }

   return totalRevisions;

}



JA Jacobs replied to Karmegam Seerangan November 27, 2023 06:50 AM UTC

Thanks ... but this basically does not make the integrity check that i asked for

you are setting the number of revisision to number of signature if (signatureField.Signature != null && signatureField.IsSigned)


but where is the annotation check so that if the signature covers the whole document (including the annotation) then it is fine ... while if the annotation is added at end and no signature after it then it breaks document integrity


i sent the details in my previous reply with explanation and links to other libraries that handle checking document integrity


https://www.syncfusion.com/forums/184838/digital-signature-add-integrity-check-get-total-number-of-revisions-and-export-pdf-version?reply=SD16Ri




RB Ravikumar Baladhandapani Syncfusion Team November 29, 2023 01:14 PM UTC

Thank you for your patience,


We've made improvements to the solution based on what you needed. Now, you can see document revision details, the entire document cover information, and check its integrity all together. Plus, the document won't lose its integrity if comments are allowed for the signature. We've also added support to ensure the document's integrity while validating the signature. Please try the workaround solution below to achieve the same outcome.



static void Main(string[] args)

{

     PdfLoadedDocument loadedDocument = new PdfLoadedDocument(@"Test.pdf");

     PdfRevision[] revisions = loadedDocument.Revisions;

     Dictionary<string, int> fieldSignatures;

     int totalRevisions = GetSignatureTotalRevision(loadedDocument.Form.Fields, loadedDocument, out fieldSignatures);

     for (int i = 0; i < loadedDocument.Form.Fields.Count; i++)

     {

         PdfLoadedSignatureField pdfLoadedSignatureField = loadedDocument.Form.Fields[i] as PdfLoadedSignatureField;

         if (pdfLoadedSignatureField != null)

         {

             bool isCoverWholeDocument = (revisions.Length == pdfLoadedSignatureField.Revision) ? true : false;

             Console.WriteLine("Signature covers whole document: " +  isCoverWholeDocument.ToString());

             Console.WriteLine("Signature Field Name: " + pdfLoadedSignatureField.Name);

             Console.WriteLine("Document Revision: " + fieldSignatures[pdfLoadedSignatureField.Name] + " of " + totalRevisions);

             Console.WriteLine("Integrity check OK? "+ pdfLoadedSignatureField.ValidateSignature().IsSignatureValid);

         }

     }

}

private static int GetSignatureTotalRevision(PdfLoadedFormFieldCollection fields, PdfLoadedDocument loadedDocument, out Dictionary<string, int> fieldSignatures)

{

     fieldSignatures = new Dictionary<string, int>();

     int totalRevisions = 0;

     Dictionary<int, PdfLoadedSignatureField> keyValuePairs = new Dictionary<int, PdfLoadedSignatureField>();

     foreach (PdfLoadedSignatureField signatureField in fields)

     {

         if (signatureField.Signature != null && signatureField.IsSigned)

         {

             totalRevisions++;

             keyValuePairs[signatureField.Revision] = signatureField;

         }

     }

     int maxRevision = 0;

     if (keyValuePairs.Count > 0)

     {

         int[] sort = keyValuePairs.Keys.ToArray();

         System.Array.Sort(sort);

 

         maxRevision = sort[sort.Length - 1];

 

         Dictionary<string, int> valuePairs = new Dictionary<string, int>();

         int count = 1;

         foreach (int revision in sort)

         {

             PdfLoadedSignatureField pdfLoadedSignatureField = keyValuePairs[revision];

             valuePairs[pdfLoadedSignatureField.Name] = count++;

         }

         fieldSignatures = valuePairs;

     }

     PdfRevision[] revisions = loadedDocument.Revisions;

 

     if(fieldSignatures.Count > 0)

     {

         if(revisions.Length > maxRevision)

         {

             totalRevisions += 1;

         }

     }

 

     return totalRevisions;

}





JA Jacobs December 27, 2023 11:54 AM UTC

Thanks

but unfortunately, the code does not return correct results in all cases, for example 


Annotaion&1Signature.pdf

Signature covers whole document: False // should be true because signature is added after annotation.

Document Revision: 1 of 2 // total revisions should be 1 file because it has only one signature.


Annotaion&2Signature&Annotation.pdf

1st signature

Signature covers whole document: False

Document Revision: 1 of 3 // total revisions  should be 2 file because it has only two signatures.


2nd signature

Signature covers whole document: False

Document Revision: 2 of 3 // total revisions should be 2 file because it has only two signatures.


Attachment: testcases27122023_273330ed.zip


RB Ravikumar Baladhandapani Syncfusion Team December 29, 2023 01:27 PM UTC

Currently we are analyzing on this, and we will update further details on 3rd January 2024.



JT Jeyalakshmi Thangamarippandian Syncfusion Team January 3, 2024 04:06 PM UTC

We've made some improvements to the solution to get better results. Please check the updated workaround to achieve the same outcome.

Annotaion&2Signature&Annotation.pdf

1st signature

Signature covers whole document: False

Document Revision: 1 of 3 // total revisions  should be 2 file because it has only two signatures.

2nd signature

Signature covers whole document: False

Document Revision: 2 of 3 // total revisions should be 2 file because it has only two signatures.

The number of revisions should be three because an annotation to be added after the second signatures


PdfLoadedDocument loadedDocument = new PdfLoadedDocument(File.OpenRead(@"Annotaion&1Signature.pdf"));

PdfRevision[] revisions = loadedDocument.Revisions;

List<long> revisionList = new List<long>();

foreach (PdfRevision revision in revisions)

{

    if (!revisionList.Contains(revision.StartPosition))

        revisionList.Add(revision.StartPosition);

}

Dictionary<stringint> fieldSignatures;

int totalRevisions = GetSignatureTotalRevision(loadedDocument.Form.Fields, loadedDocument, out fieldSignatures);

for (int i = 0; i < loadedDocument.Form.Fields.Count; i++)

{

    PdfLoadedSignatureField pdfLoadedSignatureField = loadedDocument.Form.Fields[i] as PdfLoadedSignatureField;

    if (pdfLoadedSignatureField != null)

    {

        bool isCoverWholeDocument = (revisionList.Count == pdfLoadedSignatureField.Revision) ? true : false;

        Console.WriteLine("Signature covers whole document: " + isCoverWholeDocument.ToString());

        Console.WriteLine("Signature Field Name: " + pdfLoadedSignatureField.Name);

        Console.WriteLine("Document Revision: " + fieldSignatures[pdfLoadedSignatureField.Name] + " of " + totalRevisions);

        Console.WriteLine("Integrity check OK? " + pdfLoadedSignatureField.ValidateSignature().IsSignatureValid);

    }

}

int GetSignatureTotalRevision(PdfLoadedFormFieldCollection fields, PdfLoadedDocument loadedDocument, out Dictionary<stringint> fieldSignatures)

{

    fieldSignatures = new Dictionary<stringint>();

    int totalRevisions = 0;

    Dictionary<int, PdfLoadedSignatureField> keyValuePairs = new Dictionary<int, PdfLoadedSignatureField>();

    foreach (PdfLoadedSignatureField signatureField in fields)

    {

        if (signatureField.Signature != null && signatureField.IsSigned)

        {

            totalRevisions++;

            keyValuePairs[signatureField.Revision] = signatureField;

        }

    }

    int maxRevision = 0;

    if (keyValuePairs.Count > 0)

    {

        int[] sort = keyValuePairs.Keys.ToArray();

        System.Array.Sort(sort);

 

        maxRevision = sort[sort.Length - 1];

 

        Dictionary<stringint> valuePairs = new Dictionary<stringint>();

        int count = 1;

        foreach (int revision in sort)

        {

            PdfLoadedSignatureField pdfLoadedSignatureField = keyValuePairs[revision];

            valuePairs[pdfLoadedSignatureField.Name] = count++;

        }

        fieldSignatures = valuePairs;

    }

    PdfRevision[] revisions = loadedDocument.Revisions;

 

    List<long> revisionList = new List<long>();

    foreach (PdfRevision revision in revisions)

    {

        if(!revisionList.Contains(revision.StartPosition))

        revisionList.Add(revision.StartPosition);

    }

    if (fieldSignatures.Count > 0)

    {

        if (revisionList.Count > maxRevision)

        {

            totalRevisions += 1;

        }

    }

    return totalRevisions;

}




JA Jacobs replied to Jeyalakshmi Thangamarippandian February 29, 2024 11:06 AM UTC

Thanks for the updated code .... but can you elaborate what does the property  PdfRevision.StartPosition refers to ?

what is the use of it in the above code 

in this link it is referred to the starting position of the revision within the PDF document.

https://help.syncfusion.com/cr/file-formats/Syncfusion.Pdf.Parsing.PdfRevision.html#Syncfusion_Pdf_Parsing_PdfRevision_StartPosition

while PdfLoadedSignatureField.Revision is not described here

https://help.syncfusion.com/cr/file-formats/Syncfusion.Pdf.Parsing.PdfLoadedSignatureField.html#Syncfusion_Pdf_Parsing_PdfLoadedSignatureField_Signature

and why you are depending on PdfRevision.StartPosition since it is not unique as pdf revisions use the concept of incremental updates ?

https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf

Image_3421_1709202365246

Also i think syncfusion PdfLoadedDocument.Revisions calculation should be direct.

for example if pdf with no signatures it should be equal zero

if pdf with no signatures and has any number of annotations ... it should stay also zero

once a signature is added , the revisions should be 1

Any annotation is added after signature it should become two and should stays equal 2 regardless of their count but the signature does not cover the whole document till a second signature is added and then it stays equal 2 but the signature covers the whole document .

Any further annotations added regardless of their count the revisions should become three till the third signature is added and then it should stays equal three but the signature covers the whole document and so on.

Can this be the default behaviour in syncfusion ?



JT Jeyalakshmi Thangamarippandian Syncfusion Team March 1, 2024 01:55 PM UTC

Currently, we are validating this and will update further details on March 5th, 2024.



AG Aribalakrishnan Govindasamy Syncfusion Team March 5, 2024 03:24 PM UTC

As mentioned in the previous update, we do not have support to export the PDF based on this version. we have support to retrieve the revisions the document and signature field.

 In Pdf revision feature gives you all the details about changes made to the document. And then signature revisions tell you specifically about the index of signed revisions in the loaded document. We've shared a workaround solution to help you get the specific details you need about revisions



JA Jacobs replied to Aribalakrishnan Govindasamy March 5, 2024 04:04 PM UTC

Dear Aribalakrishnan Govindasamy

It seems you missed my comment 

I didn't ask about exporting pdf based on revision

I am having questions and inquiries about the provided workaround.

Please check again my previous comment ... waiting for your reply



JT Jeyalakshmi Thangamarippandian Syncfusion Team March 7, 2024 01:47 PM UTC

Currently we are still analyzing on your requirement, and we will update further details on March 8th, 2024.



JT Jeyalakshmi Thangamarippandian Syncfusion Team March 8, 2024 04:02 PM UTC

 We are still analyzing on your requirement, and will update further details on March 11th, 2024.



JT Jeyalakshmi Thangamarippandian Syncfusion Team March 11, 2024 03:07 PM UTC


Property  & Queries

Description

PdfLoadedDocument.Revison

The PdfLoadedDocument.Revisions feature helps you find the number of incremental updates made in the PDF. It's important to note that this count is not influenced by the signature.

 

PdfRevision.StartPosition

The PdfRevision.StartPosition feature provides details about the starting offset position in the PDF for an incremental update.

 

PdfLoadedSignatureField.Revision

The PdfLoadedSignatureField.Revision feature gives you the index of the signed revision for a signature, considering the incremental updates in the PDF. For instance, if a document undergoes 10 incremental updates and a signature is added in the 5th update, the returned value will be 5.

We've incorporated these functionalities in PdfLoadedDocument for handling incremental updates. These are the behaviors we've implemented for the mentioned APIs.

As your requirement specifically involves revisions based on signatures, we've created a workaround sample to fulfill this need.

Also i think syncfusion PdfLoadedDocument.Revisions calculation should be direct.

for example, if pdf with no signatures it should be equal zero

if pdf with no signatures and has any number of annotations ... it should stay also zero

once a signature is added , the revisions should be 1

 

Our PdfLoadedDocument.Revisions may differ from other libraries because our functionality doesn't depend on signature signed coverage. If you've faced any issues with the suggested workaround's result, please let us know. We'll investigate the problem and work on resolving it.

 

Regards,

Jeyalakshmi T


Loader.
Up arrow icon