HTTPS的双向认证(二)

这篇文章接着讲解下面架构当中的三张证书的创建过程:

从上面的架构可以看到一共有三张证书:

上面的证书,有几点需要注意的:

关于证书和密钥的注意点就讲这么多。关于公钥加密,非对称加密的基础知识,不是本文讲解重点,需要大家自己系统学习。本文侧重讲解应用和架构。接下来介绍三张证书的创建过程,以及客户端证书的签名过程。因为篇幅关系,这篇文章只讲「服务端证书」的创建过程,并仔细分析证书内容。

创建服务端证书

使用openssl来创建一张服务端证书,证书名命名为server.crt。以下是openssl的相关命令:

$ openssl req \
    -new \
    -newkey rsa:4096 \
    -days 365 \
    -nodes \
    -x509 \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=Personal/CN=localhost" \
    -keyout server.key \
    -out server.crt

通过上面的命令,我们创建了服务端证书,证书对应的CNlocalhost。因此这张证书可以让nginx用来服务localhost这个域名。以下是执行命令的过程:

注意上面的命令一共生成了两个文件,一个是server.key,另一个是server.crt

其中server.key是私钥文件,server.crt是证书文件,这是一套。要注意私钥是必须要保存好不能泄露出去的,证书后续要配置进nginx服务器,用于出示给客户端,让客户端自己去验证服务端的证书的有效性(比如浏览器会用默认的CA机构列表去验证服务端的证书是不是有效机构签名的)。

创建好服务端证书以后,我们可以看一下证书内容:

可以看到服务端证书的文件内容就是base64加密的字符串。接下来可以使用openssl的命令解析证书的内容:

$ openssl x509 -noout -text -in server.crt

上面的命令会打印出来证书的具体内容。命令里面几个options的含义如下:

x509

表明证书是x509格式的。注意「格式」和「编码」是两回事。格式规定了证书里面所包含的「章节段落」和内容,而编码则是证书的内容保存格式,并且编码分为好几层。关于数字证书的「格式」与「编码」标准,不是本文重点,因此不展开论述。

-noout

参考这篇文章:

里面对noout选项的说明如下:

The -noout switch omits the output of the encoded version of the private key.

最后两个-text-in,一个是让openssl把读取证书的内容输出到屏幕上,然后-in选项指定要读区的证书文件。

接下来就是查看上面的openssl命令输出的具体内容:

可以看到上面的证书当中包含几个段落的内容。重点看下两部分的内容:

Subject: C = CN, ST = Beijing, L = Beijing, O = Personal, CN = localhost

「Subject」是证书的主题内容,也就是证书的机构信息等等。可以看到CNlocalhost。接下来是这部分内容:

Issuer: C = CN, ST = Beijing, L = Beijing, O = Personal, CN = localhost

「Issuer」是证书的签名机构,可以看到这张证书默认的签名机构就是它自己,所以这是一张「自签名」的证书。

如果我们要让服务端证书被所有的客户端(比如浏览器)默认就信任,那么就要拿这张数字证书去权威机构进行「数字签名」,这样issuer就会变成权威机构。而权威机构的数字证书列表都在各种客户端的默认信任机构列表里,比如chrome浏览器在macOS的环境下默认使用操作系统的机构证书列表:

这些都是默认的权威机构,可以看到这些证书叫做「系统根证书」:

「根证书」也可以叫叫「CA证书」、「机构证书」。我们自己的证书被这些机构签名以后,默认就会被主流的浏览器,工具(比如openssl)信任。因为它们都会维护一个默认的权威机构证书列表。

那么我们在demo场景下,就使用服务端自签名证书就可以了。然后在客户端访问服务端的时候,使用服务端证书本身作为权威机构证书(CA)就可以了。自签名证书都是自己即自己的issuer,所以权威机构的证书要么是由上级权威机构签名,要么是自签名,取决于机构所在级别。

我们自签名的证书因为不在这样的一个签名的信任链条里,所以默认客户端是不会信任的。所以上网的时候会经常看到弹出一个网站的「证书不可靠」这样的警告。

本系列文章的后续篇章会介绍如何让curl发起请求的时候,使用「服务端证书」作为客户端的CA机构证书,去验证服务端证书。因为服务端证书是「自签名」的证书,所以自己验证自己就可以了。

接下来可以看一下生成的公钥文件server.key的内容:

可以看到这里包含的是给证书加密的密钥,也是base64编码的。这个密钥文件一定要保存好不要泄露。一旦私钥文件泄露,那么就等于私钥加密的证书的身份就不能保证了,谁都可以用这个私钥文件伪造一份对应的证书。

我们可以用openssl命令来查看私钥的内容:

$ openssl pkey -in server.key -text

下面是打印出来的私钥的解码后内容:

注意私钥的这些参数如果泄露,那么私钥就泄露了。

关于服务端证书,要说的就这么多。下一篇文章讲解生成「CA证书」和「客户端证书」的方法,并且使用我们自己生成的「CA证书」给「客户端证书」签名。

My Github Page: https://github.com/liweinan

Powered by Jekyll and Theme by solid

If you have any question want to ask or find bugs regarding with my blog posts, please report it here:
https://github.com/liweinan/liweinan.github.io/issues