Search code examples
.netpowershellcertificate

Certificates informations


When accessing the Windows certificate store, you can view a property called 'Description' in the "Details" tab. I am unable to retrieve this using a PowerShell or .NET command. Does anyone have this information, dear community?

$certs = Get-ChildItem Cert:\LocalMachine\My\
$certs[2] | select *

PSPath                   : Microsoft.PowerShell.Security\Certificate::LocalMachine\My\000000000000000
PSParentPath             : Microsoft.PowerShell.Security\Certificate::LocalMachine\My
PSChildName              : 000000000000000
PSDrive                  : Cert
PSProvider               : Microsoft.PowerShell.Security\Certificate
PSIsContainer            : False
EnhancedKeyUsageList     : {Authentication du serveur (1.3.6.1.5.5.7.3.1)}
DnsNameList              : {SERVER.DOMAIN.FR}
SendAsTrustedIssuer      : False
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty
PolicyId                 : {0000}
Archived                 : False
Extensions               : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}
FriendlyName             : FRIENDLY_NAME
IssuerName               : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter                 : 09/01/2027 16:38:30
NotBefore                : 10/01/2024 16:38:30
HasPrivateKey            : True
PrivateKey               : System.Security.Cryptography.RSACryptoServiceProvider
PublicKey                : System.Security.Cryptography.X509Certificates.PublicKey
RawData                  : {48, 130, 6, 211...}
SerialNumber             : 000000000000000
SubjectName              : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm       : System.Security.Cryptography.Oid
Thumbprint               : 000000000000000
Version                  : 3
Handle                   : 000000000000000
Issuer                   : CN=DOMAIN.FR, DC=DOMAIN, DC=FR
Subject                  : CN=SERVER.DOMAIN.FR, OU=DOMAIN, L=CITY, S=STATE, C=UK

Solution

  • Description is not part of the certificate itself and is vendor specific. For windows, you can use this code to pull the description

    $signature = @"
    [DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool CertGetCertificateContextProperty(
        IntPtr pCertContext,
        uint dwPropId,
        Byte[] pvData,
        ref uint pcbData
    );
    "@
    
    Add-Type -MemberDefinition $signature -Namespace PKI -Name Crypt32
    $pcbData = 0
    # if the function returns False, then description is not specified.
    $CERT_DESCRIPTION_PROP_ID = 13
    
    $certs = Get-ChildItem Cert:\LocalMachine\My\ | Select-Object *,@{n='Description';e={
        if ([PKI.Crypt32]::CertGetCertificateContextProperty($_.Handle,$CERT_DESCRIPTION_PROP_ID,$null,[ref]$pcbData)) {
            # allocate a buffer to store property value
            $pvData = New-Object byte[] -ArgumentList $pcbData
            # call the function again to write actual data into allocated buffer
            [void][PKI.Crypt32]::CertGetCertificateContextProperty($_.Handle,$CERT_DESCRIPTION_PROP_ID,$pvData,[ref]$pcbData)
            # Description is null-terminated unicode string
            [Text.Encoding]::Unicode.GetString($pvData).TrimEnd()
        }
    }}
    

    Reference the accepted answer here

    EDIT I actually like this approach better, using a scriptproperty

    $certs = Get-ChildItem Cert:\LocalMachine\My\ | Add-Member -MemberType ScriptProperty -Name Description -Value {
        $signature = @"
        [DllImport("Crypt32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool CertGetCertificateContextProperty(
            IntPtr pCertContext,
            uint dwPropId,
            Byte[] pvData,
            ref uint pcbData
        );
    "@
    
        if($null -eq ('PKI.Crypt32' -as [type])){
            Add-Type -MemberDefinition $signature -Namespace PKI -Name Crypt32
        }
    
        $pcbData = 0
        # if the function returns False, then description is not specified.
        $CERT_DESCRIPTION_PROP_ID = 13
    
        if ([PKI.Crypt32]::CertGetCertificateContextProperty($this.Handle,$CERT_DESCRIPTION_PROP_ID,$null,[ref]$pcbData)) {
            # allocate a buffer to store property value
            $pvData = New-Object byte[] -ArgumentList $pcbData
            # call the function again to write actual data into allocated buffer
            [void][PKI.Crypt32]::CertGetCertificateContextProperty($this.Handle,$CERT_DESCRIPTION_PROP_ID,$pvData,[ref]$pcbData)
            # Description is null-terminated unicode string
            [Text.Encoding]::Unicode.GetString($pvData).TrimEnd()
        }
    } -PassThru