how check PdfSignatureLevel in Existing Signed PDF document

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

image

but on this code returns as B-T :

image

Regards
Paul

update - its ok,works all fine !

Regards
Paul