C语言操作WINDOWS系统存储区数字证书相关函数详解及实例

以下代码使用C++实现遍历存储区证书及使用UI选择一个证书

--使用 CertOpenSystemStore打开证书存储区.
--在循环中,使用CertEnumCertificatesInStore. 枚举所有存储区中的证书.
--使用CryptUIDlgViewContext显示一个证书 .
--使用CertGetNameString取得证书主题名称.
--在循环中,使用 CertEnumCertificateContextProperties 获取与证书关联的所有属性标识.
--使用CertGetCertificateContextProperty 获取每一个标识值.
--使用CryptUIDlgSelectCertificateFromStore以UI的方式列出存储区所有证书并提示用户选择其中一个.
--使用 CertCloseStore关闭存储区.

函数详解
1.CertOpenSystemStore

HCERTSTORE WINAPI CertOpenSystemStore(
__in HCRYPTPROV_LEGACY hprov,//CSP句柄,一般设置为NULL
__in LPTCSTR szSubsystemProtocol//有四种类型,CA:认证机构证书;MY:关联私钥的证书存储区;ROOT:根证书;SPC:Software Publisher Certificate.
);
如果成功此函数函数一个证书存储区的句柄,否则返回NULL,证书存储区被打开后所有标准证书存储函数均可使用,使用完毕后请用CertCloseStore关闭存储区
2.CertEnumCertificatesInStore

PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(
__in HCERTSTORE hCertStore,
__in PCCERT_CONTEXT pPrevCertContext
);
hCertStore:存储区句柄
pPrevCertContext:指向先前创立的证书上下文CERT_CONTEXT 结构体,这个参数必须先置为NULL才能获取第一个证书
3.CryptUIDlgViewContext
列出一个证书,CTL或CRL上下文
BOOL WINAPI CryptUIDlgViewContext(
__in DWORD dwContextType,
__in const void *pvContext,
__in HWND hwnd,
__in LPCWSTR pwszTitle,
__in DWORD dwFlags,
__in void *pvReserved
);
dwContextType :上下文的类型,如下表
Value/Meaning
CERT_STORE_CERTIFICATE_CONTEXT/PCCERT_CONTEXT

CERT_STORE_CRL_CONTEXT/PCCRL_CONTEXT

CERT_STORE_CTL_CONTEXT/PCCTL_CONTEXT
pvContext :指向列出的证书,CTL或CRL上下文的指针
hwnd :窗口显示句柄
pwszTitle :显示标题字符串
dwFlags :一般设置为0
pvReserved :保留
4.CertGetNameString
从一个证书的CERT_CONTEXT 结构体中取得主题或颁发者名称
DWORD WINAPI CertGetNameString(
__in   PCCERT_CONTEXT pCertContext,
__in   DWORD dwType,
__in   DWORD dwFlags,
__in   void *pvTypePara,
__out LPTSTR pszNameString,
__in   DWORD cchNameString
);
dwType :名称的输出格式
CERT_NAME_EMAIL_TYPE:如果证书有主题可选名称扩展或颁发者名称,使用rfc822Name 选项. 如果在扩展里没有发现 rfc822Name 选项,使用该Email OID的主题名

称域 . 如果rfc822Name或the Email OID 均没发现, 使用string. 否则返回空值 (returned character count is 1). pvTypePara 不使用,设置为 NULL.
CERT_NAME_RDN_TYPE:调用CertNameToStr转换主题名称BLOB . pvTypePara points to a DWORD containing the dwStrType passed to CertNameToStr. 如果主

