1+ using Syncfusion . Pdf . Parsing ;
2+ using Syncfusion . Pdf . Security ;
3+ using System . Security . Cryptography . X509Certificates ;
4+
5+ // Load signed PDF
6+ using ( PdfLoadedDocument document = new PdfLoadedDocument ( Path . GetFullPath ( @"Data/Input.pdf" ) ) )
7+ {
8+ // Get the PDF form
9+ PdfLoadedForm form = document . Form ;
10+
11+ if ( form != null && form . Fields != null && form . Fields . Count > 0 )
12+ {
13+ foreach ( PdfLoadedField field in form . Fields )
14+ {
15+ // Check for signature field
16+ if ( field is PdfLoadedSignatureField signatureField && signatureField . IsSigned )
17+ {
18+ // Validate signature
19+ PdfSignatureValidationResult result = signatureField . ValidateSignature ( ) ;
20+
21+ if ( result ? . Certificates != null && result . Certificates . Count > 0 )
22+ {
23+ X509Certificate2 certificate = result . Certificates [ 0 ] ;
24+
25+ string policyId = GetCertificatePolicyOID ( certificate ) ;
26+
27+ if ( ! string . IsNullOrEmpty ( policyId ) )
28+ {
29+ Console . WriteLine ( $ "Policy OID: { policyId } ") ;
30+
31+ string certClass = MapCertificateClass ( policyId ) ;
32+ Console . WriteLine ( $ "Certificate Type: { certClass } ") ;
33+ }
34+ else
35+ {
36+ Console . WriteLine ( "❌ Certificate policy not found." ) ;
37+ }
38+
39+ Console . WriteLine ( "-----------------------------------" ) ;
40+ }
41+ }
42+ }
43+ }
44+ }
45+
46+ // Extract Certificate Policy OID (2.5.29.32)
47+ string GetCertificatePolicyOID ( X509Certificate2 certificate )
48+ {
49+ foreach ( X509Extension extension in certificate . Extensions )
50+ {
51+ if ( extension ? . Oid ? . Value == "2.5.29.32" )
52+ {
53+ string formatted = extension . Format ( true ) ;
54+
55+ // Example format contains: "Policy Identifier=OID"
56+ return ExtractPolicyID ( formatted ) ;
57+ }
58+ }
59+ return null ;
60+ }
61+
62+ // Extracts Policy Identifier from formatted string
63+ string ExtractPolicyID ( string policyText )
64+ {
65+ if ( string . IsNullOrEmpty ( policyText ) )
66+ return null ;
67+ const string keyword = "Policy Identifier=" ;
68+ int index = policyText . IndexOf ( keyword , StringComparison . OrdinalIgnoreCase ) ;
69+ if ( index < 0 )
70+ return null ;
71+ index += keyword . Length ;
72+ int endIndex = policyText . IndexOf ( "," , index ) ;
73+ string rawOid ;
74+ if ( endIndex > index )
75+ rawOid = policyText . Substring ( index , endIndex - index ) ;
76+ else
77+ rawOid = policyText . Substring ( index ) ;
78+ // Clean unwanted characters
79+ return CleanOID ( rawOid ) ;
80+ }
81+
82+ string CleanOID ( string oid )
83+ {
84+ if ( string . IsNullOrEmpty ( oid ) )
85+ return null ;
86+
87+ // Remove line breaks, tabs, spaces
88+ oid = oid . Replace ( "\r " , "" )
89+ . Replace ( "\n " , "" )
90+ . Replace ( "\t " , "" )
91+ . Trim ( ) ;
92+
93+ // Remove anything after invalid characters like '['
94+ int index = oid . IndexOfAny ( new char [ ] { '[' , ' ' } ) ;
95+ if ( index > 0 )
96+ oid = oid . Substring ( 0 , index ) ;
97+
98+ return oid . Trim ( ) ;
99+ }
100+
101+ // Map OID to Certificate Type
102+ string MapCertificateClass ( string oid )
103+ {
104+ switch ( oid )
105+ {
106+ case "2.16.356.100.2.1" :
107+ return "Class 1 Certificate" ;
108+
109+ case "2.16.356.100.2.2" :
110+ return "Class 2 Certificate" ;
111+
112+ case "2.16.356.100.2.3" :
113+ return "Class 3 Certificate" ;
114+
115+ case "2.16.840.1.114028.10.1.6" :
116+ return "DocuSign High Assurance (Equivalent to Class 3)" ;
117+
118+ default :
119+ return "Unknown / Custom Certificate Policy" ;
120+ }
121+ }
0 commit comments