2

我想列出系统上安装的所有 CSP 和 CNG 提供程序,但我在 C# 中找不到这样做的好方法。对于 CSP,我可以枚举某个注册表项(不优雅,但功能齐全),但我一直无法找到任何方法来获取 CNG 提供程序的列表。

.NET 中是否有任何远程类似System.Security.Cryptography.Get[CSP/CNG]Providers()或类似逻辑/直截了当的东西可以使用?谢谢!

4

2 回答 2

1

据我所知,.NET Framework 中没有类似的东西。

对于 CSP 提供程序,枚举以下子项: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider

对于 CNG 提供程序,枚举以下子项: HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Cryptography\Providers

于 2018-02-08T18:02:29.247 回答
1

使用它来枚举 CSP 提供程序和容器:

using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace CspSample
{

   struct Provider
   {
      public string Name { get; set; }
      public int Type { get; set; }
   }

    class CspUtils
    {
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool CryptEnumProviderTypes(
 uint dwIndex,
 uint pdwReserved,
 uint dwFlags,
 [In] ref uint pdwProvType,
 StringBuilder pszTypeName,
 [In] ref uint pcbTypeName);


        [DllImport("Advapi32.dll")]
        private static extern bool CryptEnumProviders(
            int dwIndex,
            IntPtr pdwReserved,
            int dwFlags,
            ref int pdwProvType,
            StringBuilder pszProvName,
            ref int pcbProvName);

        public static List<Provider> ListAllProviders()
        {
            List<Provider> installedCSPs = new List<Provider>();
            int cbName;
            int dwType;
            int dwIndex;
            StringBuilder pszName;
            dwIndex = 0;
            dwType = 1;
            cbName = 0;
            while (CryptEnumProviders(dwIndex, IntPtr.Zero, 0, ref dwType, null, ref cbName))
            {
                pszName = new StringBuilder(cbName);

                if (CryptEnumProviders(dwIndex++, IntPtr.Zero, 0, ref dwType, pszName, ref cbName))
                {
                    installedCSPs.Add(new Provider { Name = pszName.ToString(), Type = dwType });
                }
            }
            return installedCSPs;
        }


        const int PP_ENUMCONTAINERS = 2;
        const int PROV_RSA_FULL = 1;
        const int ERROR_MORE_DATA = 234;
        const int ERROR_NO_MORE_ITEMS = 259;
        const int CRYPT_FIRST = 1;
        const int CRYPT_NEXT = 2;
        //TODO: Find how to disable this flag (not machine keystore)
        const int CRYPT_MACHINE_KEYSET = 0x20;
        const int CRYPT_VERIFYCONTEXT = unchecked((int)0xF0000000);

        public static IList<string> EnumerateKeyContainers(string providerName, int providerType)
        {
            ProvHandle prov;
            if (!CryptAcquireContext(out prov, null, providerName, providerType, CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT))
                throw new Win32Exception(Marshal.GetLastWin32Error());

            List<string> list = new List<string>();
            IntPtr data = IntPtr.Zero;
            try
            {
                int flag = CRYPT_FIRST;
                int len = 0;
                if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, IntPtr.Zero, ref len, flag))
                {
                    if (Marshal.GetLastWin32Error() != ERROR_MORE_DATA)
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                data = Marshal.AllocHGlobal(len);
                do
                {
                    if (!CryptGetProvParam(prov, PP_ENUMCONTAINERS, data, ref len, flag))
                    {
                        if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS)
                            break;

                        //throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    list.Add(Marshal.PtrToStringAnsi(data));
                    flag = CRYPT_NEXT;
                }
                while (true);
            }
            finally
            {
                if (data != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(data);
                }

                prov.Dispose();
            }
            return list;
        }

        private sealed class ProvHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            public ProvHandle()
                : base(true)
            {
            }

            protected override bool ReleaseHandle()
            {
                return CryptReleaseContext(handle, 0);
            }

            [DllImport("advapi32.dll")]
            private static extern bool CryptReleaseContext(IntPtr hProv, int dwFlags);
        }


        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern bool CryptAcquireContext(out ProvHandle phProv, string pszContainer, string pszProvider, int dwProvType, int dwFlags);

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool CryptGetProvParam(ProvHandle hProv, int dwParam, IntPtr pbData, ref int pdwDataLen, int dwFlags);
    }
}
于 2020-10-06T09:45:03.740 回答