您的位置:首页 > 运维架构

通过OpenSSL获取证书扩展属性之二:“密钥用法”和"增强型密钥用法"

2015-09-10 15:31 381 查看
上篇文章讲述了如何使用OpenSSL获取证书的“基本约束”扩展属性:通过OpenSSL获取证书扩展属性之一:“基本约束”

今天继续讲述如何获取“密钥用法”和“增强型密钥用法”这两个扩展属性。"密钥用法"限定了该证书的用途类型,主要分数据签名和数据加密两大类(有的证书同时具有这两类用途)。如下图所示,该证书的用途类型为“数据签名”:



而“增强型密钥用法”属性进一步指明具体用途, 如下图所以,该证书的具体用途为“邮件签名”和“身份验证签名”:



通过OpenSSL获取这两个扩展属性,具体步骤如下:

1、调用X509_get_ext_d2i()获取对应的扩展属性对象;

2、解析对象结构体,得到具体的用法类型。其中:

“密钥用法”使用结构体ASN1_BIT_STRING表示,其具体定义如下:

<span style="font-size:12px;">struct asn1_string_st
	{
	int length;
	int type;
	unsigned char *data;
	/* The value of the following field depends on the type being
	 * held.  It is mostly being used for BIT_STRING so if the
	 * input data has a non-zero 'unused bits' value, it will be
	 * handled correctly */
	long flags;
	};</span>
其成员变量pbData[0]和pbData[1]表明了用途类型,可以是下面定义的一种、或几种用途的组合。

<span style="font-size:12px;">#define KU_DIGITAL_SIGNATURE	0x0080
#define KU_NON_REPUDIATION	0x0040
#define KU_KEY_ENCIPHERMENT	0x0020
#define KU_DATA_ENCIPHERMENT	0x0010
#define KU_KEY_AGREEMENT	0x0008
#define KU_KEY_CERT_SIGN	0x0004
#define KU_CRL_SIGN		0x0002
#define KU_ENCIPHER_ONLY	0x0001
#define KU_DECIPHER_ONLY	0x8000</span>


而"增强型密钥用法"使用ASN1_OBJECT STACK返回。具体定义如下:

<span style="font-size:12px;">typedef struct asn1_object_st
	{
	const char *sn,*ln;
	int nid;
	int length;
	const unsigned char *data;	/* data remains const after init */
	int flags;	/* Should we free this one */
	} ASN1_OBJECT;</span>
<span style="font-size:12px;">typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;</span>


3、根据用法类型,返回用法名称。

基于以上过程,下面给出获取“密钥用法”和“增强型密钥用法”两个扩展属性的完整代码。“密钥用法”扩展属性的获取代码如下:

ULONG COpenSSLCertificate::_GetExtKeyUsage(X509 *pX509Cert, LPSTR lpscProperty, ULONG* pulLen)
{	
	char value[512] = {0};
	ASN1_BIT_STRING* lASN1UsageStr;

	if (!m_pX509)
	{
		return CERT_ERR_INVILIDCALL;
	}
	if (!pulLen)
	{
		return CERT_ERR_INVALIDPARAM;
	}
	
	lASN1UsageStr = (ASN1_BIT_STRING *)X509_get_ext_d2i(m_pX509, NID_key_usage, NULL, NULL);
	if (lASN1UsageStr)
	{
		char temp[32] = {0};
		unsigned short usage = lASN1UsageStr->data[0];
		if(lASN1UsageStr->length > 1)
		{ 
			usage |= lASN1UsageStr->data[1] << 8;
		}
		sprintf_s(temp, 32, "(%x)", usage);

		if (usage & KU_DIGITAL_SIGNATURE)
		{
			strcat_s(value, 512, "Digital Signature, ");
		}
		if (usage & KU_NON_REPUDIATION)
		{
			strcat_s(value, 512, "Non-Repudiation, ");
		}
		if (usage & KU_KEY_ENCIPHERMENT)
		{
			strcat_s(value, 512, "Key Encipherment, ");
		}
		if (usage & KU_DATA_ENCIPHERMENT)
		{
			strcat_s(value, 512, "Data  Encipherment, ");
		}
		if (usage & KU_KEY_AGREEMENT)
		{
			strcat_s(value, 512, "Key  Agreement, ");
		}
		if (usage & KU_KEY_CERT_SIGN)
		{
			strcat_s(value, 512, "Certificate Signature, ");
		}
		if (usage & KU_CRL_SIGN)
		{
			strcat_s(value, 512, "CRL Signature, ");
		}
			
		strcat_s(value, 512, temp);
	}
	else
	{
		return CERT_ERR_ATTR_NOTEXIST;
	}
	
	if (!lpscProperty)
	{
		*pulLen = strlen(value) + 1;
	}
	if (*pulLen < (strlen(value) + 1))
	{
		return CERT_ERR_BUFFER_TOO_SMALL;
	}
	strcpy_s(lpscProperty, *pulLen, value);

	return CERT_ERR_OK;
}
“增强型密钥用法”的获取代码如下:

ULONG COpenSSLCertificate::_GetExtEnhancedKeyUsage(X509 *pX509Cert, LPSTR lpscProperty, ULONG* pulLen)
{
	int i = 0;
	char value[512] = {0};
	EXTENDED_KEY_USAGE* extusage;

	if (!m_pX509)
	{
		return CERT_ERR_INVILIDCALL;
	}
	if (!pulLen)
	{
		return CERT_ERR_INVALIDPARAM;
	}
	
	extusage = (EXTENDED_KEY_USAGE *)X509_get_ext_d2i(m_pX509, NID_ext_key_usage, NULL, NULL);
	if (!extusage)
	{
		return CERT_ERR_ATTR_NOTEXIST;
	}
	long id[] = {OBJ_email_protect};

	for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++)
	{
		int j = 0;
		char obj_id[128] = {0};
		char obj_name[128] = {0};
		ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(extusage, i);

		OBJ_obj2txt(obj_id, sizeof(obj_id), obj, 1);
		OBJ_obj2txt(obj_name, sizeof(obj_name), obj, 0);

		if (strlen(value) > 0)
		{
			strcat_s(value, 512, "; ");
		}
		strcat_s(value, 512, obj_name);
		strcat_s(value, 512, " (");
		strcat_s(value, 512, obj_id);
		strcat_s(value, 512, ")");		
	}
    sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
	
	if (!lpscProperty)
	{
		*pulLen = strlen(value) + 1;
	}
	if (*pulLen < (strlen(value) + 1))
	{
		return CERT_ERR_BUFFER_TOO_SMALL;
	}
	strcpy_s(lpscProperty, *pulLen, value);

	return CERT_ERR_OK;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: