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

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

  --使用CertOpenSystemStore打开证书存储区.

  --在循环中,使用CertEnumCertificatesInStore.枚举所有存储区中的证书.

  --使用CryptUIDlgViewContext显示一个证书.

  --使用CertGetNameString取得证书主题名称.

  --在循环中,使用CertEnumCertificateContextProperties获取与证书关联的所有属性标识.

  --使用CertGetCertificateContextProperty获取每一个标识值.

  --使用CryptUIDlgSelectCertificateFromStore以UI的方式列出存储区所有证书并提示用户选择其中一个.

  --使用CertCloseStore关闭存储区.

  函数详解

  1.CertOpenSystemStore

  HCERTSTOREWINAPICertOpenSystemStore(

  __inHCRYPTPROV_LEGACYhprov,//CSP句柄,一般设置为NULL

  __inLPTCSTRszSubsystemProtocol//有四种类型,CA:认证机构证书;MY:关联私钥的证书存储区;ROOT:根证书;SPC:SoftwarePublisherCertificate.

  );

  如果成功此函数函数一个证书存储区的句柄,否则返回NULL,证书存储区被打开后所有标准证书存储函数均可使用,使用完毕后请用CertCloseStore关闭存储区

  2.CertEnumCertificatesInStore

  PCCERT_CONTEXTWINAPICertEnumCertificatesInStore(

  __inHCERTSTOREhCertStore,

  __inPCCERT_CONTEXTpPrevCertContext

  );

  hCertStore:存储区句柄

  pPrevCertContext:指向先前创立的证书上下文CERT_CONTEXT结构体,这个参数必须先置为NULL才能获取第一个证书

  3.CryptUIDlgViewContext

  列出一个证书,CTL或CRL上下文

  BOOLWINAPICryptUIDlgViewContext(

  __inDWORDdwContextType,

  __inconstvoidpvContext,

  __inHWNDhwnd,

  __inLPCWSTRpwszTitle,

  __inDWORDdwFlags,

  __invoidpvReserved

  );

  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结构体中取得主题或颁发者名称

  DWORDWINAPICertGetNameString(

  __inPCCERT_CONTEXTpCertContext,

  __inDWORDdwType,

  __inDWORDdwFlags,

  __invoidpvTypePara,

  __outLPTSTRpszNameString,

  __inDWORDcchNameString

  );

  dwType:名称的输出格式

  CERT_NAME_EMAIL_TYPE:如果证书有主题可选名称扩展或颁发者名称,使用rfc822Name选项.如果在扩展里没有发现rfc822Name选项,使用该EmailOID的主题名

  称域.如果rfc822Name或theEmailOID均没发现,使用string.否则返回空值(returnedcharactercountis1).pvTypePara不使用,设置为NULL.

  CERT_NAME_RDN_TYPE:调用CertNameToStr转换主题名称BLOB.pvTypeParapointstoaDWORDcontainingthedwStrTyp epassedtoCertNameToStr.如果主

  题名称域为空且证书拥有一个主题可选扩展使用来自CertNameToStr的第一个目录名称

  CERT_NAME_ATTR_TYPE:例如,如果pvTypePara值为szOID_COMMON_NAME,使用主题名称成员,如果主题名称成员为空且证书拥有一个可选名称扩展,使用第一个目录名称选项

  CERT_NAME_SIMPLE_DISPLAY_TYPE:使用下列顺序szOID_COMMON_NAME, szOID_ORGANIZATIONAL_UNIT_NAME,s zOID_ORGANIZATION_NAME,orszOID_RSA_emailAddr如果其中一个属性没有找到,使用主题可选名称扩展,如果这些都不匹配则使用第一个属性

  CERT_NAME_FRIENDLY_DISPLAY_TYPE

  CERT_NAME_DNS_TYPE

  CERT_NAME_URL_TYPE

  CERT_NAME_UPN_TYPE

  5.CertEnumCertificateContextProperties

  DWORDWINAPICertEnumCertificateContextProperties(

  __inPCCERT_CONTEXTpCertContext,

  __inDWORDdwPropId//取得第一个属性该值设为0,取得接下来的属性该值为此函数所返回

  );

  6.CertGetCertificateContextProperty

  BOOLWINAPICertGetCertificateContextProperty(

  __inPCCERT_CONTEXTpCertContext,

  __inDWORDdwPropId,

  __outvoidpvData,

  __inoutDWORDpcbData

  );

  该获取证书属性信息,详细请参考http://msdn.microsoft.com/en-us/library/aa376079(V S.85).aspx

  7.CryptUIDlgSelectCertificateFromStore

  PCCERT_CONTEXTWINAPICryptUIDlgSelectCertificateFro mStore(

  __inHCERTSTOREhCertStore,

  __inHWNDhwnd,

  __in_optLPCWSTRpwszTitle,

  __in_optLPCWSTRpwszDisplayString,

  __inDWORDdwDontUseColumn,

  __inDWORDdwFlags,

  __invoidpvReserved

  );

  弹出一个对话框,允许用户从指定存储目录中选择一个证书

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

  #i nclude<stdio.h>

  #i nclude<windows.h>

  #i nclude<wincrypt.h>

  #i nclude<cryptuiapi.h>//需要装PLATFORMSDK

  #i nclude<tchar.h>

  #pragmacomment(lib,"crypt32.lib")

  #pragmacomment(lib,"cryptui.lib")

  #defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_A SN_ENCODING)

  voidMyHandleError(chars);

  voidmain(void)

  {

  HCERTSTOREhCertStore;

  PCCERT_CONTEXTpCertContext=NULL;

  charpszNameString[256];

  charpszStoreName[256]="MY";

  DWORDdwPropId=0;

  charthumb[100]="";

  chartemstring[10];

  pCertContext=NULL;

  if(hCertStore=CertOpenSystemStore(

  NULL,

  pszStoreName))

  {

  fprintf(stderr,"Thesstorehasbeenopened.\n",pszStor eName);

  }

  else

  {

  MyHandleError("Thestorewasnotopened.");

  }

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

  while(pCertContext=CertEnumCertificatesInStore(

  hCertStore,

  pCertContext))

  {

  //打印证书名称

  if(CertGetNameString(

  pCertContext,

  CERT_NAME_RDN_TYPE,

  0,

  NULL,

  pszNameString,

  128))

  printf("\nCertificatefors\n",pszNameString);

  //遍历指定证书所有属性标识

  while(dwPropId=CertEnumCertificateContextPropertie s(

  pCertContext,//所列出的证书属性的上下文

  dwPropId))//dwPropId值必须先置为0

  {

  //循环开始执行,属性值被找到

  printf("Property#dfound->",dwPropId);

  //------------------------------------------------ -------------------

  //Indicatethekindofpropertyfound.

  switch(dwPropId)

  {

  caseCERT_FRIENDLY_NAME_PROP_ID:

  {

  printf("Displayname:");

  break;

  }

  caseCERT_SIGNATURE_HASH_PROP_ID:

  {

  printf("Signaturehashidentifier");

  break;

  }

  caseCERT_KEY_PROV_HANDLE_PROP_ID:

  {

  printf("KEYPROVEHANDLE");

  break;

  }

  caseCERT_KEY_PROV_INFO_PROP_ID:

  {

  printf("KEYPROVINFOPROPID");

  break;

  }

  caseCERT_SHA1_HASH_PROP_ID:

  {

  printf("SHA1HASHidentifier");

  break;

  }

  caseCERT_MD5_HASH_PROP_ID:

  {

  printf("md5hashidentifier");

  break;

  }

  caseCERT_KEY_CONTEXT_PROP_ID:

  {

  printf("KEYCONTEXTPROPidentifier");

  break;

  }

  caseCERT_KEY_SPEC_PROP_ID:

  {

  printf("KEYSPECPROPidentifier");

  break;

  }

  caseCERT_ENHKEY_USAGE_PROP_ID:

  {

  printf("ENHKEYUSAGEPROPidentifier");

  break;

  }

  caseCERT_NEXT_UPDATE_LOCATION_PROP_ID:

  {

  printf("NEXTUPDATELOCATIONPROPidentifier");

  break;

  }

  caseCERT_PVK_FILE_PROP_ID:

  {

  printf("PVKFILEPROPidentifier");

  break;

  }

  caseCERT_DESCRIPTION_PROP_ID:

  {

  printf("DESCRIPTIONPROPidentifier");

  break;

  }

  caseCERT_ACCESS_STATE_PROP_ID:

  {

  printf("ACCESSSTATEPROPidentifier");

  break;

  }

  caseCERT_SMART_CARD_DATA_PROP_ID:

  {

  printf("SMART_CARDDATAPROPidentifier");

  break;

  }

  caseCERT_EFS_PROP_ID:

  {

  printf("EFSPROPidentifier");

  break;

  }

  caseCERT_FORTEZZA_DATA_PROP_ID:

  {

  printf("FORTEZZADATAPROPidentifier");

  break;

  }

  caseCERT_ARCHIVED_PROP_ID:

  {

  printf("ARCHIVEDPROPidentifier");

  break;

  }

  caseCERT_KEY_IDENTIFIER_PROP_ID:

  {

  printf("KEYIDENTIFIERPROPidentifier");

  break;

  }

  caseCERT_AUTO_ENROLL_PROP_ID:

  {

  printf("AUTOENROLLidentifier.");

  break;

  }

  }//Endswitch.

  printf("\n");

  }//Endinnerwhile.

  }//Endouterwhile.

  //------------------------------------------------ -------------------

  //Selectanewcertificatebyusingtheuserinterface.

  //使用UI选择一个新证书

  if(!(pCertContext=CryptUIDlgSelectCertificateFromS tore(

  hCertStore,

  NULL,

  NULL,

  NULL,

  CRYPTUI_SELECT_LOCATION_COLUMN,

  0,

  NULL)))

  {

  MyHandleError("SelectUIfailed.");

  }

  else

  {

  //显示名称

  if(CertGetNameString(

  pCertContext,

  CERT_NAME_RDN_TYPE,

  0,

  NULL,

  pszNameString,

  128))

  {

  printf("\nCertificatefors\n",pszNameString);

  LPBYTEpEncodedBytes=NULL;

  LPBYTEpHash;

  DWORDcbData,i;

  pHash=NULL;

  cbData=http://blog.soso.com/qz.q/0;

  CertGetCertificateContextProperty(pCertContext,CER T_HASH_PROP_ID,NULL,&cbData);

  if(cbData=http://blog.soso.com/qz.q/=0)

  {

  MyHandleError("CertGetCertificateContextProperty1f ailed");

  }

  pHash=(LPBYTE)HeapAlloc(GetProcessHeap(),0,cbData) ;

  if(pHash==NULL)

  {

  MyHandleError("HeapAllocfailed");

  }

  if(!CertGetCertificateContextProperty(pCertContext ,CERT_HASH_PROP_ID,pHash,&cbData))

  {

  MyHandleError("CertGetCertificateContextProperty2f ailed");

  }

  printf("CERT_HASH_PROP_IDLengthisd\n",cbData);

  for(i=0;i<cbData;i++)

  {

  sprintf(temstring,"02x",pHash);

  strcat(thumb,temstring);

  }

  printf("Thethumbiss",thumb);

  }

  else

  fprintf(stderr,"CertGetNamefailed.\n");

  }

  //------------------------------------------------ -------------------

  //Cleanup.

  CertFreeCertificateContext(pCertContext);

  CertCloseStore(hCertStore,0);

  }//Endofmain.

  voidMyHandleError(LPTSTRpsz)

  {

  _ftprintf(stderr,TEXT("Anerroroccurredintheprogram .\n"));

  _ftprintf(stderr,TEXT("s\n"),psz);

  _ftprintf(stderr,TEXT("Errornumberx.\n"),GetLastEr ror());

  _ftprintf(stderr,TEXT("Programterminating.\n"));

  exit(1);

  }//EndofMyHandleError.

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

  1. 如何在cmd窗口里快速且正确打开任意位置路径(各版本windows系统都适合)(图文详解)(博主推荐)

    问题的由来 有时候,我们很苦恼,总是先系统键 + R,然后再去手动敲.尤其对win7系统比较麻烦 解决办法 方法一:复制路径(这点对win10系统做得好,直接可以复制) ,win7系统的话可能还需要设 ...

  2. Windows学习总结(10)——Windows系统中常用的CMD命令详解

    1.ping命令 ping是电脑网络故障诊断中的常用的命令,它的作用是用来检查网络是否通畅或者网络连接速度.我们来看一下PING命令的具体表述. 日常的诊断过程中我们最常用到的就是诊断连接是否通畅. ...

  3. C#从证书存储区读取证书

    using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptograph ...

  4. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

  5. linux系统的任务计划crontab使用详解

    linux系统的任务计划crontab使用详解 其实大部分系统管理工作都是通过定期自动执行某一个脚本来完成的,那么如何定期执行某一个脚本呢?这就要借助linux的cron功能了. 关于cron任务计划 ...

  6. 魔方Newlife.Cube权限系统的使用及模版覆盖详解

    讲人:大石头 时间:2018-11-14 晚上20:00 地点:钉钉群(组织代码BKMV7685)QQ群:1600800 内容:魔方Newlife.Cube权限系统的使用及模版覆盖详解 准备 源码地址 ...

  7. Python操作redis系列以 哈希(Hash)命令详解(四)

    # -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1. Hset 命令用于 ...

  8. 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解

    [源码下载] 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通知 Toa ...

  9. 重新想象 Windows 8 Store Apps (36) - 通知: Tile 详解

    [源码下载] 重新想象 Windows 8 Store Apps (36) - 通知: Tile 详解 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通知 Tile ...

随机推荐

  1. 第七章 LED将为我闪烁:控制发光二级管

    LED驱动开发实验 如图所示,LED1-LED2 分别与GPC0_3.GPC0_4 相连,通过GPC0_3.GPC0_4 引脚的高低电平来控制三极管的导通性,从而控制LED 的亮灭. 根据三极管的特性 ...

  2. 17秋 软件工程 第六次作业 Beta冲刺

    题目:团队作业--Beta冲刺 Scrum Beta Scrum1 Beta Scrum2 Beta Scrum3 Beta Scrum4 Beta Scrum5 总结博客 总结博客

  3. Java多线程(三)如何创建线程

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  4. linux远程目录共享

    一.环境介绍 1.服务器说明: 有两台服务器,(1)101报表服务器,上面是tomcat跑的原生FineReport报表系统,(2)103业务服务器,上面是具体的业务系统. 2.需求说明: 报表文件由 ...

  5. 【APIO2018】铁人两项

    [APIO2018]铁人两项 题目描述 大意就是给定一张无向图,询问三元组\((s,c,f)\)中满足\(s\neq c\neq f\)且存在\((s\to c\to f)\)的简单路径(每个点最多经 ...

  6. centos 防火墙的操作

    systemctl start firewalld systemctl restart firewalld systemctl status firewalld systemctl enable fi ...

  7. 解决Zabbix网页端Get value error: cannot connect to [[192.168.238.139]:10050]: [113] No route to host问题

    在安装配置完zabbix_agentd以后,网页端出现  Get value error: cannot connect to [[192.168.238.139]:10050]: [113] No ...

  8. I/O 机制的介绍(Linux 中直接 I/O 机制的介绍)

    IO连接的建立方式 1.缓存IO.流式IO: 2.映射IO.块式IO: 3.直接IO. IO的方式: 同步.异步.定时刷新: MMAP与内核空间 mmap使用共享用户空间与内核空间实现: 直接 I/O ...

  9. Interrupt

    Interrupt ,给线程发送一个中断信号 给t1线程发送了中断信号,t1对线程的中断信号判断后,跳出循环,线程t1运行结束 public class Demo { public static vo ...

  10. 转://云和恩墨的两道Oracle面试题

    真题1. 对于一个NUMBER(1)的列,如果查询中的WHERE条件分别是大于3和大于等于4,那么这二者是否等价? 答案:首先对于查询结果而言,二者没有任何区别.从这一点上讲无论是指定大于3还是指定大 ...