Openssl:在SSL_CTX_load_verify_locations API中使用CApath参数时,证书validation失败

我正在尝试与服务器计算机建立TLS连接。 我使用openssl CLI命令创建了根CA证书和服务器证书。 我创建了服务器证书,其通用名称与其IP地址相同。 根CA证书的通用名称是服务器的FQDN。

我正在使用openssl库API建立与服务器的连接。 我正在使用API

int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath)

用于设置CA文件查找路径。

当我使用CAfile参数指定我的CA文件的路径时,一切正常,将CApath参数保留为NULL。

但是,如果我使用CApath参数指定包含CA文件的目录的路径,将CAfile参数保留为NULL,则由于证书validation错误,连接将失败。

当我使用wireshark捕获数据包时,我发现我的客户端代码正在从服务器发送“服务器问候”的TLS响应“未知CA”。 我使用了在成功连接中使用的相同CA证书文件。

根据我在探索openssl库源代码时的观察,我推断,在我的情况下,CA文件不被认为是有效的,因此由于某些未知原因而未被库API加载。

有人可以告诉我原因,如果可能的话,可以解决这个问题吗?

我正在为自己的问题发布答案,因为我花了很多时间为这个问题寻找解决方案,因为我没有从互联网上获得有关此问题的太多信息。 我希望这将有助于其他面临类似问题的人。

如果CApath不为null,则CApath指向的目录应包含有效的CA证书。 最重要的是CA文件名应该是主题名哈希值。

可以将CA文件重命名为其主题名称哈希值,也可以使用与CA文件的CA主题名称哈希相同的名称创建CA文件的软链接。

c_rehash实用程序可用于在CApath中创建必要的链接。 这个sipmle的语法。

 c_rehash  

c_rehash实用程序可能并非在所有Linux发行版中都可用。 在这种情况下

 openssl x509 -in  -noout -subject_hash 

可用于生成主题名称哈希(例如e5d93f80)。 只需将“.0”附加到此值,并使用此名称(e5d93f80.0)创建一个到CA文件的软链接。 如果有多个CA文件具有相同的主题名称哈希值,则它们的扩展名应该不同(例如e5d93f80.1)。 搜索是在分机号码的排序中进行的。

opensssl引入了这种技术来减少CA文件的查找时间。 否则openssl可能必须读取CApath中的所有文件以查找匹配的CA文件。