gmssl编程之X509证书解析
引言
最近空出了些时间整理了下以前的项目代码,看到了之前通过研究gmssl源码实现的一整套X509证书解析的代码,故记之以文。
(PS. 可能实现主要是为了满足项目需求,若有不对之处,还请指针ヾ( ̄▽ ̄))
下面小编列举了下X509证书结构的证书基本项(Basic Certificate Fields)、证书扩展项(Certificate Standard Extensions)以及自定义扩展项信息的解析。
若想了解更详细的X509结构,可查看RFC 5280规范。
X509语法结构
从RFC 5280规范中可看到X.509 v3证书语法结构如如下:
The X.509 v3 certificate basic syntax is as follows. For signature
calculation, the data that is to be signed is encoded using the ASN.1
distinguished encoding rules (DER) [X.690]. ASN.1 DER encoding is a
tag, length, value encoding system for each element.
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING }
TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version MUST be v2 or v3
extensions [3] EXPLICIT Extensions OPTIONAL
-- If present, version MUST be v3
}
Version ::= INTEGER { v1(0), v2(1), v3(2) }
CertificateSerialNumber ::= INTEGER
Validity ::= SEQUENCE {
notBefore Time,
notAfter Time }
Time ::= CHOICE {
utcTime UTCTime,
generalTime GeneralizedTime }
UniqueIdentifier ::= BIT STRING
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING }
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING
-- contains the DER encoding of an ASN.1 value
-- corresponding to the extension type identified
-- by extnID
}
基本项
小编实现的证书基本项的解析包括:版本号、序列号、颁发者、使用者、有效期、公钥等。其它的信息项由于项目不需要所以就没实现了╰( ̄▽ ̄)╭。
证书版本号
/*获取x509证书中 版本号*/
int openSSLCert_get_version(X509 *pX509, unsigned char *pucVer, unsigned int *puiVerLen)
{
if (!pX509 || !pucVer || !puiVerLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
if (*puiVerLen <= 2)
{
LError("openSSLCert_get_version failed, SAF_R_BUFFER_TOO_SMALL.");
return SAR_IndataLenErr;
}
int ver = X509_get_version(pX509);
switch (ver)
{
case 0:
strcpy((char *)pucVer, "V1");
break;
case 1:
strcpy((char *)pucVer, "V2");
break;
case 2:
strcpy((char *)pucVer, "V3");
break;
default:
LError("Unknown return value of X509_get_version.");
return SAR_UnknownErr;
}
LDebug("version: {}", pucVer);
return SAR_Ok;
}
证书序列号
/*获取证书序列号*/
int openSSLCert_get_SN(X509 *pX509, unsigned char *pucSN, unsigned int *puiSNLen)
{
int ret = SAR_Ok;
BIGNUM *bignum = NULL;
char *serial = NULL;
ASN1_INTEGER *asn1_i = NULL;
if (!pX509 || !puiSNLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
asn1_i = X509_get_serialNumber(pX509);
bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
if (NULL == bignum)
{
LError("openSSLCert_get_SN failed, ERR_R_ASN1_INTEGER_to_BN.");
ret = SAR_UnknownErr;
goto FREE_MEMORY;
}
#if 0
serial = BN_bn2hex(bignum); //大数转16进制
if (NULL == serial)
{
LOG(ERROR) << "openSSLCert_get_SN, ERR_R_BN_bn2hex.";
ret = SAR_UnknownErr;
goto FREE_MEMORY;
}
#else
serial = BN_bn2dec(bignum); //大数转整数字符串
if (NULL == serial)
{
LError("openSSLCert_get_SN failed, ERR_R_BN_bn2dec.");
ret = SAR_UnknownErr;
goto FREE_MEMORY;
}
#endif
BN_free(bignum);
if (!pucSN)
{
*puiSNLen = strlen(serial) + 1;
LError("pucSN is NULL.");
ret = SAR_MemoryErr;
goto FREE_MEMORY;
}
if (*puiSNLen < strlen(serial) + 1)
{
LError("openSSLCert_get_SN failed, SAF_R_BUFFER_TOO_SMALL.");
ret = SAR_BufferTooSmall;
goto FREE_MEMORY;
}
strcpy_s((char *)pucSN, *puiSNLen, serial);
*puiSNLen = strlen(serial);
FREE_MEMORY:
OPENSSL_free(serial);
return ret;
}
证书颁发者
/*获取证书颁发者*/
int openSSL_get_Issuer(X509 *pX509, unsigned char *pucIssuer, unsigned int *puiIssuerLen)
{
char tmp_buf[512] = { 0 };
int tmpBufLen = sizeof(tmp_buf);
X509_NAME *pCommonName = NULL;
if (!pX509 || !puiIssuerLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
pCommonName = X509_get_issuer_name(pX509);
if (!pCommonName)
{
LError("X509_get_issuer_name failed.");
return SAR_UnknownErr;
}
//获取issuer中所有信息,例如C=CN,DC=AIDDAID,DC=HSMz5k82u8NvyZ4uCoCLpBZqT8a2Vx2jW,OU=1234567890,CN=AIDIMCENTITYID
memset(tmp_buf, '\0', sizeof(tmp_buf));
X509_NAME_oneline(pCommonName, tmp_buf, tmpBufLen);
for (int i = 1; i < (int)strlen(tmp_buf); i++)
{
if (tmp_buf[i] == '/')
{
tmp_buf[i] = ',';
}
}
tmpBufLen = strlen(tmp_buf);
if (!pucIssuer)
{
*puiIssuerLen = tmpBufLen + 1;
LError("pucIssuer buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiIssuerLen < (unsigned int)tmpBufLen + 1)
{
LError("pucIssuer buffer is too small.");
return SAR_BufferTooSmall;
}
memcpy(pucIssuer, tmp_buf + 1, tmpBufLen);
*puiIssuerLen = tmpBufLen;
LDebug("issuer: {}", pucIssuer);
return SAR_Ok;
}
/*获取证书颁发者(issuer)中的某一项的值,例如C、O、OU、CN*/
int openSSLCert_get_Issuer_Entry(X509 *pX509, int nid, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
char tmp_buf[512] = { 0 };
int tmpBufLen = sizeof(tmp_buf);
X509_NAME *pCommonName = NULL;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
pCommonName = X509_get_issuer_name(pX509);
if (!pCommonName)
{
LError("X509_get_issuer_name failed.");
return SAR_UnknownErr;
}
switch (nid)
{
//case NID_countryName: //国家
//case NID_stateOrProvinceName: //省
//case NID_localityName: //地区
case NID_organizationName: //组织
case NID_organizationalUnitName: //单位
case NID_commonName: //通用名
tmpBufLen = X509_NAME_get_text_by_NID(pCommonName, nid, tmp_buf, tmpBufLen);
if (-1 == tmpBufLen)
{
LError("X509_NAME_get_text_by_NID failed.");
return SAR_UnknownErr;
};
break;
default:
LError("Invalid NID, not support yet.");
return SAR_NotSupportYetErr;
//break;
}
if (!pucInfo)
{
*puiInfoLen = tmpBufLen + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (ULONG)tmpBufLen + 1)
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, tmp_buf);
*puiInfoLen = tmpBufLen + 1;
return SAR_Ok;
}
证书使用者
/*获取证书使用者*/
int openSSLCert_get_SubjectName(X509 *pX509, unsigned char *pucSubject, unsigned int *puiSubjectLen)
{
char tmp_buf[512] = { 0 };
int tmpBufLen = sizeof(tmp_buf);
X509_NAME *pSubName = NULL;
if (!pX509 || !puiSubjectLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
pSubName = X509_get_subject_name(pX509);
if (!pSubName)
{
LError("X509_get_subject_name failed.");
return SAR_UnknownErr;
}
//获取subject中所有信息,例如C=CN,O=AIDDAID,OU=1234567890,CN=AIDIMCENTITYID
memset(tmp_buf, '\0', sizeof(tmp_buf));
X509_NAME_oneline(pSubName, tmp_buf, tmpBufLen);
for (int i = 1; i < (int)strlen(tmp_buf); i++)
{
if (tmp_buf[i] == '/')
{
tmp_buf[i] = ',';
}
}
tmpBufLen = strlen(tmp_buf);
if (!pucSubject)
{
*puiSubjectLen = tmpBufLen + 1;
LError("pucSubject buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiSubjectLen < (unsigned int)tmpBufLen + 1)
{
LError("pucSubject buffer is too small.");
return SAR_BufferTooSmall;
}
memcpy(pucSubject, tmp_buf + 1, tmpBufLen);
*puiSubjectLen = tmpBufLen;
LDebug("subject: {}", pucSubject);
return SAR_Ok;
}
/*获取证书使用者(Subject)中的某一项的值,例如C、O、OU、CN*/
int openSSLCert_get_SubjectName_Entry(X509 *pX509, int nid, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
char tmp_buf[512] = { '\0' };
int tmpBufLen = sizeof(tmp_buf);
X509_NAME *pSubName = NULL;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
pSubName = X509_get_subject_name(pX509);
if (!pSubName)
{
LError("X509_get_subject_name failed.");
return SAR_UnknownErr;
}
switch (nid)
{
//case NID_countryName: //国家
//case NID_stateOrProvinceName: //省
//case NID_localityName: //地区
case NID_organizationName: //组织
case NID_organizationalUnitName: //单位
case NID_commonName: //通用名
case NID_pkcs9_emailAddress: //邮箱地址
tmpBufLen = X509_NAME_get_text_by_NID(pSubName, nid, tmp_buf, tmpBufLen);
if (-1 == tmpBufLen)
{
LError("X509_NAME_get_text_by_NID failed");
return SAR_UnknownErr;
};
break;
default:
LError("Invalid NID, not support yet.");
return SAR_NotSupportYetErr;
break;
}
if (!pucInfo)
{
*puiInfoLen = tmpBufLen + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (ULONG)tmpBufLen + 1)
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, tmp_buf);
*puiInfoLen = tmpBufLen + 1;
return SAR_Ok;
}
证书有效期
/*获取有效期开始时间, 时间字符串格式“YYYY-MM-DD HH:mm:ss” */
int openSSLCert_get_notBefore(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
ASN1_TIME *timeNotBefore = NULL; //"YYMMDDhhmm[ss]Z" 返回的UTC格式的时间字符串
time_t lResult = 0;
int err = 0;
char startTBuf[80] = { '\0' };
struct tm* startTInfo;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
//get notBefore from X509
timeNotBefore = X509_get_notBefore(pX509);
if (NULL == timeNotBefore)
{
LError("X509_get_notBefore failure.");
return SAR_IndataErr;
}
//ASN1_Time to time_t
lResult = ASN1_TIME_get(timeNotBefore, &err);
if (err != 0)
{
LError("ASN1_Time convert to time_t failure.");
return SAR_IndataErr;
}
//time_t format "YYYY-MM-DD HH:mm:ss"
startTInfo = localtime(&lResult);
strftime(startTBuf, 80, "%Y-%m-%d %H:%M:%S", startTInfo);
if (!pucInfo)
{
*puiInfoLen = strlen(startTBuf) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < strlen(startTBuf) + 1)
{
LError("pucInfo buffer is too small, needed:{}", strlen(startTBuf) + 1);
return SAR_BufferTooSmall;
}
memset(pucInfo, '\0', *puiInfoLen);
memcpy(pucInfo, startTBuf, strlen(startTBuf));
*puiInfoLen = strlen(startTBuf);
//LOG(DEBUG) << "notBefore:" << pucInfo;
return SAR_Ok;
}
/*获取有效期截止时间,时间字符串格式“YYYY-MM-DD HH:mm:ss”*/
int openSSLCert_get_notAfter(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
ASN1_TIME *timeNotAfter = NULL; //"YYMMDDhhmm[ss]Z" 返回的UTC格式的时间字符串
time_t lResult = 0;
int err = 0;
char endTBuf[80] = { '\0' };
struct tm* endTInfo;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
timeNotAfter = X509_get_notAfter(pX509);
if (NULL == timeNotAfter)
{
LError("X509_get_notAfter failure.");
return SAR_UnknownErr;
}
//ASN1_Time to time_t
lResult = ASN1_TIME_get(timeNotAfter, &err);
if (err != 0)
{
LError("ASN1_Time convert to time_t failure.");
return SAR_IndataErr;
}
//time_t format "YYYY-MM-DD HH:mm:ss"
endTInfo = localtime(&lResult);
strftime(endTBuf, 80, "%Y-%m-%d %H:%M:%S", endTInfo);
if (!pucInfo)
{
*puiInfoLen = strlen(endTBuf) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < strlen(endTBuf) + 1)
{
LError("pucInfo buffer is too small, needed: {}", strlen(endTBuf) + 1);
return SAR_BufferTooSmall;
}
memset(pucInfo, '\0', *puiInfoLen);
memcpy(pucInfo, endTBuf, strlen(endTBuf));
*puiInfoLen = strlen(endTBuf);
//LOG(DEBUG) << "notAfter:" << pucInfo;
return SAR_Ok;
}
/*获取有效期, 格式为开始时间+截止时间,中间以“,”分隔, (例如“2019-10-26 09:34:40,2020-10-26 09:34:40”)*/
int openSSLCert_get_validTime(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
unsigned char notBeforeT[24] = { '\0' };
unsigned int notBeforeTLen = 24;
unsigned char notAfterT[24] = { '\0' };
unsigned int notAfterTLen = 24;
int ret = SAR_UnknownErr;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
ret = openSSLCert_get_notBefore(pX509, notBeforeT, ¬BeforeTLen);
if (ret != SAR_Ok)
{
LError("openSSLCert_get_notBefore failed.");
return SAR_UnknownErr;
}
ret = openSSLCert_get_notAfter(pX509, notAfterT, ¬AfterTLen);
if (ret != SAR_Ok)
{
LError("openSSLCert_get_notAfter failed.");
return SAR_UnknownErr;
}
if (!pucInfo)
{
*puiInfoLen = notBeforeTLen + notAfterTLen + 2;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < notBeforeTLen + notAfterTLen + 2)
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
memset(pucInfo, 0x00, *puiInfoLen);
strcpy((char *)pucInfo, (const char *)notBeforeT);
strcat((char *)pucInfo, ",");
strncat((char *)pucInfo, (const char *)notAfterT, notAfterTLen);
*puiInfoLen = notBeforeTLen + notAfterTLen + 1;
return SAR_Ok;
}
证书公钥
/*获取证书公钥*/
int openSSLCert_get_PubKey(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
#if 0
// 以下虽为正规方式 (个人认为)
// 注,若生成的证书x509结构中cert_info->X509_pubkey->EVP_PKEY 未填入值。故用X509_get_pubkey取不到数据
EVP_PKEY *pubKey = NULL;
unsigned char *pTmp = NULL;
int pubLen = 0;
pubKey = X509_get_pubkey(pX509);
if (!pubKey)
{
LError("X509_get_pubkey failed");
return SAR_UnknownErr;
}
pubLen = i2d_PublicKey(pubKey, NULL);
if (!pucInfo)
{
*puiInfoLen = pubLen;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < pubLen)
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
pTmp = pucInfo;
//把证书公钥转为DER编码的数据
*puiInfoLen = i2d_PublicKey(pubKey, &pTmp);
#else
//通过X509_get0_pubkey_bitstr获取X509_pubkey_st结构中public_key成员的数据
ASN1_BIT_STRING * pubkey;
pubkey = X509_get0_pubkey_bitstr(pX509);
int nlen = pubkey->length;
//LOG(DEBUG) << std::hex << std::setw(2) << pubkey->data << std::endl;
if (!pucInfo)
{
*puiInfoLen = nlen;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (unsigned int)nlen)
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
memset(pucInfo, '\0', *puiInfoLen);
memcpy(pucInfo, pubkey->data, nlen);
*puiInfoLen = nlen;
#endif
return SAR_Ok;
}
扩展项
通用根据项目需要,小编实现的扩展信息项的解析包括:基本约束、密钥用途、增强型密钥用途、颁发者标识、使用者标识、CRL分发点、颁发机构信息访问等。
基本约束
/*获取证书扩展属性:基本约束*/
int openSSLCert_get_ext_BasicConstraints(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
int crit = 0;
char value[512] = { 0 };
BASIC_CONSTRAINTS *bcons = NULL;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
bcons = (BASIC_CONSTRAINTS*)X509_get_ext_d2i(pX509, NID_basic_constraints, &crit, NULL);
if (!bcons)
{
LError("X509_get_ext_d2i failure, attr(NID_basic_constraints) not exist");
return SAR_UnknownErr;
}
if (!bcons->ca)
{
strcat_s(value, sizeof(value), "Subject Type=End Entity; ");
strcat_s(value, sizeof(value), "Path Length Constraint=None");
}
else
{
char temp[128] = { 0 };
sprintf_s(temp, sizeof(temp), "Path Length Constraint=%d", bcons->pathlen);
strcat_s(value, sizeof(value), "Subject Type=CA; ");
strcat_s(value, sizeof(value), temp);
}
BASIC_CONSTRAINTS_free(bcons);
if (!pucInfo)
{
*puiInfoLen = strlen(value) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (strlen(value) + 1))
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, value);
*puiInfoLen = strlen(value) + 1;
LDebug("ExtBasicConstraints: {}", pucInfo);
return SAR_Ok;
}
密钥用途
/*获取证书扩展属性:密钥用途*/
int openSSLCert_get_ext_keyUsage(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
//密钥用法
ASN1_BIT_STRING *lASN1UsageStr = NULL;
unsigned short usage = 0;
char temp[32] = { 0 };
char value[512] = { 0 };
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
int crit = 0;
lASN1UsageStr = (ASN1_BIT_STRING *)X509_get_ext_d2i(pX509, NID_key_usage, &crit, NULL);
if (!lASN1UsageStr)
{
LError("X509_get_ext_d2i failure, attr(NID_key_usage) not exist");
return SAR_UnknownErr;
}
if (crit)
{
strcat_s(value, sizeof(value), "critical, ");
}
usage = lASN1UsageStr->data[0];
if (lASN1UsageStr->length > 1)
{
usage |= lASN1UsageStr->data[1] << 8;
}
sprintf_s(temp, sizeof(temp), "(%x)", usage);
if (usage & KU_DIGITAL_SIGNATURE)
{
strcat_s(value, sizeof(value), "Digital Signature, ");
}
if (usage & KU_NON_REPUDIATION)
{
strcat_s(value, sizeof(value), "Non-Repudiation, ");
}
if (usage & KU_KEY_ENCIPHERMENT)
{
strcat_s(value, sizeof(value), "Key Encipherment, ");
}
if (usage & KU_DATA_ENCIPHERMENT)
{
strcat_s(value, sizeof(value), "Data Encipherment, ");
}
if (usage & KU_KEY_AGREEMENT)
{
strcat_s(value, sizeof(value), "Key Agreement, ");
}
if (usage & KU_KEY_CERT_SIGN)
{
strcat_s(value, sizeof(value), "Certificate Signature, ");
}
if (usage & KU_CRL_SIGN)
{
strcat_s(value, sizeof(value), "CRL Signature, ");
}
strcat_s(value, sizeof(value), temp);
ASN1_BIT_STRING_free(lASN1UsageStr);
if (!pucInfo)
{
*puiInfoLen = strlen(value) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (strlen(value) + 1))
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, value);
*puiInfoLen = strlen(value) + 1;
LDebug("KeyUsage: {}", pucInfo);
return SAR_Ok;
}
增强型密钥用途
/*获取证书扩展属性:增强型密钥用途*/
int openSSLCert_get_ext_EnhancedKeyUsage(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
int i = 0;
char value[512] = { 0 };
EXTENDED_KEY_USAGE* extusage;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return -1;
}
int crit = 0;
extusage = (EXTENDED_KEY_USAGE *)X509_get_ext_d2i(pX509, NID_ext_key_usage, &crit, NULL);
if (!extusage)
{
LError("X509_get_ext_d2i failure, attr(NID_ext_key_usage) not exist");
return -1;
}
//是否为关键扩展项
if (crit)
{
strcat_s(value, sizeof(value), "critical, ");
}
for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++)
{
switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
case NID_server_auth:
strcat_s(value, sizeof(value), "serverAuth, ");
break;
case NID_client_auth:
strcat_s(value, sizeof(value), "clientAuth, ");
break;
case NID_email_protect:
strcat_s(value, sizeof(value), "emailProtection, ");
break;
case NID_code_sign:
strcat_s(value, sizeof(value), "codeSigning, ");
break;
case NID_OCSP_sign:
strcat_s(value, sizeof(value), "OCSPSigning, ");
break;
case NID_time_stamp:
strcat_s(value, sizeof(value), "timeStamping, ");
break;
case NID_ms_code_ind:
strcat_s(value, sizeof(value), "msCodeInd, ");
break;
case NID_ms_code_com:
strcat_s(value, sizeof(value), "msCodeCom, ");
break;
case NID_ms_ctl_sign:
strcat_s(value, sizeof(value), "msCTLSign, ");
break;
case NID_ms_efs:
strcat_s(value, sizeof(value), "msEFS, ");
break;
case NID_ns_sgc:
strcat_s(value, sizeof(value), "nsSGC, ");
break;
case NID_ms_sgc:
strcat_s(value, sizeof(value), "msSGC, ");
break;
case NID_dvcs:
strcat_s(value, sizeof(value), "DVCS, ");
break;
case NID_anyExtendedKeyUsage:
strcat_s(value, sizeof(value), "anyExtendedKeyUsage, ");
break;
}
}
sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
int len = strlen(value);
if (len > 2)
{
value[len - 1] = 0; //去除末尾逗号
value[len - 2] = 0;
}
if (!pucInfo)
{
*puiInfoLen = strlen(value) + 1;
LError("pucInfo buffer is NULL.");
return -1;
}
if (*puiInfoLen < (strlen(value) + 1))
{
LError("pucInfo buffer is too small.");
return -1;
}
strcpy_s((char *)pucInfo, *puiInfoLen, value);
*puiInfoLen = strlen(value) + 1;
LDebug("EnhancedKeyUsage: {}", (char *)pucInfo);
return 0;
}
颁发者标识
/*获取证书扩展属性:颁发者标识*/
int openSSLCert_get_ext_AuthorityIdentifier(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
int i = 0;
int crit = 0;
char value[512] = { 0 };
AUTHORITY_KEYID *akeyid = NULL;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
akeyid = (AUTHORITY_KEYID*)X509_get_ext_d2i(pX509, NID_authority_key_identifier, &crit, NULL);
if (!akeyid)
{
LError("X509_get_ext_d2i failure, attr(NID_authority_key_identifier) not exist");
return SAR_UnknownErr;
}
strcat_s(value, sizeof(value), "KeyID=");
for (i = 0; i < akeyid->keyid->length; i++)
{
char keyid[8] = { 0 };
sprintf_s(keyid, 8, "%x ", akeyid->keyid->data[i]);
strcat_s(value, sizeof(value), keyid);
}
AUTHORITY_KEYID_free(akeyid);
if (!pucInfo)
{
*puiInfoLen = strlen(value) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (strlen(value) + 1))
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, value);
*puiInfoLen = strlen(value) + 1;
return SAR_Ok;
}
使用者标识
/*获取证书扩展属性:使用者标识*/
int openSSLCert_get_ext_SubjectIdentifier(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
int i = 0;
int crit = 0;
char value[512] = { 0 };
ASN1_OCTET_STRING *skid = NULL;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
skid = (ASN1_OCTET_STRING*)X509_get_ext_d2i(pX509, NID_subject_key_identifier, &crit, NULL);
if (!skid)
{
LError("X509_get_ext_d2i failure, attr(NID_subject_key_identifier) not exist");
return SAR_UnknownErr;
}
for (i = 0; i < skid->length; i++)
{
char keyid[8] = { 0 };
sprintf_s(keyid, 8, "%x ", skid->data[i]);
strcat_s(value, sizeof(value), keyid);
}
ASN1_OCTET_STRING_free(skid);
if (!pucInfo)
{
*puiInfoLen = strlen(value) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (strlen(value) + 1))
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, value);
*puiInfoLen = strlen(value) + 1;
return SAR_Ok;
}
CRL分发点
/*获取证书扩展属性:CRL分发点*/
int openSSLCert_get_ext_CRLDistPoints(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
int i = 0;
int crit = 0;
char value[512] = { 0 };
CRL_DIST_POINTS *crlpoints = NULL;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
crlpoints = (CRL_DIST_POINTS*)X509_get_ext_d2i(pX509, NID_crl_distribution_points, &crit, NULL);
if (!crlpoints)
{
LError("X509_get_ext_d2i failure, attr(NID_crl_distribution_points) not exist");
return SAR_UnknownErr;
}
for (i = 0; i < sk_DIST_POINT_num(crlpoints); i++)
{
int j, gtype;
GENERAL_NAMES *gens;
GENERAL_NAME *gen;
ASN1_STRING *uri;
DIST_POINT *dp = sk_DIST_POINT_value(crlpoints, i);
if (!dp->distpoint || dp->distpoint->type != 0)
continue;
gens = dp->distpoint->name.fullname;
for (j = 0; j < sk_GENERAL_NAME_num(gens); j++)
{
gen = sk_GENERAL_NAME_value(gens, j);
uri = (ASN1_STRING*)GENERAL_NAME_get0_value(gen, >ype);
if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6)
{
char *uptr = (char *)ASN1_STRING_data(uri);
if (strlen(value) > 0)
{
strcat_s(value, 512, " | ");
}
strcat_s(value, 512, uptr);
}
}
}
CRL_DIST_POINTS_free(crlpoints);
if (!pucInfo)
{
*puiInfoLen = strlen(value) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (strlen(value) + 1))
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, value);
*puiInfoLen = strlen(value) + 1;
return SAR_Ok;
}
颁发机构信息访问
/*获取证书扩展属性:颁发机构信息访问*/
int openSSLCert_get_ext_AuthorityInfoAccess(X509 *pX509, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
int i = 0;
int crit = 0;
char value[512] = { 0 };
AUTHORITY_INFO_ACCESS *accinfo = NULL;
if (!pX509 || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
accinfo = (AUTHORITY_INFO_ACCESS*)X509_get_ext_d2i(pX509, NID_info_access, &crit, NULL);
if (!accinfo)
{
LError("X509_get_ext_d2i failure, attr(NID_info_access) not exist");
return SAR_UnknownErr;
}
for (i = 0; i < sk_ACCESS_DESCRIPTION_num(accinfo); i++)
{
ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(accinfo, i);
if (ad && ad->location && ad->location->type == GEN_URI)
{
char temp[256] = { 0 };
char method[32] = { 0 };
char *uptr = (char *)ASN1_STRING_data(ad->location->d.uniformResourceIdentifier);
if (strlen(value) > 0)
{
strcat_s(value, 512, " | ");
}
OBJ_obj2txt(method, 32, ad->method, 1);
sprintf_s(temp, 256, "Access Method=证书颁发机构颁发者 (%s), \r\n", method);
strcat_s(value, 512, temp);
strcat_s(value, 512, uptr);
}
}
AUTHORITY_INFO_ACCESS_free(accinfo);
if (!pucInfo)
{
*puiInfoLen = strlen(value) + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (strlen(value) + 1))
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
strcpy_s((char *)pucInfo, *puiInfoLen, value);
*puiInfoLen = strlen(value) + 1;
return SAR_Ok;
}
自定义私有扩展项
私有自定义扩展项时通过自定义的OID值来进行查找并解析。
/*获取证书中自定义私有扩展项信息*/
int openSSLCert_get_ext_SelfDefinedExtension(X509 *pX509, const char *pcPriOid, unsigned char *pucInfo, unsigned int *puiInfoLen)
{
if (!pX509 || !pcPriOid || !puiInfoLen)
{
LError("ERR_R_PASSED_NULL_PARAMETER.");
return SAR_IndataErr;
}
ASN1_OBJECT *obj;
obj = OBJ_txt2obj(pcPriOid, 1);
if (obj == NULL)
{
return SAR_NotExportErr; //未找到指定的自定义扩展项
}
int idx = X509_get_ext_by_OBJ(pX509, obj, -1);
/* Does extension exist? */
if (idx == -1) {
return SAR_NotExportErr; //未找到指定的自定义扩展项
}
X509_EXTENSION *extension = X509_get_ext(pX509, idx);
if (NULL == extension)
{
LError("X509_get_ext fail");
return SAR_IndataErr;
}
ASN1_OCTET_STRING *ext_val = X509_EXTENSION_get_data(extension);
if (!ext_val)
{
LError("X509_EXTENSION_get_data return null");
return SAR_IndataErr;
}
if (!pucInfo)
{
*puiInfoLen = ext_val->length + 1;
LError("pucInfo buffer is NULL.");
return SAR_MemoryErr;
}
if (*puiInfoLen < (ext_val->length + 1))
{
LError("pucInfo buffer is too small.");
return SAR_BufferTooSmall;
}
memset(pucInfo, '\0', *puiInfoLen);
memcpy(pucInfo, ext_val->data, ext_val->length);
*puiInfoLen = ext_val->length;
return SAR_Ok;
}
我不休息我还能学 ⊂(‘ω’⊂ )))Σ≡=─༄༅༄༅༄༅༄༅༄༅