通过OpenSSL获取这两个扩展属性,具体步骤如下:
1、调用X509_get_ext_d2i()获取对应的扩展属性对象;
2、解析对象结构体,得到具体的用法类型。其中:
“密钥用法”使用结构体ASN1_BIT_STRING表示,其具体定义如下:
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;
};
其成员变量pbData[0]和pbData[1]表明了用途类型,可以是下面定义的一种、或几种用途的组合。#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
而"增强型密钥用法"使用ASN1_OBJECT STACK返回。具体定义如下:
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;
typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
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;
}