C++ 实现证书文件的X509验证

参考:https://blog.csdn.net/hanghang121/article/details/51579280?utm_source=blogxgwz26&utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-4&spm=1001.2101.3001.4242

 

通过证书Server,验证证书的有效性

openssl实现了标准的x509v3数字证书,其源码在crypto/x509和crypto/x509v3中。其中x509目录实现了数字证书以及证书申请相关的各种函数,包括了X509和X509_REQ结构的设置、读取、打印和比较;数字证书的验证、摘要;各种公钥的导入导出等功能。x509v3目录主要实现了数字证书扩展项相关的函数。

在进行身份认证时,首先要对发送给服务器进行认证的x509证书有效性进行验证,在Openssl中,可以用一个API接口可以实现:int X509_verify_cert(X509_STORE_CTX *ctx); 
接口中形参是X509_STORE_CTX(X509证书库上下文)类型,在X509证书库上下文中,存在一个X509证书库和一个待验证的X509证书,可以加入信任的证书链,也可以加入CRL证书链(证书撤销列表)

 

步骤: 
1)初始化环境 
a.新建证书存储区X509_STORE_new() 
b.新建证书校验上下文X509_STORE_CTX_new() 

2)导入根证书 
a.读取CA证书,从DER编码格式化为X509结构d2i_X509() 
b.将CA证书导入证书存储区X509_STORE_add_cert() 

3)导入要校验的证书test 
a.读取证书test,从DER编码格式化为X509结构d2i_X509() 
b.在证书校验上下文初始化证书test,X509_STORE_CTX_init() 
c.校验X509_verify_cert 

 

代码:

复制代码
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 
  5 #include <openssl/evp.h>
  6 #include <openssl/x509.h>
  7 
  8 #define CERT_PATH "/home/ckelsel/work/rc4/cert"
  9 #define ROOT_CERT "ca.cer"
 10 #define WIN71H "win71h.cer"
 11 #define WIN71Y "win71y.cer"
 12 
 13 
 14 #define GET_DEFAULT_CA_CERT(str) sprintf(str, "%s/%s", CERT_PATH, ROOT_CERT)
 15 #define GET_CUSTOM_CERT(str, path, name) sprintf(str, "%s/%s", path, name)
 16 
 17 #define MAX_LEGTH 4096
 18 
 19 
 20 int my_load_cert(unsigned char *str, unsigned long *str_len,
 21               const char *verify_cert, const unsigned int cert_len)
 22 {
 23     FILE *fp;
 24     fp = fopen(verify_cert, "rb");
 25     if ( NULL == fp)
 26     {
 27         fprintf(stderr, "fopen fail\n");
 28         return -1;
 29     }
 30 
 31     *str_len = fread(str, 1, cert_len, fp);
 32     fclose(fp);
 33     return 0;
 34 }
 35 
 36 X509 *der_to_x509(const unsigned char *der_str, unsigned int der_str_len)
 37 {
 38     X509 *x509;
 39     x509 = d2i_X509(NULL, &der_str, der_str_len);
 40     if ( NULL == x509 )
 41     {
 42         fprintf(stderr, "d2i_X509 fail\n");
 43 
 44         return NULL;
 45     }
 46     return x509;
 47 }
 48 int x509_verify()
 49 {
 50     int ret;
 51     char cert[MAX_LEGTH];
 52 
 53     unsigned char user_der[MAX_LEGTH];
 54     unsigned long user_der_len;
 55     X509 *user = NULL;
 56 
 57     unsigned char ca_der[MAX_LEGTH];
 58     unsigned long ca_der_len;
 59     X509 *ca = NULL;
 60 
 61     X509_STORE *ca_store = NULL;
 62     X509_STORE_CTX *ctx = NULL;
 63     STACK_OF(X509) *ca_stack = NULL;
 64 
 65     /* x509初始化 */
 66     ca_store = X509_STORE_new();
 67     ctx = X509_STORE_CTX_new();
 68 
 69     /* root ca*/
 70     GET_DEFAULT_CA_CERT(cert);
 71     /* 从文件中读取 */
 72     my_load_cert(ca_der, &ca_der_len, cert, MAX_LEGTH);
 73     /* DER编码转X509结构 */
 74     ca = der_to_x509(ca_der, ca_der_len);
 75     /* 加入证书存储区 */
 76     ret = X509_STORE_add_cert(ca_store, ca);
 77     if ( ret != 1 )
 78     {
 79         fprintf(stderr, "X509_STORE_add_cert fail, ret = %d\n", ret);
 80         goto EXIT;
 81     }
 82 
 83     /* 需要校验的证书 */
 84     GET_CUSTOM_CERT(cert, CERT_PATH, WIN71H);
 85     my_load_cert(user_der, &user_der_len, cert, MAX_LEGTH);
 86     user = der_to_x509(user_der, user_der_len);
 87 
 88     ret = X509_STORE_CTX_init(ctx, ca_store, user, ca_stack);
 89     if ( ret != 1 )
 90     {
 91         fprintf(stderr, "X509_STORE_CTX_init fail, ret = %d\n", ret);
 92         goto EXIT;
 93     }
 94 
 95     //openssl-1.0.1c/crypto/x509/x509_vfy.h
 96     ret = X509_verify_cert(ctx);
 97     if ( ret != 1 )
 98     {
 99         fprintf(stderr, "X509_verify_cert fail, ret = %d, error id = %d, %s\n",
100                 ret, ctx->error, X509_verify_cert_error_string(ctx->error));
101         goto EXIT;
102     }
103 EXIT:
104     X509_free(user);
105     X509_free(ca);
106 
107     X509_STORE_CTX_cleanup(ctx);
108     X509_STORE_CTX_free(ctx);
109 
110     X509_STORE_free(ca_store);
111 
112     return ret == 1 ? 0 : -1;
113 }
114 
115 int main()
116 {
117     OpenSSL_add_all_algorithms();
118     x509_verify();
119     return 0;
120 }
复制代码

 

