CSP: Parsing X509 certificate Essentials with CryptoAPI

Source: Internet
Author: User
Tags filetime

In the previous article, "CSP: Using CryptoAPI to decode X509 certificate content," describes how to use CryptoAPI to decode the certificate file to get the pccert_context method of the certificate context handle. Let's go on to get the desired certificate entry through the certificate context handle. This article first describes how to get the base entry for a certificate, and later an article explains how to obtain an extension of the certificate.

The following code assumes that the certificate context handle has been m_pcertcontext by decoding the certificate file. As for how to decode the certificate file and get the certificate context handle M_pcertcontext, please read the previous article.

First, let's look at the structure definition for the certificate context:

typedef struct _CERT_CONTEXT {    DWORD                   dwcertencodingtype;    BYTE                    *pbcertencoded;    DWORD                   cbcertencoded;    Pcert_info              Pcertinfo;    Hcertstore              Hcertstore;} Cert_context, *pcert_context;typedef const cert_context *pccert_context;typedef struct _cert_info {    DWORD                       dwversion;    Crypt_integer_blob          serialnumber;    Crypt_algorithm_identifier  Signaturealgorithm;    Cert_name_blob              Issuer;    FILETIME                    Notbefore;    FILETIME                    Notafter;    Cert_name_blob              Subject;    Cert_public_key_info        Subjectpublickeyinfo;    Crypt_bit_blob              Issueruniqueid;    Crypt_bit_blob              Subjectuniqueid;    DWORD                       cextension;    Pcert_extension             rgextension;} Cert_info, *pcert_info;

Some of the certificate primitives that we want to get are directly in these two structures.

First, version number

The field dwversion in the struct Cert_info is the certificate version, which can be obtained directly from the following code:

DWORD Dwcertver = m_pcertcontext->pcertinfo->dwversion;
The version values are defined as follows:

#define CERT_V1     0#define cert_v2     1#define cert_v3     2
That is, V1 has a value of 0;v3 of 2, and most of the time the certificate is V3 version.

Second, serial number

The serial number corresponds to the field serialnumber in the struct cert_info, but it is ASN.1 a large number of encoded objects that need to be decoded to be converted to the hexadecimal sequence number we normally see. The function to get the serial number is as follows:

ULONG ccspcertificate::get_sn (LPSTR lptcsn,ulong *pullen) {CHAR scsn[512] = {0};if (!m_pcertcontext) {return cert_err_ Invilidcall;} if (!pullen) {return cert_err_invalidparam;} Pcrypt_integer_blob pSn = & (M_pcertcontext->pcertinfo->serialnumber); for (int n = (int) (psn->cbdata-1); n >= 0; n--) {CHAR szhex[5] = {0};sprintf_s (Szhex, "%02x", (Psn->pbdata) [n]); strcat_s (SCSN, +, Szhex);} if (!LPTCSN) {*pullen = strlen (SCSN) + 1;return CERT_ERR_OK;} if (*pullen <= strlen (SCSN) + 1) {return cert_err_buffer_too_small;} strcpy_s (LPTCSN, *pullen, SCSN); *pullen = strlen (SCSN); return CERT_ERR_OK;}

Third, public key algorithm (certificate algorithm)

The public key algorithm in the certificate needs to be obtained through the field Subjectpublickeyinfo in the Cert_info. The specific functions are as follows:

ULONG Ccspcertificate::get_keytype (ulong* pultype) {if (!m_pcertcontext) {return cert_err_invilidcall;} if (!pultype) {return cert_err_invalidparam;} Pcert_public_key_info Ppubkey = & (M_pcertcontext->pcertinfo->subjectpublickeyinfo), if (PPubKey) {if (_ STRICMP (Ppubkey->algorithm.pszobjid, szoid_rsa_rsa) = = 0) {*pultype = Cert_key_alg_rsa;} else if (_stricmp (Ppubkey->algorithm.pszobjid, szoid_ecc_public_key) = = 0) {*pultype = CERT_KEY_ALG_ECC;} else {*pultype = 0;return Cert_err_alg_unknown;}} Else{return GetLastError ();} return CERT_ERR_OK;}

Iv. Use of certificates

The certificate is divided into two categories: "Signing certificate" and "Encryption certificate". The public key of the signing certificate is used to verify the signature, and the public key of the encryption certificate is used to encrypt the data. We need to invoke the function certgetintendedkeyusage () to obtain the purpose of the certificate, the specific function is implemented as follows:

ULONG ccspcertificate::get_keyusage (ulong* lpusage) {BYTE btusage[2] = {0};if (!m_pcertcontext) {return cert_err_ Invilidcall;} if (!lpusage) {return cert_err_invalidparam;} if (Certgetintendedkeyusage (Global_encoding_type, M_pcertcontext->pcertinfo, Btusage, 2)) {if (BtUsage[0] & Cert_digital_signature_key_usage) {*lpusage = cert_usage_sign;} else if (Btusage[0] & cert_data_encipherment_key_usage) {*lpusage = Cert_usage_exch;} Else{*lpusage = 0;return Cert_err_usage_unknown;}} Else{return GetLastError ();} return CERT_ERR_OK;}

Five, Signature algorithm