题名称域为空且证书拥有一个主题可选扩展使用来自CertNameToStr的第一个目录名称
CERT_NAME_ATTR_TYPE:例如,如果pvTypePara 值为szOID_COMMON_NAME,使用主题名称成员,如果主题名称成员为空且证书拥有一个可选名称扩展,使用第一个目录名称选项
CERT_NAME_SIMPLE_DISPLAY_TYPE:使用下列顺序szOID_COMMON_NAME, szOID_ORGANIZATIONAL_UNIT_NAME, szOID_ORGANIZATION_NAME, or szOID_RSA_emailAddr如果其中一个属性没有找到,使用主题可选名称扩展,如果这些都不匹配则使用第一个属性
CERT_NAME_FRIENDLY_DISPLAY_TYPE
CERT_NAME_DNS_TYPE
CERT_NAME_URL_TYPE
CERT_NAME_UPN_TYPE
5.CertEnumCertificateContextProperties
DWORD WINAPI CertEnumCertificateContextProperties(
__in PCCERT_CONTEXT pCertContext,
__in DWORD dwPropId//取得第一个属性该值设为0,取得接下来的属性该值为此函数所返回
);
6.CertGetCertificateContextProperty
BOOL WINAPI CertGetCertificateContextProperty(
__in     PCCERT_CONTEXT pCertContext,
__in     DWORD dwPropId,
__out    void *pvData,
__inout DWORD *pcbData
);
该获取证书属性信息,详细请参考http://msdn.microsoft.com/en-us/library/aa376079(VS.85).aspx

7.CryptUIDlgSelectCertificateFromStore
PCCERT_CONTEXT WINAPI CryptUIDlgSelectCertificateFromStore(
__in      HCERTSTORE hCertStore,
__in      HWND hwnd,
__in_opt LPCWSTR pwszTitle,
__in_opt LPCWSTR pwszDisplayString,
__in      DWORD dwDontUseColumn,
__in      DWORD dwFlags,
__in      void *pvReserved
);
弹出一个对话框,允许用户从指定存储目录中选择一个证书

 

 

代码[综合]:VC++6下面调试成功

