Verify certificate with OPENSSL and CryptoAPI
2015-11-30 14:48
429 查看
OPENSSL
Setps:
1, Input the encoded der certificate into X509struct.
2, New a X509 store and input the root certificate.
3, Inputencoded
CRL into the store and set X509_V_FLAG_CRL_CHECK.
4, New a store context and input the root restore and subject certificate.
5, Call X509_verify_cert to verify the certificate. And the function also checkCRL signature.
Here is the sample code:
/*
note: check certificate with OPENSSL
parameter:
char *szRootFP, root CA certificate file path
char *szCertFP, subject certificate file path
char *szCRLFP, CRL file path
return:
1, success
0, error
*/
boolverify509Cert(unsignedchar
*bRoot, int iRootLen,unsigned
char *bCert,int iCertLen,
unsignedchar *bCRL,
int iCrlLen)
{
int iRet = 0;
X509_STORE_CTX *ctx = NULL;
//证书存储区句柄
X509 *usrCert = NULL;
//X509证书结构体,保存用户证书
X509 *caCert = NULL;
//X509证书结构体,保存CA 证书
X509 *rootCert = NULL;
//X509证书结构体,保存根证书
X509_CRL *Crl = NULL;
//X509_CRL结构体,保存CRL
STACK_OF(X509) *caCertStack = NULL;
X509_STORE *rootCertStore = NULL;
//证书存储区
//
把DER 编码的根证书转化为X509 结构体
rootCert = d2i_X509(NULL,(const
unsigned char **)&bRoot,iRootLen);
if (rootCert==NULL)
return
false ;
//
把DER 编码的用户证书转化为X509 结构体
usrCert = d2i_X509(NULL,(const
unsigned char **)&bCert,iCertLen);
if (usrCert==NULL)
return
false ;
//
新建X509 证书存储区
rootCertStore = X509_STORE_new();
//
添加根证书到证书存储区
X509_STORE_add_cert(rootCertStore,rootCert);
//
设置检查CRL 标志位,如果设置此标志位,则检查CRL ,否则不检查CRL 。
if (NULL != bCRL) {
if (*bCRL != '/0') {
//
把DER 编码的CRL 转化为X509_CRL 结构体
Crl = d2i_X509_CRL(NULL,(const
unsigned char **)&bCRL,iCrlLen);
if (Crl==NULL) {
X509_free(rootCert);
return
false ;
}
X509_STORE_set_flags(rootCertStore,X509_V_FLAG_CRL_CHECK);
//
添加CRL 到证书存储区
X509_STORE_add_crl(rootCertStore,Crl);
}
}
//
新建证书存储区句柄
ctx = X509_STORE_CTX_new();
//
初始化根证书存储区、用户证书1
iRet = X509_STORE_CTX_init(ctx,rootCertStore,usrCert,caCertStack);
if (iRet != 1)
{
printf("X509_STORE_CTX_init err/n");
X509_free(usrCert);
X509_free(rootCert);
X509_STORE_CTX_cleanup(ctx);
X509_STORE_CTX_free(ctx);
X509_STORE_free(rootCertStore);
return
false ;
}
//
验证用户证书
iRet = X509_verify_cert(ctx);
if (iRet != 1)
{
printf("verify cer err.error= %d,info:%s/n",ctx->error,X509_verify_cert_error_string(ctx->error));
}
//
释放内存
X509_free(usrCert);
X509_free(rootCert);
X509_STORE_CTX_cleanup(ctx);
X509_STORE_CTX_free(ctx);
X509_STORE_free(rootCertStore);
return 1 == iRet ?
true : false ;
}
CryptoAPI
To use CryptoAPI, we need to include "Wincrypt.h" and link to crypt32.lib first.
Steps to check certificate and CRL
1, Add rood certificate and CRL into one cert store,
2, Add subject certificate into a cert context.
3, Check cert by callingCertVerifySubjectCertificateContext().
By setting the flag we can check signature, RCL, and time:
the flag can be the combination of
CERT_STORE_REVOCATION_FLAG 0x04
CERT_STORE_SIGNATURE_FLAG 0x01
CERT_STORE_TIME_VALIDITY_FLAG 0x02
Here we need to note that the function return true no matter if the cert is valid. We need to check the validation of cert by checking returned flag value. If be checked OK the
flag will be 0, otherwise the flag remain unchanged.
For example, to enable both signature and time validity, the value CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG is placed in the pdwFlags DWORD value as an input parameter.
If CERT_STORE_SIGNATURE_FLAG verification succeeds, but CERT_STORE_TIME_VALIDITY_FLAG verification fails, pdwFlags is set to CERT_STORE_TIME_VALIDITY_FLAG when the function returns.
If CERT_STORE_REVOCATION_FLAG was enabled and the issuer does not have a CRL in the store, then CERT_STORE_NO_CRL_FLAG is set in addition to CERT_STORE_REVOCATION_FLAG. //CERT_STORE_NO_CRL_FLAG
0x00010000
So if there is no CRL in store, we check a valid cert and we got the returned flag value 0x00010004, and we check a invalid subject certificate, the return value will be 0x00010005.
And here is the code of certificate checking function:
/*
notes:check certificate with CryptoAPI
parameter:
char *szRootFP, root CA certificate file path
char *szCertFP, subject certificate file path
char *szCRLFP, CRL file path
return:
1, success
0, system error
-1, invalid certificate
4, revoked certificate
*/
intcheckCert(char *szRootFP,char
*szCertFP, char *szCRLFP)
{
int iRet = 0;
PCCERT_CONTEXT
pCertRootContext = NULL;
PCCERT_CONTEXT
pCertContext = NULL;
HCERTSTORE hMemStore = NULL;
unsigned
char usrCertificate[4096] = {0};//DER
证书缓冲区数组
unsigned
long usrCertificateLen = 0; //
证书长度
unsigned
char derCrl[4096] = {0}; //CRL
缓冲区数组
unsigned
long derCrlLen = 0; //CRL
长度
unsigned
char derRootCert[4096] = {0};//
根证书缓冲区数组
unsigned
long derRootCertLen = 0; //
根证书长度
DWORD dwFlags = 0;
// flag for CertVerifySubjectCertificateContext
// error check
if (NULL == szRootFP || NULL == szCertFP)
return
false ;
FILE *fp;
//
读取根证书
fp = fopen(szRootFP, "rb");
if (fp==NULL)
return
false ;
derRootCertLen = fread(derRootCert,1,sizeof (derRootCert),fp);
fclose(fp);
//
读取CRL 文件
if (NULL != szCRLFP){
if (*szCRLFP != '/0') {
fp=fopen(szCRL,"rb");
if (fp==NULL)
{
printf("open file err/n");
return
false ;
}
derCrlLen = fread(derCrl,1,sizeof (derCrl),fp);
fclose(fp);
dwFlags = CERT_STORE_REVOCATION_FLAG;
}
}
//
读取待验证的用户证书
fp=fopen(szCertFP,"rb");
if (fp==NULL)
{
printf("open file err/n");
return
false ;
}
usrCertificateLen = fread(usrCertificate,1,sizeof (usrCertificate),fp);
fclose(fp);
// add subject cert to context
pCertContext = CertCreateCertificateContext(
MY_ENCODING_TYPE,
// Encoding type
usrCertificate,
// Encoded data from the certificate retrieved
usrCertificateLen);
// Length of the encoded data
if (NULL == pCertContext)
goto end;
// add to root context
// here we use store
//pCertRootContext = CertCreateCertificateContext(
//
MY_ENCODING_TYPE, // Encoding type
//
derRootCert, // Encoded data from the certificate retrieved
//
derRootCertLen); // Length of the encoded data
//if(NULL == pCertRootContext)
//
goto end;
//iRet = CertAddCertificateContextToStore(
//
hMemStore,
//
pCertRootContext,
//
CERT_STORE_ADD_ALWAYS,
//
& pStoreContext
//);
//if (iRet != true)
//
goto end;
hMemStore = CertOpenStore(
CERT_STORE_PROV_MEMORY,
// the memory provider type
0,
// the encoding type is not needed
NULL,
// use the default HCRYPTPROV
0,
// accept the default dwFlags
NULL
// pvPara is not used
);
if (NULL == hMemStore)
goto end;
// add root cert
iRet = CertAddEncodedCertificateToStore(
hMemStore,
MY_ENCODING_TYPE,
derRootCert,
derRootCertLen,
CERT_STORE_ADD_ALWAYS,
& pCertRootContext
);
if (iRet !=
true )
goto end;
// if need check RCL, go this way
if (CERT_STORE_REVOCATION_FLAG == dwFlags){
// add crl
iRet = CertAddEncodedCRLToStore(
hMemStore,
MY_ENCODING_TYPE,
derCrl,
derCrlLen,
CERT_STORE_ADD_ALWAYS,
NULL
);
if (iRet !=
true )
goto end;
}
// check the cert
// the flag can be
// CERT_STORE_REVOCATION_FLAG 0x04
// CERT_STORE_SIGNATURE_FLAG 0x01
// CERT_STORE_TIME_VALIDITY_FLAG 0x02
dwFlags |= CERT_STORE_SIGNATURE_FLAG;// | CERT_STORE_REVOCATION_FLAG;
iRet = CertVerifySubjectCertificateContext(
pCertContext,
pCertRootContext,
& dwFlags
);
end:
// clean resource
if (pCertContext)
CertFreeCertificateContext(pCertContext);
if (pCertRootContext)
CertFreeCertificateContext(pCertRootContext);
if (hMemStore)
CertCloseStore(hMemStore, 0);
// return result
if (iRet !=
true )
return
false ;
if (dwFlags != 0)
return dwFlags == CERT_STORE_SIGNATURE_FLAG ? -1 : dwFlags;
return
true ;
}
We may also use the following functions to check CRL:
CertCreateCRLContext
CertIsValidCRLForCertificate
CertFindCertificateInCRL
We need to note that the function CertIsValidCRLForCertificate does not look for the certificate in the CRL, we need to call CryptVerifyCertificateSignature to check
CRL signature.
More detail ofCryptoAPI check MSDN:
ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.WIN32COM.v10.en/seccrypto/security/cryptography_functions.htm#certificate_and_certificate_store_functions
By the way, all the test above is in windows platform, I will test in CE platform later.
方法:
//创建证书上下文
PCCERT_CONTEXT pCertContextRoot = CertCreateCertificateContext(X509_ASN_ENCODING, szCACert, nCACertLen);
if (pCertContextRoot == NULL)
{
return ;
}
PCCERT_CONTEXT pCertContextUser = CertCreateCertificateContext(X509_ASN_ENCODING, szUserCert, nUserCertLen);
if (pCertContextUser == NULL)
{
return ;
}
//使用根公钥对用户证书验签
if (!CryptVerifyCertificateSignature(
NULL,
X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,
pCertContextUser->pbCertEncoded,//UserCertInfo,
pCertContextUser->cbCertEncoded,//nUserCertInfoSize,
&(pCertContextRoot->pCertInfo->SubjectPublicKeyInfo))) //CA证书公钥
{
GetLastError();
return ;
}
From:/article/8848677.html
OPENSSL
Setps:
1, Input the encoded der certificate into X509struct.
2, New a X509 store and input the root certificate.
3, Inputencoded
CRL into the store and set X509_V_FLAG_CRL_CHECK.
4, New a store context and input the root restore and subject certificate.
5, Call X509_verify_cert to verify the certificate. And the function also checkCRL signature.
Here is the sample code:
/*
note: check certificate with OPENSSL
parameter:
char *szRootFP, root CA certificate file path
char *szCertFP, subject certificate file path
char *szCRLFP, CRL file path
return:
1, success
0, error
*/
boolverify509Cert(unsignedchar
*bRoot, int iRootLen,unsigned
char *bCert,int iCertLen,
unsignedchar *bCRL,
int iCrlLen)
{
int iRet = 0;
X509_STORE_CTX *ctx = NULL;
//证书存储区句柄
X509 *usrCert = NULL;
//X509证书结构体,保存用户证书
X509 *caCert = NULL;
//X509证书结构体,保存CA 证书
X509 *rootCert = NULL;
//X509证书结构体,保存根证书
X509_CRL *Crl = NULL;
//X509_CRL结构体,保存CRL
STACK_OF(X509) *caCertStack = NULL;
X509_STORE *rootCertStore = NULL;
//证书存储区
//
把DER 编码的根证书转化为X509 结构体
rootCert = d2i_X509(NULL,(const
unsigned char **)&bRoot,iRootLen);
if (rootCert==NULL)
return
false ;
//
把DER 编码的用户证书转化为X509 结构体
usrCert = d2i_X509(NULL,(const
unsigned char **)&bCert,iCertLen);
if (usrCert==NULL)
return
false ;
//
新建X509 证书存储区
rootCertStore = X509_STORE_new();
//
添加根证书到证书存储区
X509_STORE_add_cert(rootCertStore,rootCert);
//
设置检查CRL 标志位,如果设置此标志位,则检查CRL ,否则不检查CRL 。
if (NULL != bCRL) {
if (*bCRL != '/0') {
//
把DER 编码的CRL 转化为X509_CRL 结构体
Crl = d2i_X509_CRL(NULL,(const
unsigned char **)&bCRL,iCrlLen);
if (Crl==NULL) {
X509_free(rootCert);
return
false ;
}
X509_STORE_set_flags(rootCertStore,X509_V_FLAG_CRL_CHECK);
//
添加CRL 到证书存储区
X509_STORE_add_crl(rootCertStore,Crl);
}
}
//
新建证书存储区句柄
ctx = X509_STORE_CTX_new();
//
初始化根证书存储区、用户证书1
iRet = X509_STORE_CTX_init(ctx,rootCertStore,usrCert,caCertStack);
if (iRet != 1)
{
printf("X509_STORE_CTX_init err/n");
X509_free(usrCert);
X509_free(rootCert);
X509_STORE_CTX_cleanup(ctx);
X509_STORE_CTX_free(ctx);
X509_STORE_free(rootCertStore);
return
false ;
}
//
验证用户证书
iRet = X509_verify_cert(ctx);
if (iRet != 1)
{
printf("verify cer err.error= %d,info:%s/n",ctx->error,X509_verify_cert_error_string(ctx->error));
}
//
释放内存
X509_free(usrCert);
X509_free(rootCert);
X509_STORE_CTX_cleanup(ctx);
X509_STORE_CTX_free(ctx);
X509_STORE_free(rootCertStore);
return 1 == iRet ?
true : false ;
}
CryptoAPI
To use CryptoAPI, we need to include "Wincrypt.h" and link to crypt32.lib first.
Steps to check certificate and CRL
1, Add rood certificate and CRL into one cert store,
2, Add subject certificate into a cert context.
3, Check cert by callingCertVerifySubjectCertificateContext().
By setting the flag we can check signature, RCL, and time:
the flag can be the combination of
CERT_STORE_REVOCATION_FLAG 0x04
CERT_STORE_SIGNATURE_FLAG 0x01
CERT_STORE_TIME_VALIDITY_FLAG 0x02
Here we need to note that the function return true no matter if the cert is valid. We need to check the validation of cert by checking returned flag value. If be checked OK the
flag will be 0, otherwise the flag remain unchanged.
For example, to enable both signature and time validity, the value CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG is placed in the pdwFlags DWORD value as an input parameter.
If CERT_STORE_SIGNATURE_FLAG verification succeeds, but CERT_STORE_TIME_VALIDITY_FLAG verification fails, pdwFlags is set to CERT_STORE_TIME_VALIDITY_FLAG when the function returns.
If CERT_STORE_REVOCATION_FLAG was enabled and the issuer does not have a CRL in the store, then CERT_STORE_NO_CRL_FLAG is set in addition to CERT_STORE_REVOCATION_FLAG. //CERT_STORE_NO_CRL_FLAG
0x00010000
So if there is no CRL in store, we check a valid cert and we got the returned flag value 0x00010004, and we check a invalid subject certificate, the return value will be 0x00010005.
And here is the code of certificate checking function:
/*
notes:check certificate with CryptoAPI
parameter:
char *szRootFP, root CA certificate file path
char *szCertFP, subject certificate file path
char *szCRLFP, CRL file path
return:
1, success
0, system error
-1, invalid certificate
4, revoked certificate
*/
intcheckCert(char *szRootFP,char
*szCertFP, char *szCRLFP)
{
int iRet = 0;
PCCERT_CONTEXT
pCertRootContext = NULL;
PCCERT_CONTEXT
pCertContext = NULL;
HCERTSTORE hMemStore = NULL;
unsigned
char usrCertificate[4096] = {0};//DER
证书缓冲区数组
unsigned
long usrCertificateLen = 0; //
证书长度
unsigned
char derCrl[4096] = {0}; //CRL
缓冲区数组
unsigned
long derCrlLen = 0; //CRL
长度
unsigned
char derRootCert[4096] = {0};//
根证书缓冲区数组
unsigned
long derRootCertLen = 0; //
根证书长度
DWORD dwFlags = 0;
// flag for CertVerifySubjectCertificateContext
// error check
if (NULL == szRootFP || NULL == szCertFP)
return
false ;
FILE *fp;
//
读取根证书
fp = fopen(szRootFP, "rb");
if (fp==NULL)
return
false ;
derRootCertLen = fread(derRootCert,1,sizeof (derRootCert),fp);
fclose(fp);
//
读取CRL 文件
if (NULL != szCRLFP){
if (*szCRLFP != '/0') {
fp=fopen(szCRL,"rb");
if (fp==NULL)
{
printf("open file err/n");
return
false ;
}
derCrlLen = fread(derCrl,1,sizeof (derCrl),fp);
fclose(fp);
dwFlags = CERT_STORE_REVOCATION_FLAG;
}
}
//
读取待验证的用户证书
fp=fopen(szCertFP,"rb");
if (fp==NULL)
{
printf("open file err/n");
return
false ;
}
usrCertificateLen = fread(usrCertificate,1,sizeof (usrCertificate),fp);
fclose(fp);
// add subject cert to context
pCertContext = CertCreateCertificateContext(
MY_ENCODING_TYPE,
// Encoding type
usrCertificate,
// Encoded data from the certificate retrieved
usrCertificateLen);
// Length of the encoded data
if (NULL == pCertContext)
goto end;
// add to root context
// here we use store
//pCertRootContext = CertCreateCertificateContext(
//
MY_ENCODING_TYPE, // Encoding type
//
derRootCert, // Encoded data from the certificate retrieved
//
derRootCertLen); // Length of the encoded data
//if(NULL == pCertRootContext)
//
goto end;
//iRet = CertAddCertificateContextToStore(
//
hMemStore,
//
pCertRootContext,
//
CERT_STORE_ADD_ALWAYS,
//
& pStoreContext
//);
//if (iRet != true)
//
goto end;
hMemStore = CertOpenStore(
CERT_STORE_PROV_MEMORY,
// the memory provider type
0,
// the encoding type is not needed
NULL,
// use the default HCRYPTPROV
0,
// accept the default dwFlags
NULL
// pvPara is not used
);
if (NULL == hMemStore)
goto end;
// add root cert
iRet = CertAddEncodedCertificateToStore(
hMemStore,
MY_ENCODING_TYPE,
derRootCert,
derRootCertLen,
CERT_STORE_ADD_ALWAYS,
& pCertRootContext
);
if (iRet !=
true )
goto end;
// if need check RCL, go this way
if (CERT_STORE_REVOCATION_FLAG == dwFlags){
// add crl
iRet = CertAddEncodedCRLToStore(
hMemStore,
MY_ENCODING_TYPE,
derCrl,
derCrlLen,
CERT_STORE_ADD_ALWAYS,
NULL
);
if (iRet !=
true )
goto end;
}
// check the cert
// the flag can be
// CERT_STORE_REVOCATION_FLAG 0x04
// CERT_STORE_SIGNATURE_FLAG 0x01
// CERT_STORE_TIME_VALIDITY_FLAG 0x02
dwFlags |= CERT_STORE_SIGNATURE_FLAG;// | CERT_STORE_REVOCATION_FLAG;
iRet = CertVerifySubjectCertificateContext(
pCertContext,
pCertRootContext,
& dwFlags
);
end:
// clean resource
if (pCertContext)
CertFreeCertificateContext(pCertContext);
if (pCertRootContext)
CertFreeCertificateContext(pCertRootContext);
if (hMemStore)
CertCloseStore(hMemStore, 0);
// return result
if (iRet !=
true )
return
false ;
if (dwFlags != 0)
return dwFlags == CERT_STORE_SIGNATURE_FLAG ? -1 : dwFlags;
return
true ;
}
We may also use the following functions to check CRL:
CertCreateCRLContext
CertIsValidCRLForCertificate
CertFindCertificateInCRL
We need to note that the function CertIsValidCRLForCertificate does not look for the certificate in the CRL, we need to call CryptVerifyCertificateSignature to check
CRL signature.
More detail ofCryptoAPI check MSDN:
ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.WIN32COM.v10.en/seccrypto/security/cryptography_functions.htm#certificate_and_certificate_store_functions
By the way, all the test above is in windows platform, I will test in CE platform later.
方法:
//创建证书上下文
PCCERT_CONTEXT pCertContextRoot = CertCreateCertificateContext(X509_ASN_ENCODING, szCACert, nCACertLen);
if (pCertContextRoot == NULL)
{
return ;
}
PCCERT_CONTEXT pCertContextUser = CertCreateCertificateContext(X509_ASN_ENCODING, szUserCert, nUserCertLen);
if (pCertContextUser == NULL)
{
return ;
}
//使用根公钥对用户证书验签
if (!CryptVerifyCertificateSignature(
NULL,
X509_ASN_ENCODING|PKCS_7_ASN_ENCODING,
pCertContextUser->pbCertEncoded,//UserCertInfo,
pCertContextUser->cbCertEncoded,//nUserCertInfoSize,
&(pCertContextRoot->pCertInfo->SubjectPublicKeyInfo))) //CA证书公钥
{
GetLastError();
return ;
}
From:/article/8848677.html
相关文章推荐
- pexpect-pxssh-登陆Linux-执行命令
- apache的poi读写excel
- [Hadoop 2.6.0] Remote Submit Job Error:[ExitCodeException: /bin/bash: line 0: fg: no job control]
- 在Java中读取EXCEL文件 JExcelAPI与Apache POI两者对比
- linux下系统定时任务配置----crontab(mysql定时备份)
- shell用if
- Linux下Opencv的安装及配置使用
- htm.dropdownlist
- 自动化运维利器之cobbler安装centos7
- Linux下安装Matlab2014及破解
- Linux下查看端口占用进程号,程序名的方法
- CentOS 6.4下PXE+Kickstart无人值守安装操作系统
- linux 二进制 安装mysql 5.5.46
- OpenStack基础知识
- Apache下url不带扩展名也能访问文件的解决办法
- linux shell 脚本中的set -e 是什么意思?
- linux基础命令学习之echo(8)
- centos 运用ssh的rsa算法实现无密码登录
- linux 终端相关
- tomcat设置manager