前言
继前文RSA(六) X.509 CA 证书 所述,X.509 CA 证书是由 CA 认证中心签名并颁发的;但是最后,作者留下了这么一个疑问,就是如果在企业内网,我同样需要对公钥进行认证,但是因为不需要连接外网,所以并不需要 CA 证书(因为,CA 证书毕竟开销不菲);那么是否有这样的一种可替代的方案,在不使用 CA 证书的前提下,能否保证公钥的合法性?答案是自签名证书
;
备注,本文是作者的原创作品,转载请注明出处。
定义
看下 wikipedia https://en.wikipedia.org/wiki/Self-signed_certificate 上的最重要的一段解释
In technical terms a self-signed certificate is one signed with its own private key.
自签名证书说穿了,就是一个由自己的私钥进行签名的证书;
与 CA 证书的区别
通过 RSA(六) X.509 CA 证书 章节我们知道,要保证公钥的合法性,我们需要把自己的公钥交给第三方 CA 机构,通过它的私钥来进行签名,并生成一张 CA 证书并颁发给用户;而与 CA 证书相对应的就是自签名证书,也就是说,我自己的公钥不交给第三方的 CA 机构进行签名,而是直接由自己的私钥进行签名,并生成一张自签名的证书;
如何生成
这里我主要讲解一下,如果通过 openssl 来生成自签名的证书,
1 | $ openssl req \ |
然后同样需要输入 CSR 相关的信息来申请;最后,会在本地目录中生成一个私钥 private.key 和一张自签名的证书 self-signed.crt;注意,自签名证书文件的后缀为 .crt;下面来看看各个参数的简要说明,
-x509
告诉 openssl 生成一张自签名的证书;-nodes
告诉 openssl 在生成私钥的时候忽略密码
参考
How To Create a Self-Signed SSL Certificate for Apache in Ubuntu 16.04
OpenSSL Essentials: Working with SSL Certificates, Private Keys and CSRs
内部结构
我们来查看一下刚才通过 openssl 生成的自签名证书 self-signed.crt 的内部结构;
1 | $ openssl x509 -text -noout -in domain.crt |
内容如下,
1 | Certificate: |
备注,要参看其它证书类型的内容,参考 https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs#view-certificates
一些特性,
首先,我们可以看到不像 CA 证书那样有多层证书结构,自签名证书只有一层证书结构;也就是没有 Certificate Chain 的概念;
再次,可以看到 Issuer 发布者和证书拥有者 Subject 是相同的,都是 C=CN, ST=ChengDu, L=ChengDu, O=HRX, OU=HRX, CN=HRX/emailAddress=comedshang@163.com,表明证书的签名方和证书自己是同一个机构(或者角色),这也就是
自签名
命名的由来;
关键内容,
Subject Public Key Info
这段内容就是公钥的内容了;Signature Algorithm: sha1WithRSAEncryption
这段内容就表示对公钥和身份信息一起的签名信息了,可以看到,采用的是 SHA1 算法;
最后,比较重要的是,因为该证书只有一层,所以,自签名证书在通讯过程中扮演的也就是 Root Certificate,通常是需要被加载如客户端的 trust store 中;
如何保证内网通讯的安全性
比如内网中,Alice 想和 Bob 保持可靠的加密通讯;
首先,Alice 需要生成秘钥 Kp 以及自签名证书 Cself
然后,Bob 通过某种方式将 Alice 的 Cself 加入自己的 trust store 中;
注意,如果 Bob 是通过浏览器访问的 Alice 站点,那么浏览器会提示,是否相信该证书,如果选择相信,这个时候,浏览器会自动将该 Cself 证书加入自己的 trust store 中;之后,某个时刻,Bob 向 Alice 发起安全通讯的会话,双方握手过程中,
- Alice 将 C′self (X.509 自签名)证书发送给 Bob
- Bob 通过 trust store 中之前预加载的 Cself 中所指明的签名算法对 C′self 进行签名,得到签名 S′
- 最后 Bob 使用 trust store 中 Cself 的签名 S 与 S′ 进行比较,
- 若相等,则表示 Alice 当前发送过来的证书是可靠的,也就是说,其身份信息和公钥是合法的,没有被伪造过;
- 若不等,则表示 Alice 当前发送过来的证书是不可靠的,其身份信息或者是公钥是被篡改过的;应当立即停止与 Alice 的通讯;这种情况下,往往会提示握手失败,证书不可靠;
但切记,在公网中使用自签名证书的 SSL 加密通讯的方式是不可靠的,其根本原因是,因为没有公钥基础设施的支持,其自签名证书很容易被伪造;这部分内容在之前的 RSA(五) PKI (Public Key Infrastructure) 公钥基础设施 等系列文章中有过详细的阐述,有兴趣的读者可以从这里开始;
如何加入 trust store
参考如下的几篇文章,
openssl with Apache:
How To Create a Self-Signed SSL Certificate for Apache in Ubuntu 16.04
How to create a self-signed SSL Certificate for Apache
java keytool series:
Tomcat SSL Installation Instructions
: https://www.sslshopper.com/tomcat-ssl-installation-instructions.html
java keytool - Key and Certificate Management Tool: http://docs.oracle.com/javase/1.5.0/docs/tooldocs/solaris/keytool.html
Import a private key into a Java Key Store: http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art049
TODO
给一些详细的用例;比如 Java、Tomcat 是如何使用自签名证书进行通讯的?
References
OpenSSL Essentials: Working with SSL Certificates, Private Keys and CSRs: https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs