Home > Software engineering >  Retrieve KeySpec Value from Certificate Using PowerShell
Retrieve KeySpec Value from Certificate Using PowerShell

Time:10-11

I am attempting to verify a certificate in the machine store has KeySpec set to AT_KEYEXCHANGE. Using certutil.exe does provide this information, but requires string parsing. I would prefer to avoid string parsing to avoid assumptions on the output of certutil.exe that I do not know will always be true across different versions of Windows.

I have looked at the properties and methods for System.Security.Cryptography.X509Certificates.X509Certificate2 and System.Security.Cryptography.X509Certificates.RSACertificateExtensions.

How can I retrieve the KeySpec from the certificate in the certificate store?

CodePudding user response:

I suspect the following isn't a direct equivalent of what you're looking for, but perhaps it ultimately contains the information you're looking for; it is based on applying Get-ChildItem to PowerShell's Cert: drive:

Get-ChildItem Cert:\LocalMachine -Recurse | 
  Where-Object { -not $_.PSIsContainer -and $_.EnhancedKeyUsageList }
    Format-List @{ 
                  Name='KeyUsage'
                  Expression={ ($_.EnhancedKeyUsageList.FriendlyName) -join ', ' } 
                },
                Subject,
                Thumbprint

Note: The behavior changed between Windows PowerShell and PowerShell (Core) 7.1, both in terms of the default output formatting and how many certificates report a non-null .EnhancedKeyUsageList property value: Windows PowerShell reports many more.

In PowerShell (Core) 7.1, the above yields something like:

KeyUsage   : Code Signing, Time Stamping, Encrypting File System
Subject    : CN=UTN-USERFirst-Object, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, S=UT, C=US
Thumbprint : 6E6D0A31B454AF8E8F06CFEB438351056204C28C

KeyUsage   : Server Authentication, Client Authentication, , 
Subject    : OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign, OU=VeriSign International Server CA - Class 3, OU="VeriSign, Inc.", O=VeriSign Trust Network
Thumbprint : 13E8AB4167D5830F9440093564AC0211C2D26E62


KeyUsage   : Code Signing, Windows Hardware Driver Verification
Subject    : CN=Microsoft Windows Hardware Compatibility, OU=Microsoft Corporation, OU=Microsoft Windows Hardware Compatibility Intermediate CA, OU=Copyright (c) 1997 Microsoft Corp.
Thumbprint : 75F7C7CDC6900B145CF9242910EC037D423F369F

KeyUsage   : Code Signing, Time Stamping, Encrypting File System
Subject    : CN=UTN-USERFirst-Object, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, S=UT, C=US
Thumbprint : 59E6BAC5EFE4C1A11B889146BD983F468C5103BA

KeyUsage   : Server Authentication
Subject    : CN=localhost
Thumbprint : 81F6D78B7A53AE3D03264D178A2E0FEBC978C4D8

CodePudding user response:

I was able to find the KeySpec with the help from here and here. The CspKeyContainerInfo class contains a property called KeyNumber, which is what certutil refers to as KeySpec.

There are two methods I have found. One that works for only PowerShell 5 and the other that works for both PowerShell 5 and 7.

PowerShell 5 Only

$Cert = (Get-ChildItem -Path Cert:\LocalMachine\My)[1]
$Cert.PrivateKey.CspKeyContainerInfo.KeyNumber

PowerShell 5 and 7

$Cert = (Get-ChildItem -Path Cert:\LocalMachine\My)[1]
$PrivateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Cert)
$CngProvider = [System.Security.Cryptography.CngProvider]::new($PrivateKey.Key.Provider)
$CngKey = [System.Security.Cryptography.CngKey]::Open($PrivateKey.Key.KeyName,  $CngProvider, [System.Security.Cryptography.CngKeyOpenOptions]::MachineKey)
$CspParameters = [System.Security.Cryptography.CspParameters]::New(1, $CngKey.Provider, $CngKey.KeyName)
$CspParameters.Flags = [System.Security.Cryptography.CspProviderFlags]::UseMachineKeyStore
$CspKeyContainerInfo = [System.Security.Cryptography.CspKeyContainerInfo]::New($CspParameters)
$CspKeyContainerInfo.KeyNumber
  • Related