#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <cryptuiapi.h>//需要装PLATFORM SDK
#include <tchar.h>
#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "cryptui.lib")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);
void main(void)
{


HCERTSTORE       hCertStore;       
PCCERT_CONTEXT   pCertContext=NULL;     
char pszNameString[256] ;
char pszStoreName[256] = "MY";

DWORD            dwPropId = 0;
char thumb[100]="";
char temstring[10];
pCertContext = NULL;
if ( hCertStore = CertOpenSystemStore(
     NULL,
     pszStoreName))
{
     fprintf(stderr,"The %s store has been opened. /n", pszStoreName);
}
else
{
     MyHandleError("The store was not opened.");
}

//使用CertEnumCertificatesInStore从存储区获取证书,pCertContext必须置为NULL才能找到第一个证书

while(pCertContext= CertEnumCertificatesInStore(
     hCertStore,
     pCertContext))
{
//打印证书名称
if(CertGetNameString(
   pCertContext,
   CERT_NAME_RDN_TYPE,
   0,
   NULL,
   pszNameString,
   128))
   printf("/nCertificate for %s /n",pszNameString);
//遍历指定证书所有属性标识
while(dwPropId = CertEnumCertificateContextProperties(
       pCertContext, // 所列出的证书属性的上下文
       dwPropId))    // dwPropId值必须先置为0
{


//循环开始执行,属性值被找到
printf("Property # %d found->", dwPropId);

//-------------------------------------------------------------------
// Indicate the kind of property found.

   switch(dwPropId)
   {
     case CERT_FRIENDLY_NAME_PROP_ID:
     {
       printf("Display name: ");
       break;
     }
     case CERT_SIGNATURE_HASH_PROP_ID:
     {
       printf("Signature hash identifier ");
       break;
     }
     case CERT_KEY_PROV_HANDLE_PROP_ID:
     {
       printf("KEY PROVE HANDLE");
       break;
     }
     case CERT_KEY_PROV_INFO_PROP_ID:
     {
       printf("KEY PROV INFO PROP ID ");
       break;
     }
     case CERT_SHA1_HASH_PROP_ID:
     {
        printf("SHA1 HASH identifier");
        break;
     }
     case CERT_MD5_HASH_PROP_ID:
     {
        printf("md5 hash identifier ");
        break;
     }
     case CERT_KEY_CONTEXT_PROP_ID:
     {
        printf("KEY CONTEXT PROP identifier");
        break;
     }
     case CERT_KEY_SPEC_PROP_ID:
     {
        printf("KEY SPEC PROP identifier");
        break;
      }
      case CERT_ENHKEY_USAGE_PROP_ID:
      {
        printf("ENHKEY USAGE PROP identifier");
        break;
      }
      case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
      {
        printf("NEXT UPDATE LOCATION PROP identifier");
        break;
      }
      case CERT_PVK_FILE_PROP_ID:
      {
         printf("PVK FILE PROP identifier ");
         break;
      }
      case CERT_DESCRIPTION_PROP_ID:
      {
        printf("DESCRIPTION PROP identifier ");
        break;
      }
      case CERT_ACCESS_STATE_PROP_ID:
      {
        printf("ACCESS STATE PROP identifier ");
        break;
      }
      case CERT_SMART_CARD_DATA_PROP_ID:
      {
         printf("SMART_CARD DATA PROP identifier ");
         break;
      }
      case CERT_EFS_PROP_ID:
      {
        printf("EFS PROP identifier ");
        break;
      }
      case CERT_FORTEZZA_DATA_PROP_ID:
      {
        printf("FORTEZZA DATA PROP identifier ");
        break;
      }
      case CERT_ARCHIVED_PROP_ID:
      {
        printf("ARCHIVED PROP identifier ");
        break;
      }
      case CERT_KEY_IDENTIFIER_PROP_ID:
      {
        printf("KEY IDENTIFIER PROP identifier ");
        break;
      }
      case CERT_AUTO_ENROLL_PROP_ID:
      {
        printf("AUTO ENROLL identifier. ");
        break;
      }

  
   } // End switch.
printf("/n");
  
  
} // End inner while.
} // End outer while.

//-------------------------------------------------------------------
// Select a new certificate by using the user interface.
//使用UI选择一个新证书
if(!(pCertContext = CryptUIDlgSelectCertificateFromStore(
hCertStore,
NULL,
NULL,
NULL,
CRYPTUI_SELECT_LOCATION_COLUMN,
0,
NULL)))
{
    MyHandleError("Select UI failed." );
}
else
{
//显示名称

if(CertGetNameString(
   pCertContext,
   CERT_NAME_RDN_TYPE,
   0,
   NULL,
   pszNameString,
   128))
{
   printf("/nCertificate for %s /n",pszNameString);

 


LPBYTE pEncodedBytes = NULL;
LPBYTE pHash;
DWORD cbData, i;
pHash = NULL;
cbData = 0;

CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID, NULL, &cbData);
if (cbData == 0)
{
   MyHandleError("CertGetCertificateContextProperty 1 failed");
}
pHash = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, cbData);
if (pHash == NULL)
{
   MyHandleError("HeapAlloc failed");
}
if (!CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID, pHash,                                     &cbData))
{
   MyHandleError("CertGetCertificateContextProperty 2 failed");
}

printf("CERT_HASH_PROP_ID Length is %d/n", cbData);


for (i = 0; i < cbData; i++)
{
   
sprintf( temstring,"%02x",   pHash[i]);
strcat(thumb,temstring);
}

printf("%The thumb is %s", thumb);

}
else
   fprintf(stderr,"CertGetName failed. /n");
}

//-------------------------------------------------------------------
// Clean up.

CertFreeCertificateContext(pCertContext);
CertCloseStore(hCertStore,0);

 

} // End of main.


void MyHandleError(LPTSTR psz)
{
    _ftprintf(stderr, TEXT("An error occurred in the program. /n"));
    _ftprintf(stderr, TEXT("%s/n"), psz);
    _ftprintf(stderr, TEXT("Error number %x./n"), GetLastError());
    _ftprintf(stderr, TEXT("Program terminating. /n"));
    exit(1);
} // End of MyHandleError.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值