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


     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. ",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(" Certificatefors ",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(" ");

      }//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(" Certificatefors ",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 ",cbData);

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

      {

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

      strcat(thumb,temstring);

      }

      printf("Thethumbiss",thumb);

      }

      else

      fprintf(stderr,"CertGetNamefailed. ");

      }

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

      //Cleanup.

      CertFreeCertificateContext(pCertContext);

      CertCloseStore(hCertStore,0);

      }//Endofmain.

      voidMyHandleError(LPTSTRpsz)

      {

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

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

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

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

      exit(1);

      }//EndofMyHandleError.
  • 相关阅读:
    海龟交易
    暑假攻略:怎样让孩子过一个充实又省钱的假期
    值得追随
    在哪里能找的你想要的答案?
    顺势加仓策略
    交易中 你的加仓策略是怎样的?背后的逻辑是什么?
    驻守深寒:寻找那些有效地关键K线
    统计相关
    求助Ubuntu16.10如何设置默认启动为字符界面
    【Linux系列】Ubuntu ping通,xshell无法连接
  • 原文地址:https://www.cnblogs.com/hjbf/p/10316287.html
Copyright © 2020-2023  润新知