Bug in PdfFileSignature.Save(Stream)

I am trying to work on a solution where I operate on a PDF in-memory for adding a digital signature. When I save the signed pdf to disk, it all looks good. However, if I save to a stream and then persist the stream to disk, the certificate is invalid. Following is the slightly altered code from your documentation:

Here, inputPath is the pdf file. OutputPath is the fully qualified desired pdf file path. CertPath is the certificate which is trusted and has no password. Logo is the image.

void SignPDF(string inputPath, string outputPath, string certPath, string logo)
{
	var outputStream = new MemoryStream();
	var inputStream = new MemoryStream(File.ReadAllBytes(inputPath));
	using (PdfFileSignature signature = new PdfFileSignature())
	{
		signature.BindPdf(inputStream);
		PKCS7 pkcs = new PKCS7(certPath, ""); // Use PKCS7/PKCS7Detached objects
		DocMDPSignature docMdpSignature = new DocMDPSignature(pkcs, DocMDPAccessPermissions.NoChanges);
		System.Drawing.Rectangle rect = new System.Drawing.Rectangle(100, 100, 200, 100);
		// Set signature appearance
		signature.SignatureAppearance = logo;
		// Create any of the three signature types
		signature.Certify(1, null,null,null, true, rect, docMdpSignature);
		// Save output PDF file
		//signature.Save(outputPath) //works fine;
		signature.Save(outputStream);
		var doc = new Document(outputStream);
		doc.Save(outputPath);
	}

AcroRd32_thEbv9p1Va.png (7.3 KB)

Attached is the screenshot which shows when the stream is saved, the certificate becomes invalid. I am using Aspose.PDF version 20.8.0

Valid signed document is also attached here. The only difference in code is that here we used signature.Save(outputFile) where it directly saves the file to disk instead of memory stream.AcroRd32_pjG5LrGHdn.png (7.3 KB)

@AbhishekTripathi

Would you kindly try to write the stream directly to the disk without re-initializing a Document object with it like following:

using (FileStream file = new FileStream("file.pdf", FileMode.Create, System.IO.FileAccess.Write)) {
   byte[] bytes = new byte[outputStream.Length];
   outputStream.Read(bytes, 0, (int)outputStream.Length);
   file.Write(bytes, 0, bytes.Length);
   outputStream.Close();
}

In case the issue still persists, please share your sample PDF, Certificate file, and a sample image with us. We will test the scenario in our environment and address it accordingly.

I have tried that already. Probably I should have mentioned that. The issue with saving the raw stream to disk is that the file created is corrupted and when you open it in Acrobat, it complains. However, when you initalize the Document object with the stream and save the document using Document.Save(filePath) then it is saved as a correct pdf albeit with the issues I mentioned.

Attached is the corrupted file produced with raw stream persisted to disk.pdf-raw-stream-corrupted.pdf (97.1 KB)

As requested, I am attaching the assets used for the POC. You would need Linqpad v6 to run the code which is free.

You can also easily port the code to VisualStudio2019 if you wish.

ASPOSE_POC.zip (8.8 KB)

@AbhishekTripathi

We were able to reproduce the issue in our environment and logged it as PDFNET-48689 in our issue tracking system. We will further look into its details and keep you informed with the status of its correction. Please be patient and spare us some time.

We are sorry for the inconvenience.

@AbhishekTripathi

We have investigated the logged ticket. In this case, you should use

outputStream.WriteTo(new FileStream(dataDir + "output.pdf", FileMode.Create));

In your below code, a new document is created here, the new document has a different hashcode due to which the signature has been failing.

var doc = new Document(outputStream);
doc.Save(dataDir + "output.pdf");