Ubuntu上默认证书库是怎么回事

RMAG news

背景

最近整HTTP3客户端时候,需要验证服务端证书,中间出了点小插曲,老是报错见上篇文章,问题解决了但是想到另外个问题,浏览器和客户端都是怎么验证证书的,我们都知道服务端给出证书,客户端根据本地的或者用户提供的根证书校验,但是系统根证书在哪儿,为什么我没有设置,他们就自动找到了?本文旨在根据这个问题,梳理Ubuntu系统自带证书库和浏览器的证书库。本文主要聚焦Ubuntu系统,但是其他系统的流程大致相似。

系统证书库

Ubuntu系统的证书目录位于/etc/ssl/certs, 根证书是/etc/ssl/certs/ca-certificates.crt。 其他平台的默认证书可以查看golang源码文件

查看/etc/ssl/certs发现里面有很多pem格式证书,这里就是系统根证书目录,我的机器上面有部分软链接到/usr/share/ca-certificates/mozilla(这个是系统读取/etc/ca-certificates.conf配置加入的)。文件/etc/ssl/certs/ca-certificates.crt是这些证书的合集,可以使用如下命令查看所有证书的subject

awk -v cmd=‘openssl x509 -noout -subject’ ‘/BEGIN/ {close(cmd)}; {print | cmd}’ < /etc/ssl/certs/ca-certificates.crt

系统证书更新

系统不建议我们自己手动证书到这个目录和文件中,那我们如何添加证书到系统呢?系统提供了命令update-ca-certificates

man 8 update-ca-certificates

根据manpage介绍,update-ca-certificates更新etc/ssl/certs和ca-certificates.crt。我们将pem格式证书以.crt后缀放到/usr/local/share/ca-certificates,一个证书一个文件,然后执行命令就会自动添加到根目录证书中。

寻找证书

刚才不建议咱们自己添加证书,因为其中有些步骤是看不见的,比如c_rehash过程。寻找证书通过证书的subject,如果通过打开文件找到subject比对,那这样效率太低了,所以通过将证书的subject的hash值作为文件名,就可以提高寻找效率了,rehash就是干这个事。比如,我的系统中有个Go_Daddy_Class_2_CA.pem证书

ll /etc/ssl/certs | grep ‘Go_Daddy_Class_2_CA’
# f081611a.0 -> Go_Daddy_Class_2_CA.pem 这个是rehash生成文件
# Go_Daddy_Class_2_CA.pem -> /usr/share/ca-certificates/mozilla/Go_Daddy_Class_2_CA.crt

可以通过以下命令看下hash值是否正确(当然是正确的)

openssl x509 -hash -fingerprint -noout -in $(readlink -f /etc/ssl/certs/Go_Daddy_Class_2_CA.pem)
# f081611a
# SHA1 Fingerprint=27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4

最后的.0是为了防止hash碰撞产生一样的值。

OpenSSL

OpenSSL默认情况使用系统证书库

openssl version -d # 打印OpenSSL目录
ls -l $(openssl version -d | tr -d ‘”‘ | awk ‘{print $2}’) # 查看OpenSSL目录内容

通过查看OpenSSL目录,里面的certs文件夹默认是软链接到/etc/ssl/certs。因此OpenSSL编写代码使用默认证书库就是系统证书库

SSL_CTX_set_default_verify_paths(ssl_ctx);

浏览器

浏览器一般使用图形界面设置,但是我就觉得纳闷了,我在浏览器中设置了,但是根目录证书中没有,猜想肯定使用自己证书库,查找后确定是这样的。

Firefox和Chrome都使用sqlite存储用户导入证书,具体放在文件cert9.db中,早期放在cert8.db,这里咱们不溯源历史,有兴趣可以查看相关文档。同样,这个数据库不建议直接操作,浏览器都使用了NSS_Shared_DB管理数据库,提供了命令certutil操作,Ubuntu需要安装libnss3-tools

sudo apt install libnss3-tools

Chromium源码文档中有提供如何操作。

查找浏览器证书库地址

命令操作没啥问题,但是关键是制定证书的数据库地址。Ubuntu一般使用snap(尽管不想使用)按照Chrome,会放在snap目录$HOME/snap/[chromium|firefox],如果没有snap目录,可以查看个人目录隐藏文件夹$HOME/.pki/nssdb,可能会不一样,可以通过查找方式查询:

find $HOME -type f -name ‘cert9.db’

注意浏览器都是以用户(profile)形式生成cert9.db的,Chromium系列明显亲民点,可以使用比如$HOME/snap/chromium/current软链接到当前用户目录。

JKS(Java Key Store)

在前面查看/etc/ssl/certs目录时,看到有个文件夹java,翻看资料后发现,JAVA平台可以使用自己的证书库,支持多种存储格式,JKS的store位于$JAVA_HOME/lib/security/cacerts或者$JAVA_HOME/jre/lib/security/cacerts,JKS使用JDK提供的工具keytool管理。JKS的store默认密码是changeit。

# find JAVA_HOME
export JAVA_HOME=readlink -f $(which java) | sed ‘s//bin/java//’

# List
keytool -list -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit | head -5
# OR
keytool -list -cacerts -storepass changeit | head -5

# Add
keytook -import -alias testCert -keystore $JAVA_HOME/lib/security/cacerts -file ca_cert.crt

有用知识

工具mkcert是cert操作相关的库,里面有上面的相关信息,有兴趣可以仔细查看阅读。