如何检查X509根证书是否在系统可信证书库中(C语言OpenSSL实现)
手动验证OpenSSL证书链中的根证书
要拒绝untrusted-root.badssl.com或self-signed.badssl.com这类无效证书,核心是确认链中最后一个证书是系统可信库中被认可的根证书,而不是仅检查签名或信任标志。以下是具体实现步骤和代码:
核心思路
- 在系统可信库中查找与待验证根证书匹配的条目(不能直接内存比较,需通过主体名称/密钥哈希匹配)。
- 验证该可信证书是否被允许用于TLS服务器认证(或对应场景的用途)。
- 确认根证书是合法自签的(可信根必须自签)。
实现代码
X509* cert; // 证书链的最后一个证书(待验证的根证书) X509_STORE* store = SSL_CTX_get_cert_store(ctx); // 系统可信证书库 // 1. 在可信库中查找匹配的根证书 X509_LOOKUP* lookup = X509_STORE_get_lookup(store); if (lookup == NULL) { fprintf(stderr, "Failed to get lookup from trusted store\n"); return -1; } X509_NAME* subject_name = X509_get_subject_name(cert); X509* trusted_root = X509_LOOKUP_find(lookup, X509_LOOKUP_BY_SUBJECT_NAME, subject_name); if (trusted_root == NULL) { // 根证书不在可信库中,直接拒绝 fprintf(stderr, "Root certificate not found in trusted store\n"); return -1; } // 2. 验证该证书是否被信任用于TLS服务器认证 int trust_status = X509_check_trust(trusted_root, X509_TRUST_TLS_SERVER, NULL); if (trust_status != X509_V_OK) { fprintf(stderr, "Root certificate is not trusted for TLS server auth\n"); X509_free(trusted_root); return -1; } // 3. 确认根证书是合法自签的(可信根必须满足) if (!X509_self_signed(trusted_root)) { fprintf(stderr, "Trusted root certificate is not self-signed\n"); X509_free(trusted_root); return -1; } // 所有验证通过 X509_free(trusted_root); return 0;
关键细节说明
- 可信库查找:使用
X509_LOOKUP_find而非直接内存比较,因为系统可信库中的证书可能存在编码、扩展差异,但主体名称/密钥标识是一致的,查找函数会自动匹配对应条目。 - 信任用途检查:
X509_check_trust的X509_TRUST_TLS_SERVER参数限定证书用途为TLS服务器认证,能排除那些可信但不适用于该场景的证书(比如仅用于代码签名的根证书)。 - 自签检查:
X509_self_signed仅验证签名有效性,不能替代可信库检查——self-signed.badssl.com的证书是自签且签名有效,但不在可信库中,所以必须结合前面的查找步骤。
为什么之前的方法无效
X509_trusted:仅检查证书的内部TRUSTED标志,需要手动标记证书为可信,而非从系统库中查找,因此无法识别系统不认可的根证书。X509_self_signed:只验证签名逻辑,不关心证书是否在可信库中,所以无法区分合法自签根和恶意自签证书。
内容的提问来源于stack exchange,提问作者zxcvber
相关产品推荐
相关产品推荐

