Hi,
I would like to sign the pdf using a national id card from my web application.
Here is the process:
-
Prepare the document for signing: add an empty signature field, get the hash of the PDF and return that hash to the client.
-
Javascript client receives the hash and sends it to the native application that will do the signing
-
Native application returns the signature of the hash and a certificate that was used for signing (without private key)
-
Javascript client sends the signature and certificate to the server
-
Server should open the prepared pdf and add the received signature to the pdf
The first problem that I have is with the step 1.
I was looking at the PdfDelayOrReSignDigitalId but in step 1 I don’t have a certificate so I tried this
using (var document = GemBox.Pdf.PdfDocument.Load("SignDemo.pdf"))
{
// Add a visible signature field to the first page of the PDF document.
var signatureField = document.Form.Fields.AddSignature(document.Pages[0], 300, 500, 250, 50);
signatureField.Name = "gemsig";
var sig = signatureField.Sign(SignerFunc, PdfSignatureFormat.PKCS7, 9000);
document.Save("SignDemoGem_prepare.pdf");
//return hash to the client
return new
{
hash = MyPDFInfo.Hash
};
}
byte[] SignerFunc(Stream stream)
{
//get pdf hash
var hash = SHA256.Create().ComputeHash(stream);
MyPDFInfo.Hash = Convert.ToHexString(hash);
//return empty byte[]
return new byte[8000];
}
I’m unsure if this is a good approach?
Next problem is with step 5.
using (var document = GemBox.Pdf.PdfDocument.Load("SignDemoGem_prepare.pdf"))
{
// get signature field
var signatureField = document.Form.Fields.FirstOrDefault(x => x.Name == "gemsig");
byte[] bytes = Convert.FromHexString(dto.certificate);
var cert = new X509Certificate2(bytes);
var pdfCertificate = new GemBox.Pdf.Security.PdfCertificate(cert);
var digitalId = new PdfDelayOrReSignDigitalId(pdfCertificate);
digitalId.Signature = Convert.FromHexString(dto.signature);
var signer = new PdfSigner(digitalId);
((PdfSignatureField)signatureField).Sign(signer);
}
This adds the signature but the signature is invalid. I get an error “Document has been altered or corrupted since it was signed”. I have noticed that the digitalId.Hash after calling Sign method is not the same as the one returned to the client
I have then tried another approach
using (var document = GemBox.Pdf.PdfDocument.Load("SignDemoGem_prepare.pdf"))
{
// Add a visible signature field to the first page of the PDF document.
var signatureField = document.Form.Fields.FirstOrDefault(x => x.Name == "gemsig");
//dto.certificate
//what to do with the certificate
MyPDFInfo.Signature = dto.signature;
((PdfSignatureField)signatureField).Sign(SignerFunc2, PdfSignatureFormat.PKCS7, 9000);
document.Save("SignDemoGem2_signed.pdf");
}
byte[] SignerFunc2(Stream stream)
{
//get pdf hash
//var hash = SHA256.Create().ComputeHash(stream);
//the hash is the same as the one returned to the client
//return the signature received from client
return Convert.FromHexString(MyPDFInfo.Signature);
}
but I still get an invalid signature with error “There are errors in the formatting or information contained in this signature”
Can you please provide some guidance?
All the examples I have seen where using a certificate with private key or were calling an external web service in the same step.
Thank you