Some time ago I've posted a simple code example that will retrieve registered CSPs: Get registered CSPs on the system. The code was updated to provide detailed information about supported algorithms and protocols by particular CSP. Updated version of this code is shipped with my PowerShell PKI module as a Get-CryptographicServiceProvider cmdlet. The output is pretty informative:
PS C:\> $CSP[1] Name Type SupportedAlgorithms ---- ---- ------------------- Microsoft Base Cryptographic Provider v1.0 RSA Full (Signature and Key Exchange) {RC2, RC4, DES, SHA-1...} PS C:\> $CSP[1].SupportedAlgorithms Name DefaultKeyLength MinKeyLength MaxKeyLength Protocols ---- ---------------- ------------ ------------ --------- RC2 40 40 56 RC4 40 40 56 DES 56 56 56 SHA-1 160 160 160 {Signing protocol} MD2 128 128 128 {Signing protocol} MD4 128 128 128 {Signing protocol} MD5 128 128 128 {Signing protocol} SSL3 SHAMD5 288 288 288 MAC 0 0 0 RSA_SIGN 512 384 16384 {Internet protocol security (IPsec) protocol... RSA_KEYX 512 384 1024 {Internet protocol security (IPsec) protocol... HMAC 0 0 0 PS C:\>
However existing code is limited to legacy CSPs and do not support any CNG (Cryptography Next Generation) CSPs. To address this limitation I wrote another function for CNG providers. As usually the code uses p/invoke to get required information:
$ncryptsignature = @' [DllImport("ncrypt.dll", SetLastError = true)] public static extern uint NCryptEnumStorageProviders( ref uint pImplCount, ref IntPtr ppImplList, uint dwFlags ); [DllImport("ncrypt.dll", SetLastError = true)] public static extern uint NCryptOpenStorageProvider( ref IntPtr phProvider, [MarshalAs(UnmanagedType.LPWStr)] string pszProviderName, uint dwFlags ); [DllImport("ncrypt.dll", SetLastError = true)] public static extern uint NCryptEnumAlgorithms( IntPtr hProvider, uint dwAlgOperations, ref int pdwAlgCount, ref IntPtr ppAlgList, uint dwFlags ); [DllImport("ncrypt.dll", SetLastError = true)] public static extern uint NCryptFreeBuffer( IntPtr pvInput ); [DllImport("ncrypt.dll", SetLastError = true)] public static extern uint NCryptFreeObject( IntPtr phProvider ); [StructLayout(LayoutKind.Sequential)] public struct NCryptProviderName { [MarshalAs(UnmanagedType.LPWStr)] public string pszName; [MarshalAs(UnmanagedType.LPWStr)] public string pszComment; }; [StructLayout(LayoutKind.Sequential)] public struct NCryptAlgorithmName { [MarshalAs(UnmanagedType.LPWStr)] public string pszName; public uint dwClass; public uint dwAlgOperations; public uint dwFlags; }; '@ Add-Type @' namespace PKI { namespace ServiceProviders { public class CspCNG { public string Name; public string Comments; public ALG_ID_CNG[] SupportedAlgorithms; } public class ALG_ID_CNG { public string Name; public string Interface; public string[] Operations; } } } '@ try {Add-Type -MemberDefinition $ncryptsignature -Namespace PKI -Name nCrypt} catch {$NoCNG = $true; return} #region enumerations $Interface = @{3 = "Asymmetric encryption"; 4 = "Secret agreement"; 5 = "Signature interface"; 0x00010001 = "Key storage interface"; 0x00010002 = "SChannel interface"; 0x00010003 = "SChannel signature interface"} #endregion [UInt32]$pImplCount = 0 [IntPtr]$ppImplList = [IntPtr]::Zero $Return = [PKI.nCrypt]::NCryptEnumStorageProviders([ref]$pImplCount,[ref]$ppImplList,0) if (!$Return) { $pvInput = $ppImplList $Names = $(for ($n = 0; $n -lt $pImplCount; $n++) { [Runtime.InteropServices.Marshal]::PtrToStructure($ppImplList,[Type][PKI.nCrypt+NCryptProviderName]) [IntPtr]$ppImplList = [int]$ppImplList + [Runtime.InteropServices.Marshal]::SizeOf([Type][PKI.nCrypt+NCryptProviderName]) }) | %{$_.pszName} [void][PKI.nCrypt]::NCryptFreeBuffer($pvInput) } else {Write-Warning "The handle is invalid."} foreach ($pszProviderName in $Names) { $CSP = New-Object PKI.ServiceProviders.CspCNG $CSP.Name = $pszProviderName [IntPtr]$phProvider = [IntPtr]::Zero $Return = [PKI.nCrypt]::NCryptOpenStorageProvider([ref]$phProvider,$pszProviderName,0) if (!$Return) { $pdwAlgCount = 0 $ppAlgList = [IntPtr]::Zero $dwAlgOperations = 0x0 $Return = [PKI.nCrypt]::NCryptEnumAlgorithms($phProvider,$dwAlgOperations,[ref]$pdwAlgCount,[ref]$ppAlgList,0) if (!$Return) { $pvInput = $ppAlgList for ($n = 0; $n -lt $pdwAlgCount; $n++) { $AlgID = [Runtime.InteropServices.Marshal]::PtrToStructure($ppAlgList,[Type][PKI.nCrypt+NCryptAlgorithmName]) $options = 4,8,16 | %{[int]$AlgID.dwAlgOperations -band $_} | ?{$_} $Alg = New-Object PKI.ServiceProviders.ALG_ID_CNG -Property @{ Name = $AlgID.pszName Interface = $Interface[[int]$AlgID.dwClass] Operations = switch ($options) { 4 {"Asymmetric encryption"} 8 {"Secret agreement"} 16 {"Signature"} } } $CSP.SupportedAlgorithms += $Alg [IntPtr]$ppAlgList = [int]$ppAlgList + [Runtime.InteropServices.Marshal]::SizeOf([Type][PKI.nCrypt+NCryptAlgorithmName]) } $CSP [void][PKI.nCrypt]::NCryptFreeBuffer($pvInput) } else {Write-Warning "Parameter is incorrect."} [void][PKI.nCrypt]::NCryptFreeObject($phProvider) } else {Write-Warning "The handle is invalid."} }
And here is output information:
PS C:\> $CSP = Get-CSP PS C:\> $CSP Name Comments SupportedAlgorithms ---- -------- ------------------- Microsoft Software Key Storage Provider {RSA, DH, DSA, ECDH_P256...} Microsoft Smart Card Key Storage Pro... {RSA, ECDH_P256, ECDH_P384, ECDH_P52... PS C:\> $CSP[0].SupportedAlgorithms Name Interface Operations ---- --------- ---------- RSA Asymmetric encryption {Asymmetric encryption, Signature} DH Secret agreement {Secret agreement} DSA Signature interface {Signature} ECDH_P256 Secret agreement {Secret agreement, Signature} ECDH_P384 Secret agreement {Secret agreement, Signature} ECDH_P521 Secret agreement {Secret agreement, Signature} ECDSA_P256 Signature interface {Signature} ECDSA_P384 Signature interface {Signature} ECDSA_P521 Signature interface {Signature} PS C:\>
Currently Microsoft provides only 2 CNG crypto providers: Microsoft Software Key Storage Provider and Microsoft Smart Card Key Storage Provider. I'll include this sample to my PS PKI module next release.
Many thanks for the post, but it didn't work well enough for me - these worked better. C# http://technet.microsoft.com/en-us/library/ff182308(v=ws.10).aspx // Investigating the Advanced Cryptographic Algorithms C++ Equivalent http://msdn.microsoft.com/en-us/library/windows/desktop/bb931371(v=vs.85).aspx // Enumerating Installed Providers
Legacy CSPs are discussed here: http://en-us.sysadmins.lv/Lists/Posts/Post.aspx?ID=37 as I have to support Windows Server 2003/XP machines as well, your link won't work for me, as they utilize CertEnroll interfaces which are not available on legacy systems. I will move to CertEnroll once I don't have legacy system support.
yes, I''m aware about this change. The code was posted for previous versions of .NET (prior to these changes).
Post your comment:
Comments: