使用CryptoAPI获取证书扩展属性之一:“基本约束”

        前面通过一系列文章,讲述了如使用CryptoAPI解析证书的基本项,现在我们来看看如何获取证书的扩展项。

        目前CA中心颁发的证书,都有一些扩展项属性,用来限定证书的用途、提供颁发者信息、以及CRL的下载地址等等。在下图中,红色区域内的属性都为证书的扩展属性。


        在CryptoAPI中,提供了获取这些扩展属性的方法。今天,我们先看看如何获取证书扩展属性中的“基本约束”属性。具体可以通过以下步骤来实现:

1、调用函数CertFindExtension()找到扩展对象

该函数的定义如下:

PCERT_EXTENSION WINAPI CertFindExtension(
  _In_ LPCSTR         pszObjId,
  _In_ DWORD          cExtensions,
  _In_ CERT_EXTENSION rgExtensions[]
);

其中:

第一个参数pszObjId为对象的ID,要获取“基本约束”扩展对象需要指定为szOID_BASIC_CONSTRAINTS2;

第二个参数是指扩展属性数组的成员个数,由证书信息结构体中的cExtension成员指定;

第三个参数为扩展属性数组,由证书信息结构体中的rgExtension成员指定。

2、使用函数CryptDecodeObject()解码对象,得到属性结构体

在CryptoAPI中,微软为“基本约束”扩展属性定义了结构体,具体如下:

typedef struct _CERT_BASIC_CONSTRAINTS2_INFO {
    BOOL                    fCA;
    BOOL                    fPathLenConstraint;
    DWORD                   dwPathLenConstraint;
} CERT_BASIC_CONSTRAINTS2_INFO, *PCERT_BASIC_CONSTRAINTS2_INFO;

其中:

第一个成员fCA,表明该证书可否作为CA证书签发下一级证书。一般用户证书该值都为FALSE;

第二个成员fPathLenConstraint,表明当作CA证书时,是否有级别限制;

第三个成员dwPathLenConstraint,只有到fPathLenConstraint为TRUE时有效,表明具体可以签发的证书级别。

3、解析结构体中的值

如果我们得到了上面结构体的具体值,就可以根据值来显示“基本约束”的属性了。

        完整的解析“基本约束”属性的函数代码如下:

ULONG CCSPCertificate::_GetExtBasicConstraints(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_BASIC_CONSTRAINTS2, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); 
	if (pCertExt)
	{
		PCERT_BASIC_CONSTRAINTS2_INFO pInfo = (PCERT_BASIC_CONSTRAINTS2_INFO)btData;
		if (CryptDecodeObject(	GLOBAL_ENCODING_TYPE, szOID_BASIC_CONSTRAINTS2, 
								pCertExt->Value.pbData, pCertExt->Value.cbData, 
								CRYPT_DECODE_NOCOPY_FLAG, pInfo, &ulDataLen))
		{
			if (pInfo->fCA) 
			{
				strcat_s(csProperty, 512, "Subject Type=CA; ");
			}
			else 
			{
				strcat_s(csProperty, 512, "Subject Type=End Entity; ");
			}
			if (pInfo->fPathLenConstraint) 
			{
				CHAR csTemp[128] = {0};
				sprintf_s(csTemp, 128, "Path Length Constraint=%d", pInfo->dwPathLenConstraint);
				strcat_s(csProperty, 512, csTemp);
			}
			else
			{
				strcat_s(csProperty, 512, "Path Length Constraint=None");
			}
		}
		else
		{
			return GetLastError();
		}		
	}
	else
	{
		pCertExt = CertFindExtension(szOID_BASIC_CONSTRAINTS, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension); 		
		if (pCertExt)
		{
			PCERT_BASIC_CONSTRAINTS_INFO pInfo = (PCERT_BASIC_CONSTRAINTS_INFO)btData;
			if (CryptDecodeObject(	GLOBAL_ENCODING_TYPE, szOID_BASIC_CONSTRAINTS, 
									pCertExt->Value.pbData, pCertExt->Value.cbData, 
									CRYPT_DECODE_NOCOPY_FLAG, pInfo, &ulDataLen))
			{
				if (pInfo->SubjectType.pbData[0] & CERT_CA_SUBJECT_FLAG) 
				{
					strcat_s(csProperty, 512, "Subject Type=CA; ");
				}
				else if (pInfo->SubjectType.pbData[0] & CERT_END_ENTITY_SUBJECT_FLAG) 
				{
					strcat_s(csProperty, 512, "Subject Type=End Entity; ");
				}
				else
				{
					strcat_s(csProperty, 512, "Subject Type=Unknown; ");
				}
				if (pInfo->fPathLenConstraint) 
				{
					CHAR csTemp[128] = {0};
					sprintf_s(csTemp, 128, "Path Length Constraint=%d", pInfo->dwPathLenConstraint);
					strcat_s(csProperty, 512, csTemp);
				}
				else
				{
					strcat_s(csProperty, 512, "Path Length Constraint=None");
				}
			}
			else
			{
				return GetLastError();
			}	
		}
		else
		{
			return CERT_ERR_ATTR_NOTEXIST;
		}	
	}

	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;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值