33using System . Diagnostics . Metrics ;
44using System . Linq ;
55using System . Security . AccessControl ;
6+ using System . Security . Cryptography . X509Certificates ;
67using System . Text ;
78using System . Threading . Tasks ;
89
@@ -20,6 +21,11 @@ public class CertificateSubject
2021 /// </summary>
2122 public string CommonName { get ; set ; }
2223
24+ /// <summary>
25+ /// Gets or sets the email address (E) of the certificate subject.
26+ /// </summary>
27+ public string ? Email { get ; set ; }
28+
2329 /// <summary>
2430 /// Gets or sets the organization (O) of the certificate subject.
2531 /// </summary>
@@ -50,6 +56,32 @@ public class CertificateSubject
5056 /// </summary>
5157 public Dictionary < string , string > Unknown { get ; } = [ ] ;
5258
59+ /// <summary>
60+ /// Initializes a new instance of the <see cref="CertificateSubject"/> class with the specified X509Certificate2 certificate.
61+ /// </summary>
62+ /// <param name="certificate">
63+ /// The certificate to extract the subject from.
64+ /// </param>
65+ public CertificateSubject ( X509Certificate2 certificate ) : this ( certificate . Subject )
66+ {
67+ var commonName = certificate . GetNameInfo ( X509NameType . SimpleName , false ) ;
68+ if ( string . IsNullOrEmpty ( commonName ) )
69+ {
70+ commonName = certificate . GetNameInfo ( X509NameType . DnsName , false ) ;
71+ }
72+
73+ if ( ! string . IsNullOrEmpty ( commonName ) )
74+ {
75+ CommonName = commonName ;
76+ }
77+
78+ var email = certificate . GetNameInfo ( X509NameType . EmailName , false ) ;
79+ if ( ! string . IsNullOrEmpty ( email ) )
80+ {
81+ Email = email ;
82+ }
83+ }
84+
5385 /// <summary>
5486 /// Initializes a new instance of the <see cref="CertificateSubject"/> class with the specified subject string.
5587 /// </summary>
@@ -77,6 +109,9 @@ public CertificateSubject(string subject)
77109 case "CN" :
78110 CommonName = value ;
79111 break ;
112+ case "E" :
113+ Email = value ;
114+ break ;
80115 case "O" :
81116 Organization = value ;
82117 break ;
@@ -101,7 +136,7 @@ public CertificateSubject(string subject)
101136
102137 if ( string . IsNullOrEmpty ( CommonName ) )
103138 {
104- throw new ArgumentException ( "Common Name (CN) is required." ) ;
139+ CommonName = string . Empty ;
105140 }
106141 }
107142
@@ -110,16 +145,18 @@ public CertificateSubject(string subject)
110145 /// Initializes a new instance of the <see cref="CertificateSubject"/> class with the specified properties.
111146 /// </summary>
112147 /// <param name="commonName">Common Name (CN) - required.</param>
148+ /// <param name="email">Email (E) - optional.</param>
113149 /// <param name="organization">Organization (O) - optional.</param>
114150 /// <param name="organizationalUnit">Organizational Unit (OU) - optional.</param>
115151 /// <param name="locality">Locality (L) - optional.</param>
116152 /// <param name="state">State or Province (ST) - optional.</param>
117153 /// <param name="country">Country (C) - optional.</param>
118- public CertificateSubject ( string commonName , string ? organization , string ? organizationalUnit , string ? locality , string ? state , string ? country )
154+ public CertificateSubject ( string commonName , string ? email , string ? organization , string ? organizationalUnit , string ? locality , string ? state , string ? country )
119155 {
120156 Ensure . String . IsNotNullOrEmpty ( commonName , nameof ( commonName ) ) ;
121157
122158 CommonName = commonName ;
159+ Email = email ;
123160 Organization = organization ;
124161 OrganizationalUnit = organizationalUnit ;
125162 Locality = locality ;
@@ -141,27 +178,32 @@ public override string ToString()
141178 $ "CN={ CommonName } "
142179 } ;
143180
144- if ( ! string . IsNullOrWhiteSpace ( Organization ) )
181+ if ( ! string . IsNullOrEmpty ( Email ) )
182+ {
183+ components . Add ( $ "E={ Email } ") ;
184+ }
185+
186+ if ( ! string . IsNullOrEmpty ( Organization ) )
145187 {
146188 components . Add ( $ "O={ Organization } ") ;
147189 }
148190
149- if ( ! string . IsNullOrWhiteSpace ( OrganizationalUnit ) )
191+ if ( ! string . IsNullOrEmpty ( OrganizationalUnit ) )
150192 {
151193 components . Add ( $ "OU={ OrganizationalUnit } ") ;
152194 }
153195
154- if ( ! string . IsNullOrWhiteSpace ( Locality ) )
196+ if ( ! string . IsNullOrEmpty ( Locality ) )
155197 {
156198 components . Add ( $ "L={ Locality } ") ;
157199 }
158200
159- if ( ! string . IsNullOrWhiteSpace ( State ) )
201+ if ( ! string . IsNullOrEmpty ( State ) )
160202 {
161203 components . Add ( $ "ST={ State } ") ;
162204 }
163205
164- if ( ! string . IsNullOrWhiteSpace ( Country ) )
206+ if ( ! string . IsNullOrEmpty ( Country ) )
165207 {
166208 components . Add ( $ "C={ Country } ") ;
167209 }
0 commit comments