Issue: After stamping the digital signature on PDF it will become invalid or tampered
We are trying to do digital signature on PDF with certificate through NSDL.
Step1:
we are generating Request XML and in this request XML we are sending the PDF doumnet's hash.
<Docs><InputHash docInfo="Document for eSign" hashAlgorithm="SHA256" id="1">4a2ae3e028d2cc3c4e47dde8bac4ecb7fb67bea2a9f916155da319c66092acfa</InputHash></Docs>
code to generate Hash:
public static string GenerateSha256(string path, string TempPdfPath) {
//return ItextSharpEsign.ExternalEsignGenerate(TempPdfPath, path);
AddSingnatureFields(path, TempPdfPath);
try
{
byte[] PdfBytes = System.IO.File.ReadAllBytes(TempPdfPath);
SHA256 sha256 = SHA256.Create();
byte[] ByteHash = sha256.ComputeHash(PdfBytes);
string DocHex = BitConverter.ToString(ByteHash).Replace("-", "").ToLower(); ;
return DocHex;
}
catch (Exception ex)
{
throw;
} }
Step2:
After posting the successful request we are able to do the Aadhaar OTP process in NSDL site later they are sending response XML with this response XML is contains Documentsignatture in base 64 format.
we are consuming the licensed synfusion dll to embed the signature on PDF code mentioned below
public static void ExternalSign(string ResponseXml, string TempPdfFile, string FinalSignedPdf)
{
FileStream tempfs = null; ;
FileStream sigfs = null; ;
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ResponseXml);
var docsign = xmlDoc.GetElementsByTagName("DocSignature")[0];
var docsin = docsign.InnerText;
PdfLoadedDocument document = new PdfLoadedDocument(TempPdfFile);
PdfSignature signature = new PdfSignature(document, document.Pages[0], null, "SignatureField", document.Form.Fields["SignatureField"] as PdfLoadedSignatureField);
signature.ComputeHash += Signature_ComputeHash;
//Save the PDF document.
document.Save(FinalSignedPdf);
//Close the document.
document.Close(true);
void Signature_ComputeHash(object sender, PdfSignatureEventArgs arguments)
{
byte[] documentBytes = arguments.Data;
arguments.SignedData = Convert.FromBase64String(docsin);
}
}
catch (Exception ex)
{
}
}
ResponseXML:
<Signatures><DocSignature error="" id="1" sigHashAlgorithm="SHA256">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</DocSignature></Signatures>
Thank you for contacting syncfusion support.
We kindly request you to follow the steps below to accomplish your requirement using our deferred signing functionality.
The deferred signing works as a client-server interaction. Typically, PDF documents are created/manipulated on the server. If the end-user needs to sign a PDF document, they have to retrieve the entire document for signing and then send back the signed PDF document. With this feature, the customer can generate a hash from a PDF document and send it to the end-user for signing. Once the end-user signs it, they will return the signed hash to the server to apply it to the PDF document.
Note: In real-time, the signed hash may be encoded with or without PKCS7 information. Therefore, we recommend creating an empty signature and utilizing our ReplaceEmptySignature functionality to accomplish this.
Please refer to the below steps to deferred sign,
Step 1: Create an empty signature using your public certificate. You can refer to the example code here: [link to the example](https://github.com/SyncfusionExamples/PDF-Examples/blob/master/Digital%20Signature/Deferred-signing-in-PDF-document/.NET/Deferred-signing-in-PDF-document/Program.cs#L21).
static void CreateEmptySignedPDF() { // Get the stream from the document. FileStream documentStream = new FileStream(Path.GetFullPath("../../../Barcode.pdf"), FileMode.Open, FileAccess.Read);
//Load an existing PDF document. PdfLoadedDocument loadedDocument = new PdfLoadedDocument(documentStream);
//Creates a digital signature. PdfSignature signature = new PdfSignature(loadedDocument, loadedDocument.Pages[0], null, "Signature");
//Sets the signature information. signature.Bounds = new RectangleF(new PointF(0, 0), new SizeF(100, 30)); signature.Settings.CryptographicStandard = CryptographicStandard.CADES; signature.Settings.DigestAlgorithm = DigestAlgorithm.SHA1;
//Create an external signer. IPdfExternalSigner externalSignature = new SignEmpty("SHA1");
//Add public certificates. System.Collections.Generic.List<X509Certificate2> certificates = new System.Collections.Generic.List<X509Certificate2>(); certificates.Add(new X509Certificate2(Convert.FromBase64String(PublicCert))); signature.AddExternalSigner(externalSignature, certificates, null);
//Save the document. FileStream inputFileStream = new FileStream(Path.GetFullPath("../../../EmptySignature.pdf"), FileMode.Create, FileAccess.ReadWrite); loadedDocument.Save(inputFileStream);
//Close the PDF document. loadedDocument.Close(true); inputFileStream.Close(); } |
Step 2: When creating the empty signature file, please follow the steps outlined in the sign block. You can find the instructions here: [link to the code](https://github.com/SyncfusionExamples/PDF-Examples/blob/master/Digital%20Signature/Deferred-signing-in-PDF-document/.NET/Deferred-signing-in-PDF-document/Program.cs#L94).
The "message" parameter represents the bytes of a document sequence, but it should be a calculated hash or digest value. Therefore, before externally signing the document, you need to generate a hash or digest value from the message bytes, as indicated below:
public byte[] Sign(byte[] message, out byte[] timeStampResponse) { byte[] digest; using (SHA256Managed sha = new SHA256Managed()) { digest = sha.ComputeHash(message); } SignDocumentHash(digest); // Convert digest bytes to base64/Hex format if requested to send to sign the digest. // Set a null value to create an empty signed document. byte[] signedBytes = null; timeStampResponse = null; return signedBytes; }
|
Step 3: Please use the following overload for Deferred Sign:
If your signed digest message already contains encoded PKCS7 information, use the following overload to replace your signed signature bytes:
// Deferred signing without PKCS7 encoding. PdfSignature.ReplaceEmptySignature(inputFileStream, pdfPassword, outputFileStream, signatureName, externalSigner, publicCertificates, false); |
Step 4: Replace your signed signature bytes as shown in the code here: [link to the code](https://github.com/SyncfusionExamples/PDF-Examples/blob/master/Digital%20Signature/Deferred-signing-in-PDF-document/.NET/Deferred-signing-in-PDF-document/Program.cs#L137).
public byte[] Sign(byte[] message, out byte[] timeStampResponse) { // Set the signed hash message to replace an empty signature. byte[] signedBytes = _signedHash; timeStampResponse = null; return signedBytes; }
|
You can find the working sample from below link,