验证证书在本机是否受信 (Windows)

C#中可以实现证书文件的X509验证,从而验证证书在本机是否受信,代码很简单:

1  static void Main(string[] args)
2     {
3         //X509Certificate2 x509 = new X509Certificate2();
4         byte[] certData = File.ReadAllBytes(@"path\to\file\test.cer");
5         X509Certificate2 x509 = new X509Certificate2(certData); 
6         string result;
7         System.Console.WriteLine(x509.Verify());
8     }

在C++中需要读取系统store的所有证书,遍历并进行验证,代码如下,

  • 本例中通过Wolfssl进行验证, 调用Openssl或微软MFC的接口也可以实现
复制代码
 1 int FunctionsV2::VerifyCertFile(const std::string strFilename, int& status)
 2     {
 3         status = 0;
 4         PCCERT_CONTEXT  pTargetCert = NULL;
 5 
 6         HCERTSTORE hCertSys = CertOpenStore(
 7             CERT_STORE_PROV_SYSTEM,
 8             0,
 9             NULL,
10             CERT_SYSTEM_STORE_CURRENT_USER,
11             L"CA");
12 
13         if (hCertSys == nullptr)
14         {
15             return -1;
16         }
17 
18         X509* certification = X509_load_certificate_file(strFilename.c_str(), WOLFSSL_FILETYPE_ASN1);
19 
20         do 
21         {
22             if (pTargetCert = CertFindCertificateInStore(
23                 hCertSys,                    // Store handle.
24                 X509_ASN_ENCODING,            // Encoding type.
25                 0,                            // Not used.
26                 CERT_FIND_SUBJECT_STR_A,    // Find type. Find a string in the certificate's subject.
27                 0,                            // The string to be searched for.
28                 pTargetCert))                // Previous context.
29             {
30                 WOLFSSL_CERT_MANAGER* cm = wolfSSL_CertManagerNew();
31                 wolfSSL_CertManagerLoadCABuffer(cm, pTargetCert->pbCertEncoded, pTargetCert->cbCertEncoded, WOLFSSL_FILETYPE_ASN1);
32 
33                 const unsigned char* der;
34                 int der_length;
35                 der = wolfSSL_X509_get_der(certification, &der_length);
36                 int ret = wolfSSL_CertManagerVerifyBuffer(cm, der, der_length, SSL_FILETYPE_ASN1);
37                 wolfSSL_CertManagerFree(cm);
38                 if (ret == SSL_SUCCESS)
39                 {
40                     status = 1;
41                     break;
42                 }
43             }
44 
45         } while (pTargetCert != NULL);
46 
47         if (pTargetCert)
48         {
49             CertFreeCertificateContext(pTargetCert);
50         }
51         if (certification)
52         {
53             X509_free(certification);
54         }
55 
56         return 0;
57     }
复制代码

 

posted @   Asp1rant  阅读(2476)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示