Hi,
How to check which of PdfSignatureLevel is signed document ?
Regards
Paul
Hi,
How to check which of PdfSignatureLevel is signed document ?
Regards
Paul
Hi Paul,
GemBox.Pdf currently lacks this feature because implementing it in full compliance requires a lot of effort to check and validate various signature-related data.
Here is an extension method that approximates this feature. The logic of it is based on the PdfSignatureLevel documentation.
internal static class GemBoxPdfExtensions
{
public static PdfSignatureLevel? GetSignatureLevel(this PdfSignature signature, PdfDocument document)
{
PdfSignatureLevel? signatureLevel;
var signatureContent = signature.Content;
System.Security.Cryptography.Pkcs.SignedCms signedCms;
try
{
signedCms = new System.Security.Cryptography.Pkcs.SignedCms();
signedCms.Decode(signatureContent.GetRawData());
}
catch
{
return null;
}
if (signedCms.SignerInfos.Count != 1)
return null;
var signerInfo = signedCms.SignerInfos[0];
if (signature.Format == PdfSignatureFormat.CAdES)
{
// See https://tools.ietf.org/html/rfc5126.html#page-34
const string
// See https://tools.ietf.org/html/rfc5035#page-7
essSigningCertificateOid = "1.2.840.113549.1.9.16.2.12",
// See https://tools.ietf.org/html/rfc5035#page-4
essSigningCertificateV2Oid = "1.2.840.113549.1.9.16.2.47";
if (signerInfo.SignedAttributes.OfType<System.Security.Cryptography.CryptographicAttributeObject>().Count(attr => attr.Oid.Value is essSigningCertificateOid or essSigningCertificateV2Oid) == 1 &&
signatureContent.ValidationInfo.CertificateRevocationLists.Count == 0 && signatureContent.ValidationInfo.OnlineCertificateStatusProtocolResponses.Count == 0 &&
signature.Date is not null &&
(signatureContent.PolicyIdentifier is null || string.IsNullOrWhiteSpace(signature.Reason)))
{
if (signatureContent.TimestampToken is not null || document.Form.Fields.OfType<PdfSignatureField>().Any(f => f.Value is PdfSignature s && s.Format == PdfSignatureFormat.RFC3161 && s.FileSectionDepth >= 0 && s.FileSectionDepth < signature.FileSectionDepth))
{
if (document.SecurityStore.Certificates.Count > 0 && (document.SecurityStore.CertificateRevocationLists.Count > 0 || document.SecurityStore.OnlineCertificateStatusProtocolResponses.Count > 0))
{
if (document.Form.Fields.OfType<PdfSignatureField>().Any(f => f.Value is PdfSignature s && s.Format == PdfSignatureFormat.RFC3161 && s.FileSectionDepth == 0) && signature.FileSectionDepth > 0)
signatureLevel = PdfSignatureLevel.PAdES_B_LTA;
else
signatureLevel = PdfSignatureLevel.PAdES_B_LT;
}
else
signatureLevel = PdfSignatureLevel.PAdES_B_T;
}
else
signatureLevel = PdfSignatureLevel.PAdES_B_B;
}
else
signatureLevel = PdfSignatureLevel.None;
}
else if (signature.Format == PdfSignatureFormat.PKCS7)
{
signatureLevel = PdfSignatureLevel.None;
}
else
{
signatureLevel = null;
}
return signatureLevel;
}
}
And here is a code snippet that shows how to use this extension method on signatures from files created with PAdES examples:
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var testFiles = new string[]
{
"PAdES B-B.pdf",
"PAdES B-T.pdf",
"PAdES B-LT.pdf",
"PAdES B-LTA.pdf"
};
foreach (var testFile in testFiles)
using (var document = PdfDocument.Load(Path.Combine(desktop, testFile)))
{
foreach (var field in document.Form.Fields)
if (field.FieldType == PdfFieldType.Signature && field is PdfSignatureField signatureField && signatureField.Value is PdfSignature signature)
{
var signatureLevel = signature.GetSignatureLevel(document);
Console.WriteLine($"Signature level of a signature on the field '{field.Name}' from the file '{testFile}' is {signatureLevel}.");
}
}
Regards,
Stipo
Hi!
Thanks for reply!
it works, but on B-LT pdf i have problem
the Acrobat checks its B-LT Signature
but on this code returns as B-T :
Regards
Paul
update - its ok,works all fine !
Regards
Paul