使用CryptoAPI获取证书扩展属性之二:“密钥用法”和"增强型密钥用法"
2015-09-09 10:18
716 查看
上篇文章讲述了如何使用CryptoAPI获取证书的“基本约束”扩展属性:使用CryptoAPI获取证书扩展属性之一:“基本约束”
今天继续讲述如何获取“密钥用法”和“增强型密钥用法”这两个扩展属性。"密钥用法"限定了该证书的用途类型,主要分数据签名和数据加密两大类(有的证书同时具有这两类用途)。如下图所示,该证书的用途类型为“数据签名”:
而“增强型密钥用法”属性进一步指明具体用途, 如下图所以,该证书的具体用途为“邮件签名”和“身份验证签名”:
通过CryptoAPI获取这两个扩展属性,具体步骤如下:
1、调用函数CertFindExtension()找到扩展对象
2、使用函数CryptDecodeObject()解码对象,得到属性结构体。其中:
“密钥用法”的结构用CRYPT_BIT_BLOB表示,其定义为:
cUsageIdentifier:指明用法标示的个数
rgpszUsageIdentifier:用法标示数组,常见的增强型用法标示定义如下(完整的定义请见文件wincrypt.h):
3、解析结构体中的值,得到具体含义
基于以上过程,下面给出获取“密钥用法”和“增强型密钥用法”两个扩展属性的完整代码。“密钥用法”扩展属性的获取代码如下:
今天继续讲述如何获取“密钥用法”和“增强型密钥用法”这两个扩展属性。"密钥用法"限定了该证书的用途类型,主要分数据签名和数据加密两大类(有的证书同时具有这两类用途)。如下图所示,该证书的用途类型为“数据签名”:
而“增强型密钥用法”属性进一步指明具体用途, 如下图所以,该证书的具体用途为“邮件签名”和“身份验证签名”:
通过CryptoAPI获取这两个扩展属性,具体步骤如下:
1、调用函数CertFindExtension()找到扩展对象
2、使用函数CryptDecodeObject()解码对象,得到属性结构体。其中:
“密钥用法”的结构用CRYPT_BIT_BLOB表示,其定义为:
typedef struct _CRYPT_BIT_BLOB { DWORD cbData; BYTE *pbData; DWORD cUnusedBits; } CRYPT_BIT_BLOB, *PCRYPT_BIT_BLOB;其成员变量pbData[0]和pbData[1]表明了用途类型,可以是下面定义的一种、或几种用途的组合。
// Byte[0] #define CERT_DIGITAL_SIGNATURE_KEY_USAGE 0x80 #define CERT_NON_REPUDIATION_KEY_USAGE 0x40 #define CERT_KEY_ENCIPHERMENT_KEY_USAGE 0x20 #define CERT_DATA_ENCIPHERMENT_KEY_USAGE 0x10 #define CERT_KEY_AGREEMENT_KEY_USAGE 0x08 #define CERT_KEY_CERT_SIGN_KEY_USAGE 0x04 #define CERT_OFFLINE_CRL_SIGN_KEY_USAGE 0x02 #define CERT_CRL_SIGN_KEY_USAGE 0x02 #define CERT_ENCIPHER_ONLY_KEY_USAGE 0x01 // Byte[1] #define CERT_DECIPHER_ONLY_KEY_USAGE 0x80而"增强型密钥用法"有自己专用的结构体,定义如下:
typedef struct _CTL_USAGE { DWORD cUsageIdentifier; LPSTR *rgpszUsageIdentifier; // array of pszObjId } CTL_USAGE, *PCTL_USAGE, CERT_ENHKEY_USAGE, *PCERT_ENHKEY_USAGE;其中:
cUsageIdentifier:指明用法标示的个数
rgpszUsageIdentifier:用法标示数组,常见的增强型用法标示定义如下(完整的定义请见文件wincrypt.h):
//+------------------------------------------------------------------------- // Enhanced Key Usage (Purpose) Object Identifiers //-------------------------------------------------------------------------- #define szOID_PKIX_KP "1.3.6.1.5.5.7.3" // Consistent key usage bits: DIGITAL_SIGNATURE, KEY_ENCIPHERMENT // or KEY_AGREEMENT #define szOID_PKIX_KP_SERVER_AUTH "1.3.6.1.5.5.7.3.1" // Consistent key usage bits: DIGITAL_SIGNATURE #define szOID_PKIX_KP_CLIENT_AUTH "1.3.6.1.5.5.7.3.2" // Consistent key usage bits: DIGITAL_SIGNATURE #define szOID_PKIX_KP_CODE_SIGNING "1.3.6.1.5.5.7.3.3" // Consistent key usage bits: DIGITAL_SIGNATURE, NON_REPUDIATION and/or // (KEY_ENCIPHERMENT or KEY_AGREEMENT) #define szOID_PKIX_KP_EMAIL_PROTECTION "1.3.6.1.5.5.7.3.4" // Consistent key usage bits: DIGITAL_SIGNATURE and/or // (KEY_ENCIPHERMENT or KEY_AGREEMENT) #define szOID_PKIX_KP_IPSEC_END_SYSTEM "1.3.6.1.5.5.7.3.5" // Consistent key usage bits: DIGITAL_SIGNATURE and/or // (KEY_ENCIPHERMENT or KEY_AGREEMENT) #define szOID_PKIX_KP_IPSEC_TUNNEL "1.3.6.1.5.5.7.3.6" // Consistent key usage bits: DIGITAL_SIGNATURE and/or // (KEY_ENCIPHERMENT or KEY_AGREEMENT) #define szOID_PKIX_KP_IPSEC_USER "1.3.6.1.5.5.7.3.7" // Consistent key usage bits: DIGITAL_SIGNATURE or NON_REPUDIATION #define szOID_PKIX_KP_TIMESTAMP_SIGNING "1.3.6.1.5.5.7.3.8" // OCSP response signer #define szOID_PKIX_KP_OCSP_SIGNING "1.3.6.1.5.5.7.3.9" // Following extension is present to indicate no revocation checking // for the OCSP signer certificate #define szOID_PKIX_OCSP_NOCHECK "1.3.6.1.5.5.7.48.1.5" // OCSP Nonce #define szOID_PKIX_OCSP_NONCE "1.3.6.1.5.5.7.48.1.2" // IKE (Internet Key Exchange) Intermediate KP for an IPsec end entity. // Defined in draft-ietf-ipsec-pki-req-04.txt, December 14, 1999. #define szOID_IPSEC_KP_IKE_INTERMEDIATE "1.3.6.1.5.5.8.2.2"
3、解析结构体中的值,得到具体含义
基于以上过程,下面给出获取“密钥用法”和“增强型密钥用法”两个扩展属性的完整代码。“密钥用法”扩展属性的获取代码如下:
ULONG CCSPCertificate::_GetExtKeyUsage(PCCERT_CONTEXT pCertContext,LPSTR lpscProperty,ULONG* pulLen) { ULONG ulRes = 0; ULONG ulDataLen = 512; ULONG ulPropertyLen = 512; BYTE btData[512] = {0}; CHAR csProperty[512] = {0}; PCERT_EXTENSION pCertExt = NULL; if (!pCertContext) { return CERT_ERR_INVILIDCALL; } if (!pulLen) { return CERT_ERR_INVALIDPARAM; } pCertExt = CertFindExtension(szOID_KEY_USAGE, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); if (!pCertExt) { return CERT_ERR_ATTR_NOTEXIST; } PCRYPT_BIT_BLOB pBlob = (PCRYPT_BIT_BLOB)btData; if (CryptDecodeObject( GLOBAL_ENCODING_TYPE, szOID_KEY_USAGE, pCertExt->Value.pbData, pCertExt->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, pBlob, &ulDataLen)) { USHORT nValue = 0; CHAR csValue[32] = {0}; if (pBlob->cbData == 1) nValue = pBlob->pbData[0]; else nValue = pBlob->pbData[0] | (pBlob->pbData[1] << 8); sprintf_s(csValue, 32, "(%x)", nValue); if (pBlob->pbData[0] & CERT_DIGITAL_SIGNATURE_KEY_USAGE) { strcat_s(csProperty, 512, "Digital Signature, "); } if (pBlob->pbData[0] & CERT_NON_REPUDIATION_KEY_USAGE) { strcat_s(csProperty, 512, "Non-Repudiation, "); } if (pBlob->pbData[0] & CERT_KEY_ENCIPHERMENT_KEY_USAGE) { strcat_s(csProperty, 512, "Key Encipherment, "); } if (pBlob->pbData[0] & CERT_DATA_ENCIPHERMENT_KEY_USAGE) { strcat_s(csProperty, 512, "Data Encipherment, "); } if (pBlob->pbData[0] & CERT_KEY_AGREEMENT_KEY_USAGE) { strcat_s(csProperty, 512, "Key Agreement, "); } if (pBlob->pbData[0] & CERT_KEY_CERT_SIGN_KEY_USAGE) { strcat_s(csProperty, 512, "Certificate Signature, "); } if (pBlob->pbData[0] & CERT_OFFLINE_CRL_SIGN_KEY_USAGE) { strcat_s(csProperty, 512, "Offline CRL Signature, "); } if (pBlob->pbData[0] & CERT_CRL_SIGN_KEY_USAGE) { strcat_s(csProperty, 512, "CRL Signature, "); } if (pBlob->pbData[0] & CERT_ENCIPHER_ONLY_KEY_USAGE) { strcat_s(csProperty, 512, "Only encypt data, "); } if (pBlob->pbData[1] & CERT_DECIPHER_ONLY_KEY_USAGE) { strcat_s(csProperty, 512, "Only decypt data, "); } strcat_s(csProperty, 512, csValue); } else { return GetLastError(); } if (!lpscProperty) { *pulLen = strlen(csProperty) + 1; } if (*pulLen < (strlen(csProperty) + 1)) { return CERT_ERR_BUFFER_TOO_SMALL; } strcpy_s(lpscProperty, *pulLen, csProperty); return CERT_ERR_OK; }“增强型密钥用法”的获取代码如下:
ULONG CCSPCertificate::_GetExtEnhancedKeyUsage(PCCERT_CONTEXT pCertContext,LPSTR lpscProperty,ULONG* pulLen) { ULONG ulRes = 0; ULONG ulDataLen = 512; ULONG ulPropertyLen = 512; BYTE btData[512] = {0}; CHAR csProperty[512] = {0}; PCERT_EXTENSION pCertExt = NULL; if (!pCertContext) { return CERT_ERR_INVILIDCALL; } if (!pulLen) { return CERT_ERR_INVALIDPARAM; } pCertExt = CertFindExtension(szOID_ENHANCED_KEY_USAGE, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); if (!pCertExt) { return CERT_ERR_ATTR_NOTEXIST; } PCERT_ENHKEY_USAGE pEnhanceUsage = (PCERT_ENHKEY_USAGE)btData; if (CryptDecodeObject( GLOBAL_ENCODING_TYPE, szOID_ENHANCED_KEY_USAGE, pCertExt->Value.pbData, pCertExt->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, pEnhanceUsage, &ulDataLen)) { for (ULONG ulIndex = 0; ulIndex < pEnhanceUsage->cUsageIdentifier; ulIndex++) { if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_SERVER_AUTH) == 0) { strcat_s(csProperty, 512, "服务器认证 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_SERVER_AUTH); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_CLIENT_AUTH) == 0) { strcat_s(csProperty, 512, "客户端认证 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_CLIENT_AUTH); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_CODE_SIGNING) == 0) { strcat_s(csProperty, 512, "程序代码签名 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_CODE_SIGNING); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_EMAIL_PROTECTION) == 0) { strcat_s(csProperty, 512, "安全电子邮件 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_EMAIL_PROTECTION); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_IPSEC_END_SYSTEM) == 0) { strcat_s(csProperty, 512, "IP终端系统安全 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_IPSEC_END_SYSTEM); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_IPSEC_TUNNEL) == 0) { strcat_s(csProperty, 512, "IP通道安全 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_IPSEC_TUNNEL); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_IPSEC_USER) == 0) { strcat_s(csProperty, 512, "IP用户安全 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_IPSEC_USER); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_TIMESTAMP_SIGNING) == 0) { strcat_s(csProperty, 512, "时间戳签名 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_TIMESTAMP_SIGNING); strcat_s(csProperty, 512, "); "); } else if (_stricmp(pEnhanceUsage->rgpszUsageIdentifier[ulIndex], szOID_PKIX_KP_OCSP_SIGNING) == 0) { strcat_s(csProperty, 512, "OCSP签名 ("); strcat_s(csProperty, 512, szOID_PKIX_KP_OCSP_SIGNING); strcat_s(csProperty, 512, "); "); } else { strcat_s(csProperty, 512, "("); strcat_s(csProperty, 512, pEnhanceUsage->rgpszUsageIdentifier[ulIndex]); strcat_s(csProperty, 512, "); "); } } } else { return GetLastError(); } if (!lpscProperty) { *pulLen = strlen(csProperty) + 1; } if (*pulLen < (strlen(csProperty) + 1)) { return CERT_ERR_BUFFER_TOO_SMALL; } strcpy_s(lpscProperty, *pulLen, csProperty); return CERT_ERR_OK; }
相关文章推荐
- PowerDesigner中Table视图同时显示Code和Name
- Ubuntu安装配置Mysql
- EasyUI基础知识Draggable(拖累)
- c++ ActiveX基础1:使用VS2010创建MFC ActiveX工程项目
- Spring @Transactional (声明试事务)
- Android中notifyDataSetInvalidated()和notifyDataSetChanged()有什么区别
- 将char*转换为wchar_t*
- python 环境准备_virtualenvwrapper
- .公司域名注册总量TOP15:西部数码跌至第五 降幅最大
- c++必须在类初始化列表中初始化的几种情况
- linux du df命令清除不要的大文件
- ARM9的OpenWRT系统的移植以及 无线视觉操控系统的软件开发
- PowerPoint如何将开发工具选项卡添加到菜单栏中
- layerfsd实现的一些思路
- MySQL 百万级分页优化(Mysql千万级快速分页)
- HDU3033 I love sneakers!(分组背包)
- Mblog 系统配置
- top里的load average怎么理解呢
- Ubuntu安装mysql和简单操作
- ajax传递json数据,springmvc后台就收json数据