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:

image

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!


Share this article:

Comments:


Post your comment:

Please, solve this little equation and enter result below. Captcha