3 // Copyright (c) Microsoft Corporation. All rights reserved.
13 namespace System.Security.Cryptography.X509Certificates {
14 using System.Globalization;
15 using System.Runtime.InteropServices;
16 using System.Security.Cryptography;
19 public enum X500DistinguishedNameFlags {
23 UseSemicolons = 0x0010,
24 DoNotUsePlusSign = 0x0020,
25 DoNotUseQuotes = 0x0040,
29 UseUTF8Encoding = 0x1000,
30 UseT61Encoding = 0x2000,
31 ForceUTF8Encoding = 0x4000,
34 public sealed class X500DistinguishedName : AsnEncodedData {
35 private string m_distinguishedName = null;
41 internal X500DistinguishedName (CAPI.CRYPTOAPI_BLOB encodedDistinguishedNameBlob) : base (new Oid(), encodedDistinguishedNameBlob) {}
43 public X500DistinguishedName (byte[] encodedDistinguishedName) : base(new Oid(), encodedDistinguishedName) {}
45 public X500DistinguishedName (AsnEncodedData encodedDistinguishedName) : base(encodedDistinguishedName) {}
47 public X500DistinguishedName (X500DistinguishedName distinguishedName) : base((AsnEncodedData) distinguishedName) {
48 m_distinguishedName = distinguishedName.Name;
51 public X500DistinguishedName (string distinguishedName) : this(distinguishedName, X500DistinguishedNameFlags.Reversed) {}
53 public X500DistinguishedName (string distinguishedName, X500DistinguishedNameFlags flag) : base(new Oid(), Encode(distinguishedName, flag)) {
54 m_distinguishedName = distinguishedName;
63 if (m_distinguishedName == null)
64 m_distinguishedName = Decode(X500DistinguishedNameFlags.Reversed);
65 return m_distinguishedName;
73 public string Decode (X500DistinguishedNameFlags flag) {
74 uint dwStrType = CAPI.CERT_X500_NAME_STR | MapNameToStrFlag(flag);
76 byte[] encodedDistinguishedName = this.m_rawData;
77 fixed (byte * pbEncoded = encodedDistinguishedName) {
78 CAPI.CRYPTOAPI_BLOB nameBlob;
79 IntPtr pNameBlob = new IntPtr(&nameBlob);
80 nameBlob.cbData = (uint) encodedDistinguishedName.Length;
81 nameBlob.pbData = new IntPtr(pbEncoded);
83 uint cchDecoded = CAPI.CertNameToStrW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
86 SafeLocalAllocHandle.InvalidHandle,
89 throw new CryptographicException(CAPI.CERT_E_INVALID_NAME);
91 using (SafeLocalAllocHandle pwszDecodeName = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(2 * cchDecoded))) {
92 if (CAPI.CertNameToStrW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
97 throw new CryptographicException(CAPI.CERT_E_INVALID_NAME);
98 return Marshal.PtrToStringUni(pwszDecodeName.DangerousGetHandle());
104 public override string Format (bool multiLine) {
106 // We must override to use the "numeric" pointer version of
107 // CryptFormatObject, since X509 DN does not have an official OID.
110 // Return empty string if no data to format.
111 if (m_rawData == null || m_rawData.Length == 0)
114 return CAPI.CryptFormatObject(CAPI.X509_ASN_ENCODING,
115 multiLine ? CAPI.CRYPT_FORMAT_STR_MULTI_LINE : 0,
116 new IntPtr(CAPI.X509_NAME),
124 private unsafe static byte[] Encode (string distinguishedName, X500DistinguishedNameFlags flag) {
125 if (distinguishedName == null)
126 throw new ArgumentNullException("distinguishedName");
129 uint dwStrType = CAPI.CERT_X500_NAME_STR | MapNameToStrFlag(flag);
131 if (!CAPI.CertStrToNameW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
138 throw new CryptographicException(Marshal.GetLastWin32Error());
140 byte[] encodedName = new byte[cbEncoded];
141 fixed (byte * pbEncoded = encodedName) {
142 if (!CAPI.CertStrToNameW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
146 new IntPtr(pbEncoded),
149 throw new CryptographicException(Marshal.GetLastWin32Error());
155 private static uint MapNameToStrFlag (X500DistinguishedNameFlags flag) {
156 // All values or'ed together. Change this if you add values to the enumeration.
157 uint allFlags = 0x71F1;
158 uint dwFlags = (uint) flag;
159 if ((dwFlags & ~allFlags) != 0)
160 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Arg_EnumIllegalVal), "flag"));
164 if ((flag & X500DistinguishedNameFlags.Reversed) == X500DistinguishedNameFlags.Reversed)
165 dwStrType |= CAPI.CERT_NAME_STR_REVERSE_FLAG;
167 if ((flag & X500DistinguishedNameFlags.UseSemicolons) == X500DistinguishedNameFlags.UseSemicolons)
168 dwStrType |= CAPI.CERT_NAME_STR_SEMICOLON_FLAG;
169 else if ((flag & X500DistinguishedNameFlags.UseCommas) == X500DistinguishedNameFlags.UseCommas)
170 dwStrType |= CAPI.CERT_NAME_STR_COMMA_FLAG;
171 else if ((flag & X500DistinguishedNameFlags.UseNewLines) == X500DistinguishedNameFlags.UseNewLines)
172 dwStrType |= CAPI.CERT_NAME_STR_CRLF_FLAG;
174 if ((flag & X500DistinguishedNameFlags.DoNotUsePlusSign) == X500DistinguishedNameFlags.DoNotUsePlusSign)
175 dwStrType |= CAPI.CERT_NAME_STR_NO_PLUS_FLAG;
176 if ((flag & X500DistinguishedNameFlags.DoNotUseQuotes) == X500DistinguishedNameFlags.DoNotUseQuotes)
177 dwStrType |= CAPI.CERT_NAME_STR_NO_QUOTING_FLAG;
179 if ((flag & X500DistinguishedNameFlags.ForceUTF8Encoding) == X500DistinguishedNameFlags.ForceUTF8Encoding)
180 dwStrType |= CAPI.CERT_NAME_STR_FORCE_UTF8_DIR_STR_FLAG;
182 if ((flag & X500DistinguishedNameFlags.UseUTF8Encoding) == X500DistinguishedNameFlags.UseUTF8Encoding)
183 dwStrType |= CAPI.CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG;
184 else if ((flag & X500DistinguishedNameFlags.UseT61Encoding) == X500DistinguishedNameFlags.UseT61Encoding)
185 dwStrType |= CAPI.CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;