Im trying digitaly sign PDF document with Syncfusion. (Library for generating pdf document)
Entire document, not just field.
I don't know mutch about signing or certificates.
I know that certificate is type of HSM, so i used:
Syncfusion - Externally sign a pdf document
It works on my development PC, but doesn't in production. Certificate is find, but at signing document it causes:
CryptographicException: Unknown error „-1073741823“ at System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, Boolean silent)
My code:
using Syncfusion.Licensing;
using Syncfusion.Pdf;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf.Parsing;
using Syncfusion.Pdf.Security;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace SyncfusionTest3
{
class Program
{
public static X509Certificate2 infoCertifikat = null;
static void Main(string[] args)
{
var store = new System.Security.Cryptography.X509Certificates.X509Store(StoreLocation.LocalMachine);
string thumbprint = "9F.."; //Production
store.Open(OpenFlags.ReadOnly);
foreach (var mCert in store.Certificates)
{
if (mCert.Thumbprint.ToUpper().Equals(thumbprint.ToUpper()))
infoCertifikat = mCert;
}
if (infoCertifikat == null)
{
Console.WriteLine("404 Certificate not found");
Console.ReadKey();
return;
}
string licenceKey = "LicenceKey";
SyncfusionLicenseProvider.RegisterLicense(licenceKey);
using (var pdfDoc = new PdfLoadedDocument("document.pdf"))
{
pdfDoc.DocumentInformation.Creator = "Me";
pdfDoc.DocumentInformation.Author = "Naxi";
PdfCertificate pdfCertificate = new PdfCertificate(infoCertifikat);
//Normal signing
//Syncfusion.Pdf.Security.PdfSignature signature1 = new Syncfusion.Pdf.Security.PdfSignature(pdfDoc, pdfDoc.Pages[0], pdfCertificate, "DigitalSign");
//External signing becouse of HSM type of certificate
Syncfusion.Pdf.Security.PdfSignature signature1 = new Syncfusion.Pdf.Security.PdfSignature(pdfDoc, pdfDoc.Pages[0], null, "DigitalSign");
signature1.ComputeHash += Signature_ComputeHash1;
signature1.Bounds = new System.Drawing.RectangleF((6 * 25.4f / 0.352777778f), (9.3f * 25.4f / 0.352777778f), 65, 25);
signature1.ContactInfo = "Contact";
signature1.LocationInfo = "World";
signature1.Reason = "I want it";
PdfStandardFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 3.8f);
float row_height = 4.2f;
signature1.Appearance.Normal.Graphics.DrawString("Digitally Signed by " + signature1.ContactInfo, font, PdfBrushes.Black, 0, row_height * 1);
signature1.Appearance.Normal.Graphics.DrawString("Reason: " + signature1.Reason, font, PdfBrushes.Black, 0, row_height * 2);
signature1.Appearance.Normal.Graphics.DrawString("Location: " + signature1.LocationInfo, font, PdfBrushes.Black, 0, row_height * 3);
signature1.Appearance.Normal.Graphics.DrawString((DateTime.Now).ToString(), font, PdfBrushes.Black, 0, row_height * 4);
pdfDoc.Save("document_signed.pdf");
pdfDoc.Close(true);
}
}
private static void Signature_ComputeHash1(object sender, PdfSignatureEventArgs ars)
{
//Get the document bytes
byte[] documentBytes = ars.Data;
SignedCms signedCms = new SignedCms(new ContentInfo(documentBytes), detached: true);
var cmsSigner = new CmsSigner(infoCertifikat);
//Set the digest algorithm SHA256
//cmsSigner.DigestAlgorithm = new Oid("1.3.6.1.4.1.311.10.3.12"); //Document signing – just tried
//cmsSigner.DigestAlgorithm = new Oid("1.2.840.113549.1.1.11"); //SHA256RSA
//cmsSigner.DigestAlgorithm = new Oid("1.2.840.113549.1.1.5"); //SHA1RSA
//cmsSigner.DigestAlgorithm = new Oid("1.3.14.3.2.26"); //SHA1
cmsSigner.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"); //SHA256
cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly; //Without this it throws CryptographicException: A certificate chain could not be bulit to a trusted root authority. (only in production)
signedCms.ComputeSignature(cmsSigner);
//Embed the encoded digital signature to the PDF document
ars.SignedData = signedCms.Encode();
}
}
}
I tried use different DigestAlgorithm. (commented in code) But i dont't know which i should use.
Im building it for Platform target x64 because without it it causes:
CryptographicException: The keyset is not defined. at System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner signer, Boolean silent, DafeCryptoProvHandle)
There is censored certificate used on production:
My certificates on develop have Key Usage: Signing document ,which is missing on production. Or Enhanced Key Usage is missing something?
Thank you for any sugesstion.
UPDATE: So, I made i little steps in different few ways which look hopefully, but not mutch.
- I tried Normal signing of Syncfusion and set CryptographicStandard.CADES
Syncfusion.Pdf.Security.PdfSignature signature1 = new Syncfusion.Pdf.Security.PdfSignature(pdfDoc, pdfDoc.Pages[0], pdfCertificate, "DigitalSign");
signature1.Settings.CryptographicStandard = CryptographicStandard.CADES;
Its make signed document and crash the program. Like without any exception.
- I looked on way, which was used some time ago and i find out, that it was signing with hashSHA1, RSA + PKCS#1.
So, i tried in external way use oid:
cmsSigner.DigestAlgorithm = new Oid("1, 3, 36, 3, 3, 1, 1"); //RSA + SHA1
And that causes: CryptographicsException: The object identifier is poorly formatted. at SignedCms.Sign(...)
- And another way Im triying is invating colleague, so we can suffer colletively.
I dont know what Im doing.
Update 2:
So, the right way is probably using external with SHA1. Signing document works, but when program ends, the program don't close like normal but stops working. The same thing do microsoft application certutil. After lists certificates it stops working.
This is new info about that certificate. Its in HSM provided by Luna.
================ Certificate 0 ================
Serial Number: ...
Issuer: ...
NotBefore: ...
NotAfter: ...
Subject: ...
Non-root Certificate
Cert Hash(sha1): 9f
Key Container = ...
Provider = Luna enhanced RSA and AES provider for Microsoft Windows
Private key is NOT exportable
ERROR: Could not verify certificate public key against private key
Revocation check skipped -- server offline
Certificate is valid