I was silent recently, because the blog was down. SharePoint is a nightmare for me. Hopefully, I’m writing my own web site with ASP.NET MVC and have plans to move to a reliable hosting in near future.
Today I want to discuss the question about extracting relative distinguished name (RDN) attributes from X.500 full distinguished name (DN) in PowerShell.
At first we need to understand how X.500 name is encoded. In X.501 the ASN.1 structure of distinguished name is defined as:
DistinguishedName ::= RDNSequence RDNSequence ::= SEQUENCE OF RelativeDistinguishedName RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue AttributeTypeAndValue ::= SEQUENCE { type AttributeType, value AttributeValue }
Where type is an object identifier of RDN attribute and value is a value associated with this particular attribute. Here is a graphical represntation of ASN.1 encoding:
Sequence of RDN attributes is wrapped by a sequence of SET tags (unordered sequence). Unfortunately, .NET doesn’t provide flexible ways to extract particular RDN from X.500 name. However, we can utilize ASN.1 parser from PowerShell PKI module to write quick function.
The idea consist of taking a X500DistinguishedName class and parsing encoded content in RawData property:
# important! Import PSPSKI module first! Import-Module PSPKI function Get-RDNAttribute { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [Security.Cryptography.X509Certificates.X500DistinguishedName]$Name ) $asn = New-Object SysadminsLV.Asn1Parser.Asn1Reader (,$Name.RawData) # move to a first element of SEQUENCE OF SET [void]$asn.MoveNext() do { # instantiate a new object that will be used to decode particular RDN $asn2 = New-Object SysadminsLV.Asn1Parser.Asn1Reader (,$asn.Payload) # move to an RDN object identifier [void]$asn2.MoveNext() # decode OID and store it in the vatriable $oid = [SysadminsLV.Asn1Parser.Asn1Utils]::DecodeObjectIdentifier($asn2.GetTagRawData()) # move to RDN value [void]$asn2.MoveNext() # decode value. We do specific decode for UniversalString and BMPString tags $value = switch ($asn2.Tag) { 28 {[Text.Encoding]::UTF32.GetString($asn2.GetPayload())} 30 {[Text.Encoding]::BigEndianUnicode.GetString($asn2.GetPayload())} default {[Text.Encoding]::UTF8.GetString($asn2.GetPayload())} } # return the RDN attribute New-Object psobject -Property @{ OID = $oid; Value = $value } } while ($asn.MoveNextCurrentLevel()) }
And the output would be similar:
[↓] [vPodans] $cert Thumbprint Subject ---------- ------- D4186B6E6D826A53C9A62EF2C0CD1B45C0E7E6C4 CN=login.live.com, OU=Passport, O=Microsoft Corporation, STREET=1 Microsof... [↓] [vPodans] Get-RDNAttribute $cert.SubjectName OID Value --- ----- System.Security.Cryptography.Oid US System.Security.Cryptography.Oid Washington System.Security.Cryptography.Oid Private Organization System.Security.Cryptography.Oid 600413485 System.Security.Cryptography.Oid US System.Security.Cryptography.Oid 98052 System.Security.Cryptography.Oid Washington System.Security.Cryptography.Oid Redmond System.Security.Cryptography.Oid 1 Microsoft Way System.Security.Cryptography.Oid Microsoft Corporation System.Security.Cryptography.Oid Passport System.Security.Cryptography.Oid login.live.com [↓] [vPodans] (Get-RDNAttribute $cert.SubjectName)[0].OID Value FriendlyName ----- ------------ 1.3.6.1.4.1.311.60.2.1.3 [↓] [vPodans] (Get-RDNAttribute $cert.SubjectName)[4].OID Value FriendlyName ----- ------------ 2.5.4.6 Country/Region [↓] [vPodans] (Get-RDNAttribute $cert.SubjectName)[5].OID Value FriendlyName ----- ------------ 2.5.4.17 PostalCode [↓] [vPodans] Get-RDNAttribute $cert.IssuerName OID Value --- ----- System.Security.Cryptography.Oid US System.Security.Cryptography.Oid VeriSign, Inc. System.Security.Cryptography.Oid VeriSign Trust Network System.Security.Cryptography.Oid Terms of use at https://www.verisign.com/rpa (c)06 System.Security.Cryptography.Oid VeriSign Class 3 Extended Validation SSL SGC CA [↓] [vPodans] Get-RDNAttribute $cert.IssuerName OID Value --- ----- System.Security.Cryptography.Oid US System.Security.Cryptography.Oid VeriSign, Inc. System.Security.Cryptography.Oid VeriSign Trust Network System.Security.Cryptography.Oid Terms of use at https://www.verisign.com/rpa (c)06 System.Security.Cryptography.Oid VeriSign Class 3 Extended Validation SSL SGC CA [↓] [vPodans] (Get-RDNAttribute $cert.IssuerName)[0].OID Value FriendlyName ----- ------------ 2.5.4.6 Country/Region [↓] [vPodans] (Get-RDNAttribute $cert.IssuerName)[1].OID Value FriendlyName ----- ------------ 2.5.4.10 Organization [↓] [vPodans]
Plain and simple. However, notice that some OIDs are not translated automatically. This is because these OIDs are not registered in the system. Therefore, when searching, it is more reliable to use OID value. For example, to retrieve all OU attributes, you should use this form:
[↓] [vPodans] [System.Security.Cryptography.Oid]"Organizational Unit" Value FriendlyName ----- ------------ 2.5.4.11 OU [↓] [vPodans] Get-RDNAttribute $cert.IssuerName | ?{$_.oid.value -eq "2.5.4.11"} OID Value --- ----- System.Security.Cryptography.Oid VeriSign Trust Network System.Security.Cryptography.Oid Terms of use at https://www.verisign.com/rpa (c)06 [↓] [vPodans]
Also, note that RDN attribute in the X.500 name may appear multiple times, therefore you may expect a collection output when filtering them by attribute name.
Have a fun with PowerShell scripting!
Post your comment:
Comments: