CSP介绍、以及使用CryptoAPI枚举CSP并获取其属性

来源:互联网 发布:2017年云计算系统集成 编辑:程序博客网 时间:2024/06/05 20:15

from http://blog.csdn.net/yyfzy/article/details/46424731

CSP,全名为“加密服务提供者(Cryptographic Service Provider)”,是微软定义的一套密码服务API。

目前,常用的密码规范或者标准有3套:CSP,PKCS#11 和 国密标准。前两者主要是为RSA算法提供服务,当然PKCS#11最新的扩展也开始支持ECC算法。而国家密码管理制定的国密标准,主要提供SM2(实际上也是ECC)服务,当然国密标准同时支持RSA,不过大多数情况下RSA的应用还是使用CSP和PKCS#11来实现。


一、CSP为一个独立的密钥服务模块

CSP可以是软件,比如Windows自带的“Microsoft Base Cryptographic Provider v1.0”和“Microsoft Enhanced Cryptographic Provider v1.0”。

CSP也可以是硬件设备,通常是USBKey,比如飞天诚信等厂商生产的。


二、一个CSP对应一个密钥容器

CSP没有设备(Key)的概念,这点和PKCS11以及国密规范都不一样。一个CSP直接对应一个密钥容器。通过CSP名和容器名直接定位密钥模块,如果不指定容器名,则是定位缺省的容器(一般情况下为第一个容器)。所以对CSP来说,最好容器名要求唯一,一般是使用GUID来作为容器名的。

如果同一个CSP有多个设备,在需要确定使用哪个设备时(比如新建容器),CSP会弹出选择框,根据设备的SN来选择使用哪个设备。


三、一个密钥容器可以包含一对签名密钥、一对加密钥、一个签名证书以及一个加密证书

通常CSP的一个密钥容器只包含一对密钥对和对应的证书,但是理论上可以把签名密钥对和加密密钥对放在同一个容器,然后通过AT_SIGNATURE和AT_KEYEXCHANGE来查找密钥。


四、枚举系统中的CSP

系统中的CSP,都在注册表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider目录下,我们可以通过API:CryptEnumProviders()来枚举想要的CSP,如下面代码所示:

[cpp] view plain copy
  1. void CTestCSPDlg::EnumCSP()  
  2. {  
  3.     DWORD dwIndex = 0;  
  4.     DWORD dwType = 0;  
  5.     DWORD dwNameLen = 0;  
  6.     CComboBox* pCSPList = (CComboBox*)GetDlgItem(IDC_COMBO_CSPLIST);  
  7.     pCSPList->ResetContent();  
  8.   
  9.     while (CryptEnumProviders(dwIndex, NULL, 0, &dwType, NULL, &dwNameLen))  
  10.     {     
  11.         DWORD dwItem = 0;  
  12.         TCHAR * pName = new TCHAR[dwNameLen + 1 ];  
  13.         if (CryptEnumProviders(dwIndex++, NULL, 0, &dwType, pName, &dwNameLen))  
  14.         {  
  15.             dwItem = pCSPList->AddString(pName);  
  16.             pCSPList->SetItemData(dwItem, dwType);  
  17.         }  
  18.         delete []pName;  
  19.     }  
  20.     pCSPList->SetCurSel(0);  
  21.     OnCbnSelchangeComboCsplist();  
  22. }  

五、获取CSP属性

得到CSP句柄之后,可以通过API:CryptGetProvParam()获取CSP的属性,比如该CSP具有的容器名、实现类型、支持算法等等。

比如下面的代码为获取当前CSP使用的容器名:

