Document has been altered or corrupted since it was signed with deffered signing #2

Hi guys,

I based some work on the following thread :
https://www.syncfusion.com/forums/183069/document-has-been-altered-or-corrupted-since-it-was-signed-with-deffered-signing

I try to apply Digital signatures from the provider SwissSign in Switzerland.


I try to follow the following process :

  • Load a document
  • Add a Signature field (in the target solution, it could be multiple)
  • Calculate the hash
  • Request a signature
  • Extract the signedHash
  • Update the signatureInfo
  • Sign the document (Deferred signature) with the replace Empty signature


Unfortunately, at the end, the document is still considered as altered or corrupted.
I tried as well to replaceEmptySignature with the flag isEncodeSignature false but no matter what it doesn't work.

In the target I would also be able to put an image as the visual signature.

One more thing, when I try to get the signatures, i'm not able to get them as AcroForm fields.

Please find attached a sample with the logic and the sequence of calls.
The call to the external service can be bypass.
The retrieved signature for the tmp.pdf file is attached as text file

Many thanks for all your help

Best regards
Louis

Attachment: sample_261ea702.zip

7 Replies 1 reply marked as answer

IJ Irfana Jaffer Sadhik Syncfusion Team December 11, 2024 02:13 PM UTC

Hi Louis Marie,

After reviewing the shared document, we believe the issue might be caused by the timestamp token response not being generated from the signed signature's result. It is not possible to add a timestamp to a signature that has already been applied to the PDF document. To resolve this, please generate the timestamp token response using the hash message of the signed signature.

Please find the example steps below:

  1. Create a hash value from the message bytes.
  2. Sign the hash value using your external service.
  3. Create a hash value from the signed signature bytes.
  4. Create a timestamp token using the hash value from the signed signature.
  5. Update the response token in the timeStampResponse and return the signed signature bytes.

/// <summary>
/// Represents to replace an empty signature from an external signer.
/// </summary>
class ExternalSigner : IPdfExternalSigner
{
    private string _hashAlgorithm;
    public string HashAlgorithm
    {
        get { return _hashAlgorithm; }
    }


   public ExternalSigner(string hashAlgorithm)
    {
        _hashAlgorithm = hashAlgorithm;
    }


   private static string ToHex(byte[] bytes, bool upperCase)
    {
        StringBuilder result = new StringBuilder(bytes.Length * 2);


       for (int i = 0; i < bytes.Length; i++)
            result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));


       return result.ToString();
    }


   public byte[] Sign(byte[] message, out byte[]timeStampResponse)
    {


       SHA256 hashstring = SHA256.Create();


       byte[] hash = hashstring.ComputeHash(message);

        string hexencodedDigest = ToHex(hash, true);


       var signed = DSSClient.Sign(identity.Id, hexencodedDigest);


       //decode hex signature
        byte[] dsg = Hex.Decode(signed.Signature);


       hash = hashstring.ComputeHash(dsg);

        hexencodedDigest = ToHex(hash, true);


       var time = DSSClient.Timestamp(hexencodedDigest);
        byte[] token = Base64.Decode(time.Token);

timeStampResponse = token;


       return dsg;
    }           
}




Please try the above suggestions on your end. Please share with us the modified sample with us if you are still facing an issue. So that we can assist with you further in this.


Regards,

Irfana J.



UN Unknown December 11, 2024 06:56 PM UTC

Hi Irfana,


Many thanks for the answer.

i'm not sure to understand well.

In the sample there were no signed document.


In the attached zip, you'll find the adapted codebase as well as an example.

In the example you have :

  • one input file : input.pdf
  • one tmp file : tmp.file which is the input with the added signature field (empty)
    the hashToSign is calculated on this file
  • the retrieved signature content : base64signature.txt
  • the signed file : signed.pdf


You'll see that the identity is compliant with the data used to request signature.
Timestamp is well formed as per Adobe Reader

Image_1002_1733943248988

Maybe these elements could help you to find what's wrong with my  code.


What will happened when I will put an image for the signature field.

Do I have to put it before the signing or as an annotation property or something else when applying the deferred signature?


One more time, thanks for helping me achieve this.


Best

Louis



Attachment: sample_ae75525c.zip


IJ Irfana Jaffer Sadhik Syncfusion Team December 13, 2024 03:59 AM UTC

Hi Louis,

