我尝试理解CA存储的概念,并使用我自己的证书链进行测试,而不影响系统范围。
我的本地主目录下有一个 ca_store 目录,其中包含一个根 CA 和一个中间 CA。
$ ls /home/my/ca_store
root_ca.crt intermediate_ca.crt
我还有服务器证书。使用openssl命令验证成功。我只想使用 C 代码来做到这一点,最好是 CA 存储的概念。
以下代码无法正确验证server.crt,但是可以使其工作吗?
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
SSL_CTX_load_verify_locations(ctx, NULL, "/home/my/ca_store");
BIO* bio = BIO_new_file("server.crt", "rb");
X509* cert = X509_new();
PEM_read_bio_X509(bio, &cert, NULL, NULL);
X509_STORE_CTX* store_ctx = X509_STORE_CTX_new();
X509_STORE_CTX_init(store_ctx, SSL_CTX_get_cert_store(ctx), cert, NULL);
int ret = X509_verify_cert(store_ctx);
if (ret != 1)
{
int error = X509_STORE_CTX_get_error(store_ctx);
const char *error_str = X509_verify_cert_error_string(error);
printf("Certificate verification failed. Error code: %d, Error message: %s\n", error, error_str);
ERR_print_errors_fp(stdout);
}
else
{
printf("Certificate verification successful\n");
}
以下是输出。
Certificate verification failed. Error code: 20, Error message: unable to get local issuer certificate
您的文件名错误。根据 OpenSSL 的
SSL_CTX_load_verify_locations()
文档(粗体我的):
如果CApath不为NULL,则指向包含PEM格式的CA证书的目录。每个文件都包含一个 CA 证书。 通过 CA 主题名称哈希值查找文件,因此该值必须可用。如果存在多个具有相同名称哈希值的 CA 证书,则扩展名必须不同(例如 9d66eef0.0、9d66eef0.1 等)。无论证书的其他属性如何,都会按照分机号的顺序执行搜索。使用 c_rehash 实用程序创建必要的链接。
将文件合并为一个并使用
CAfile
参数会更容易:
cat root_ca.crt intermediate_ca.crt > truststore.pem
然后
SSL_CTX_load_verify_locations(ctx, "/home/my/ca_store/truststore.pem", NULL);