The signature algorithm of a certificate refers to the algorithm used to sign the certificate (including the hash algorithm). The signature algorithm is represented by the Signaturealgorithm field in the structure cert_info, and the OID of the signature algorithm can be returned Pszobjid by Signaturealgorithm's subfield, so that the OID can know the specific meaning of the signature algorithm. Pszobjid is commonly defined as follows:

#define CERT_SIGNATURE_ALG_RSA_RSA "1.2.840.113549.1.1.1"   //rsa Direct Signature # define CERT_SIGNATURE_ALG_MD2RSA " 1.2.840.113549.1.1.2 "   //md2 as hash, then RSA signature # define CERT_SIGNATURE_ALG_MD4RSA" 1.2.840.113549.1.1.3 "   // MD4 as hash, then RSA signature # define CERT_SIGNATURE_ALG_MD5RSA "1.2.840.113549.1.1.4"   //md5 as hash, then RSA signature # define Cert_ Signature_alg_sha1rsa "1.2.840.113549.1.1.5"   //sha1 as hash, then RSA signature # define CERT_SIGNATURE_ALG_SM3SM2 " 1.2.156.10197.1.501 "    //sm3 for hash, then SM2 signature
Because Windows does not have a definition for the SM2/SM3 algorithm, for ECC certificates, Windows directly displays the OID of the signature algorithm: "1.2.156.10197.1.501", as shown in:



Vi. issuer

With regard to the issuer, we can get properties through Cert_name_issuer_flag. This is accomplished by the following two functions:

ULONG Ccspcertificate::get_issuer (LPSTR lpvalue, ulong *pullen) {ulong hr = CERT_ERR_OK; ULONG Ulissuerlen = 0; LPTSTR Lpszissuer = null;if (!m_pcertcontext) {return cert_err_invilidcall;} if (!pullen) {return cert_err_invalidparam;} hr = _getpropertyvalue (Szoid_common_name, Cert_name_issuer_flag, NULL, Ulissuerlen); if (0! = HR | | ulissuerlen = 0) {retur n HR;} if (!lpvalue) {*pullen = Ulissuerlen;return cert_err_ok;} if (*pullen <ulissuerlen) {return cert_err_buffer_too_small;} hr = _getpropertyvalue (Szoid_common_name, Cert_name_issuer_flag, Lpvalue, *pullen); if (0! = hr) {return hr;} return HR;} ULONG Ccspcertificate::_getpropertyvalue (LPCSTR szoid, DWORD Dwsourceid, LPSTR Lpvalue, DWORD &dwvallen) {if (!m_ Pcertcontext) {return cert_err_invilidcall;} Dwvallen = Certgetnamestringa (M_pcertcontext, cert_name_attr_type, Dwsourceid = Cert_name_issuer_flag? 1:0, (void*) SZ OId, NULL, 0); if (Dwvallen <= 1) {return GetLastError ();} if (!lpvalue) {return CERT_ERR_OK;} Dwvallen = Certgetnamestringa (m_pceRtcontext, cert_name_attr_type, Dwsourceid = = Cert_name_issuer_flag? 1:0, (void*) szoid, Lpvalue, Dwvallen); if (Dwvallen <= 1) {return GetLastError ();} return CERT_ERR_OK;}

Seven, users

The certificate consumer is represented by the subject field in the struct cert_info, but the Name_blob type, which calls Certnametostr () to the final string. The specific implementation functions are as follows:

ULONG Ccspcertificate::get_subjectname (LPSTR lpvalue, ULONG *pullen) {DWORD Dwsubjectlen = 0; Cert_name_blob certsubject;if (!m_pcertcontext) {return cert_err_invilidcall;} if (!pullen) {return cert_err_invalidparam;} Certsubject = M_pcertcontext->pcertinfo->subject;dwsubjectlen = Certnametostr (GLOBAL_ENCODING_TYPE, & Certsubject, Cert_x500_name_str, NULL, 0); if (Dwsubjectlen <= 1) {return e_fail;} if (!lpvalue) {*pullen = Dwsubjectlen;return cert_err_ok;} if (*pullen < Dwsubjectlen) {return cert_err_buffer_too_small;} *pullen = Certnametostra (Global_encoding_type, &certsubject, Cert_x500_name_str, LpValue, *pulLen); if (*pulLen <= 1) {return GetLastError ();} return CERT_ERR_OK;}

Viii. Period of validity

The validity period of the certificate, in the struct cert_info, corresponds to the field Notbefore and Notafter, both of which are FILETIME types. You can use the following function to convert it to the SYSTEMTIME type:

ULONG ccspcertificate::get_validdate (SYSTEMTIME *ptmstart, SYSTEMTIME *ptmend) {FILETIME ftstart; FILETIME ftend;if (!m_pcertcontext) {return cert_err_invilidcall;} if (Ptmstart) {memcpy (&ftstart, &m_pcertcontext->pcertinfo->notbefore, sizeof (FILETIME)); FileTimeToSystemTime (&ftstart, Ptmstart);} if (ptmend) {memcpy (&ftend, &m_pcertcontext->pcertinfo->notafter, sizeof (FILETIME)); FileTimeToSystemTime (&ftend, ptmend);} return CERT_ERR_OK;}

At this point, the basic items of the X509 certificate have been resolved! For data such as extensions or public keys for your certificate, follow the next blog post.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

CSP: Parsing X509 certificate Essentials with CryptoAPI

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.