zoukankan      html  css  js  c++  java
  • CSP介绍、以及使用CryptoAPI枚举CSP并获取其属性

    CSP,全名为“加密服务提供者(Cryptographic Service Provider)”,是微软定义的一套password服务API。眼下经常使用的password规范或者标准有3套:CSP,PKCS#11和国密标准。

    前两者主要是为RSA算法提供服务,当然PKCS#11最新的扩展也開始支持ECC算法。而国家password管理制定的国密标准。主要提供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_MACHINESOFTWAREMicrosoftCryptographyDefaultsProvider文件夹下,我们能够通过API:CryptEnumProviders()来枚举想要的CSP,如以下代码所看到的:

    void CTestCSPDlg::EnumCSP()
    {
    	DWORD dwIndex = 0;
    	DWORD dwType = 0;
    	DWORD dwNameLen = 0;
    	CComboBox* pCSPList = (CComboBox*)GetDlgItem(IDC_COMBO_CSPLIST);
    	pCSPList->ResetContent();
    
    	while (CryptEnumProviders(dwIndex, NULL, 0, &dwType, NULL, &dwNameLen))
    	{	
    		DWORD dwItem = 0;
    		TCHAR * pName = new TCHAR[dwNameLen + 1 ];
    		if (CryptEnumProviders(dwIndex++, NULL, 0, &dwType, pName, &dwNameLen))
    		{
    			dwItem = pCSPList->AddString(pName);
    			pCSPList->SetItemData(dwItem, dwType);
    		}
    		delete []pName;
    	}
    	pCSPList->SetCurSel(0);
    	OnCbnSelchangeComboCsplist();
    }

    五、获取CSP属性

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

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

    	//获取CSP容器名称
    	dwParamLen = 2048;
    	memset(btParamData, 0, 2048);
    	pList->InsertItem(dwIndex, _T("PP_CONTAINER"), 0);
    	pList->SetItemText(dwIndex, 1, _T("密钥容器名称"));
    	if (CryptGetProvParam(hProv, PP_CONTAINER, btParamData, &dwParamLen, 0))
    	{
    		TCHAR *tcValue = NULL;
    #ifdef UNICODE
    		tcValue = A2W((char*)btParamData);
    #else
    		tcValue = (char*)btParamData;
    #endif
    		pList->SetItemText(dwIndex, 2, tcValue);
    	}
    	else
    	{
    		pList->SetItemText(dwIndex, 2, _T("Failed!"));
    	}

    以下的代码枚举CSP全部的容器名:

    	//获取CSP全部的容器名称
    	dwParamLen = 2048;
    	memset(btParamData, 0, 2048);
    	pList->InsertItem(dwIndex, _T("PP_ENUMCONTAINERS"), 0);
    	pList->SetItemText(dwIndex, 1, _T("全部容器名"));
    	if (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, btParamData, &dwParamLen, CRYPT_FIRST))
    	{
    		CString strContianers;
    		TCHAR *tcValue = NULL;
    #ifdef UNICODE
    		tcValue = A2W((char*)btParamData);
    #else
    		tcValue = btParamData;
    #endif
    		strContianers += tcValue;
    		
    		dwParamLen = 2048;
    		memset(btParamData, 0, 2048);
    		while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, btParamData, &dwParamLen, CRYPT_NEXT))
    		{
    #ifdef UNICODE
    			tcValue = A2W((char*)btParamData);
    #else
    			tcValue = btParamData;
    #endif
    			strContianers += _T("/");
    			strContianers += tcValue;
    		}
    		pList->SetItemText(dwIndex, 2, strContianers);
    	}
    	else
    	{
    		pList->SetItemText(dwIndex, 2, _T("Failed!"));
    	}


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

    	//获取CSP所支持的算法信息
    	dwParamLen = 2048;
    	memset(btParamData, 0, 2048);
    	pList->InsertItem(dwIndex, _T("PP_ENUMALGS"), 0);
    	pList->SetItemText(dwIndex, 1, _T("支持的算法信息"));
    	if (CryptGetProvParam(hProv, PP_ENUMALGS, btParamData, &dwParamLen, CRYPT_FIRST))
    	{
    		CString strAlgs;
    		PROV_ENUMALGS* alg = (PROV_ENUMALGS*)btParamData;
    		TCHAR *tcValue = NULL;
    #ifdef UNICODE
    		tcValue = A2W(alg->szName);
    #else
    		tcValue = alg->szName;
    #endif
    		strAlgs += tcValue;
    		
    		dwParamLen = 2048;
    		memset(btParamData, 0, 2048);
    		while (CryptGetProvParam(hProv, PP_ENUMALGS, btParamData, &dwParamLen, CRYPT_NEXT))
    		{
    			alg = (PROV_ENUMALGS*)btParamData;
    #ifdef UNICODE
    			tcValue = A2W(alg->szName);
    #else
    			tcValue = alg->szName;
    #endif
    			strAlgs += _T("/");
    			strAlgs += tcValue;
    		}
    		pList->SetItemText(dwIndex, 2, strAlgs);
    	}
    	else
    	{
    		pList->SetItemText(dwIndex, 2, _T("Failed!"));
    	}

    等等。


    假设须要具体代码,请下载本人枚举CSP的样例。下载连接为:枚举CSP并获取属性

  • 相关阅读:
    CentOS7安装node环境
    【异常】update更新java.sql.SQLException: Duplicate entry '2019-07-30 00:00:00-110100' for key
    MySQL查询多行重复数据SQL
    Phoenix批量提交优化,官网的demo
    (转) 读懂IL
    Docker
    Docker
    Rest之路
    (转)Docker
    Docker
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8472568.html
Copyright © 2011-2022 走看看