[cpp] view plain copy
  1.     //获取CSP容器名称  
  2.     dwParamLen = 2048;  
  3.     memset(btParamData, 0, 2048);  
  4.     pList->InsertItem(dwIndex, _T("PP_CONTAINER"), 0);  
  5.     pList->SetItemText(dwIndex, 1, _T("密钥容器名称"));  
  6.     if (CryptGetProvParam(hProv, PP_CONTAINER, btParamData, &dwParamLen, 0))  
  7.     {  
  8.         TCHAR *tcValue = NULL;  
  9. #ifdef UNICODE  
  10.         tcValue = A2W((char*)btParamData);  
  11. #else  
  12.         tcValue = (char*)btParamData;  
  13. #endif  
  14.         pList->SetItemText(dwIndex, 2, tcValue);  
  15.     }  
  16.     else  
  17.     {  
  18.         pList->SetItemText(dwIndex, 2, _T("Failed!"));  
  19.     }  

下面的代码枚举CSP所有的容器名:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //获取CSP所有的容器名称  
  2. dwParamLen = 2048;  
  3. memset(btParamData, 0, 2048);  
  4. pList->InsertItem(dwIndex, _T("PP_ENUMCONTAINERS"), 0);  
  5. pList->SetItemText(dwIndex, 1, _T("所有容器名"));  
  6. if (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, btParamData, &dwParamLen, CRYPT_FIRST))  
  7. {  
  8.     CString strContianers;  
  9.     TCHAR *tcValue = NULL;  
  10. ifdef UNICODE  
  11.     tcValue = A2W((char*)btParamData);  
  12. else  
  13.     tcValue = btParamData;  
  14. endif  
  15.     strContianers += tcValue;  
  16.       
  17.     dwParamLen = 2048;  
  18.     memset(btParamData, 0, 2048);  
  19.     while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, btParamData, &dwParamLen, CRYPT_NEXT))  
  20.     {  
  21. ifdef UNICODE  
  22.         tcValue = A2W((char*)btParamData);  
  23. else  
  24.         tcValue = btParamData;  
  25. endif  
  26.         strContianers += _T("/");  
  27.         strContianers += tcValue;  
  28.     }  
  29.     pList->SetItemText(dwIndex, 2, strContianers);  
  30. }  
  31. else  
  32. {  
  33.     pList->SetItemText(dwIndex, 2, _T("Failed!"));  
  34. }  


下面的代码获取CSP的所支持的算法:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.     //获取CSP所支持的算法信息  
  2.     dwParamLen = 2048;  
  3.     memset(btParamData, 0, 2048);  
  4.     pList->InsertItem(dwIndex, _T("PP_ENUMALGS"), 0);  
  5.     pList->SetItemText(dwIndex, 1, _T("支持的算法信息"));  
  6.     if (CryptGetProvParam(hProv, PP_ENUMALGS, btParamData, &dwParamLen, CRYPT_FIRST))  
  7.     {  
  8.         CString strAlgs;  
  9.         PROV_ENUMALGS* alg = (PROV_ENUMALGS*)btParamData;  
  10.         TCHAR *tcValue = NULL;  
  11. #ifdef UNICODE  
  12.         tcValue = A2W(alg->szName);  
  13. #else  
  14.         tcValue = alg->szName;  
  15. #endif  
  16.         strAlgs += tcValue;  
  17.           
  18.         dwParamLen = 2048;  
  19.         memset(btParamData, 0, 2048);  
  20.         while (CryptGetProvParam(hProv, PP_ENUMALGS, btParamData, &dwParamLen, CRYPT_NEXT))  
  21.         {  
  22.             alg = (PROV_ENUMALGS*)btParamData;  
  23. #ifdef UNICODE  
  24.             tcValue = A2W(alg->szName);  
  25. #else  
  26.             tcValue = alg->szName;  
  27. #endif  
  28.             strAlgs += _T("/");  
  29.             strAlgs += tcValue;  
  30.         }  
  31.         pList->SetItemText(dwIndex, 2, strAlgs);  
  32.     }  
  33.     else  
  34.     {  
  35.         pList->SetItemText(dwIndex, 2, _T("Failed!"));  
  36.     }  

等等。


如果需要详细代码,请下载本人枚举CSP的例子,下载连接为:枚举CSP并获取属性


1 0