Upon further analysis, we found that in the provided sample, you created a hash from the empty signed document and signed it. However, for signing a PDF document, the correct approach is to use the document hash obtained from the SignEmpty external signer class. Below is an example of how to implement this logic correctly:


    class SignEmpty : IPdfExternalSigner
    {
        private string _hashAlgorithm;

 

        public string HashAlgorithm
        {
            get { return _hashAlgorithm; }
        }

 

        public SignEmpty(string hashAlgorithm)
        {
            _hashAlgorithm = hashAlgorithm;
        }

 

        public byte[] Sign(byte[] message, out byte[] timeStampResponse)
        {
            X509Certificate2 digitalID = new X509Certificate2(new X509Certificate2(Path.GetFullPath(@"../../../Data/PDF.pfx"), "password123"));
            if (digitalID.PrivateKey is System.Security.Cryptography.RSACryptoServiceProvider)
            {
                System.Security.Cryptography.RSACryptoServiceProvider rsa = (System.Security.Cryptography.RSACryptoServiceProvider)digitalID.PrivateKey;
                Program.SignedHash = rsa.SignData(message, HashAlgorithm);
            }
            else if (digitalID.PrivateKey is RSACng)
            {
                RSACng rsa = (RSACng)digitalID.PrivateKey;
                Program.SignedHash = rsa.SignData(message, System.Security.Cryptography.HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
            }
            Program.timestampRes = GetRFC3161TimeStampToken(Program.SignedHash);

 

            timeStampResponse = null;

 

            return null;
        }


Additionally, the timestamp token should be signed using the signed hash obtained from the above implementation. We have prepared and updated the sample for your reference. Kindly try this on your end and let us know if you need further assistance.

Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/eAuthdocVisa-517214652

If you are still facing the same issue, we request you to modify the sample by including the necessary certificate files so that we can replicate the problem on our end and provide you with a solution.

You can refer to the following UG documentation for further details: https://help.syncfusion.com/document-processing/pdf/pdf-library/net/working-with-digitalsignature#deferred-signing-in-pdf-document 


Regards,

Irfana J.




UN Unknown December 20, 2024 02:17 PM UTC

Hi Irfana,


Thanks for your feedback.

Unfortunately, it seems that it doesn't work for now.


First, your code seems to work in your use-case even using Hash Algorithm SHA-256 (please find the amend version attached.

Second, we have an issue regarding the way you suggest to sign empty and the way we retrieve a signature from our DSSP.


According to adobe documentation regardind applying a digital signature (https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/Acrobat_DigitalSignatures_in_PDF.pdf part 6.2.1) there is some steps to follow.

In our case, the step 5 is done directly by the DSSP as it is the only one who have the private key.

So do i have to try to sign something empty as I can't?


In the attached code sample, i put the code to get a signature from a computedHash.

If I try to use a signed hash I get a bad request error and according to discussion with DSSP it is normal as a computedHash only is expected.


So I don't know what I'm missing but it's strange to me.


Maybe with this sample (with working function to get signature) you'll be able to find how to get all of this working properly.



Many thanks for your help.

Best regards

Louis


Attachment: syncfusion_2cbd2d79.zip


MK Moorthy Karunanithi Syncfusion Team December 23, 2024 02:19 PM UTC

Hi Louis Marie,

Thank you for the update.

Upon investigating the shared sample, we identified that incorrect public certificates were used while creating an empty or temporary signature document. To resolve this issue, we kindly request that you update your application as per the following changes:

//Create an external signer.

IPdfExternalSigner emptyExternalSigner = new SignEmpty("SHA256");

 

//Add public certificates.

List<X509Certificate2> certificates = new List<X509Certificate2>();

certificates.Add(new X509Certificate2(new X509Certificate2(Path.GetFullPath(@"../../../Data/Syncfusion-experiment.p12"), "#=iC+njBjv(sWZtvySFxwP88")));

 

signature.AddExternalSigner(emptyExternalSigner, certificates, null);


Additionally, we observed that the signature hash in the shared reference PDF file already contains PKCS7-encoded data. Therefore, we recommend replacing the signature using the following updates in your application:

//Deferred signing without PKCS7 encoding.

PdfSignature.ReplaceEmptySignature(inputFileStream, pdfPassword, outputFileStream, signatureName, externalSigner, publicCertificates, false);

 


For more details on signing without PKCS7 encoding, please refer to our user guide documentation.

https://help.syncfusion.com/document-processing/pdf/pdf-library/net/working-with-digitalsignature#deferred-signing-without-pkcs7-encoding

Please let us know if you need further assistance.

Regards,

Moorthy K



UN Unknown January 6, 2025 08:19 AM UTC

Dear Moorthy, Irfana,


Best wishes for the upcoming year.


Many thanks for your advices, I was able to apply them and to have a functional code.


Best regards

Louis



KV Kirthika Vijayagiri Syncfusion Team January 9, 2025 06:20 AM UTC

Hi Louis Marie,

You are welcome. If you need any further assistance, please don't hesitate to reach us.


Marked as answer
Loader.
Up arrow icon