delphij's Chaos

选择chaos这个词是因为~~实在很难找到一个更合适的词来形容这儿了……

15 Jul 2010

如何:申请用于服务器SSL/TLS的X.509证书

2015-03-05更新:本文中部分干货已过时,本文本身也不再更新。请参阅 这张作弊条

SSL/TLS协议中,服务器证书是用于向客户端证明服务器身份的凭据,同时它还向用户提供了服务器的公钥,而服务器公钥则可以用来建立客户端到服务器的安全通讯(具体的通讯流程要比这个复杂,纯从技术而言,服务器的公钥主要用于与客户端进行会话密钥的协商)。

服务器的公钥只能确保拥有私钥的服务器(或人)能够解密信息,但它本身并不能确认服务器的身份。在实践中有很多种不同的方法来确保公钥确实来自受信任的服务器,在通常的SSL/TLS协商过程中,采用的方法是根据证书链来逐层验证公钥是否是有效的及其身份。简单地说,就是以安全的方法(例如安装光盘,或互相认证的签名等)事先将证书链上的某一个或某几个证书发给客户端,以便其验证最终用于服务器的安全证书。关于这一流程的具体细节,已经有很多文章进行了介绍,在此不再赘述。

如此,我们在实现采用SSL/TLS的服务器的时候,需要为证书准备的事项包括:

  • 找到一家被客户端信任的、具备签发证书资质的发证机构。发证机构可以是根CA(对于浏览器来说,通常可以在安全选项中找到类似"查看证书"之类的选项),也可以是这些根CA认可的二级发证机构。
  • 收集用于验证服务器身份的信息,例如服务器的FQDN,等
  • 生成一对用于SSL/TLS的公钥/私钥。

有了这些信息,就可以制作证书申请(CSR)供发证机构去签名了。一般来说,发证机构需要首先验证申请人的身份信息,然后对CSR提交的信息进行核对和签名,并将签名之后的证书发给申请者,或供其下载。下面以 FreeBSD、OpenSSL 为例介绍从生成公钥/私钥对到签发、安装证书的全过程。

第一步是生成公钥/私钥对。

对于多数的应用来说,2048位的RSA完全能够满足目前 (2010 年 7 月) 对于安全方面的需要。为了方便起见,我们把所有的相关文件均命名为 主机名.*,其中 key 为公钥和私钥对, csr 为证书申请, cer 为服务器证书(由CA签发),pem为合并了证书链上中间节点的证书集。假设主机名为 www.example.com,采用 RSA 算法,生成2048位的公钥/私钥对的命令为:

openssl genrsa -out www.example.com.key 2048  
chmod  400 www.example.com.key

生成好公钥/私钥对之后,应将这个文件复制一份到安全的地方保存。

第二步是生成证书请求(CSR)。

openssl req -new -sha1 -nodes -key www.example.com.key -out www.example.com.csr

注意:我们在第一步生成公私钥对的时候并没有指定OpenSSL对其进行加密(如果加密,则每次启动服务器时均需要输入密码,因此对这个文件应采用正确的权限保护,而不是密码保护,因为内存中持有私钥的进程中的私钥仍是明文,而入侵者搞定持有私钥的进程和搞定root权限的代价通常是非常接近的)。所以在此处要指明-nodes。sha1是CSR中采用的hash算法。

req命令会询问一些问题(注意,有些发证机构,例如 StartSSL 的免费证书发证机构会忽略全部的这些信息,因此对于这些发证机构,如何回答这些问题对最终结果没有影响,故可使用默认值):

Country Name (2 letter code) 国家代码(ISO 639-1)。对于中国应为CN。

State or Province Name (full name) 州或省名。

Locality Name (eg, city) 所在城市的名字。

Organization Name (eg, company) 实体的名字,例如公司名称。

Organizational Unit Name 部门名字。

Common Name 重要 服务器的 FQDN。

Email Address 用于联络的电子邮件地址。

A challenge password 并不是所有的发证机构都支持,并且我个人认为设置它不是一个很好的主意。

An optional company name 不需要填写。我用过的CA包括Verisign等等都是通过其他方法去设置。

之后我们会得到一个 www.example.com.csr 文件。使用下面的命令可以查看其内容:

openssl req -in www.example.com.csr -text

注意确认其中CN=www.example.com。

之后,把这个csr文件发给发证机构签署就可以了。

多数发证机构会使用中间发证机构(Intermediate Certificate Authority)来签署证书。有时,用户客户端可能并没有安装这些中级发证机构的证书,在得到签署好的证书文件之后,将中间发证机构的证书追加到证书文件后面,客户端在访问的时候就可以由根CA沿着中间发证机构来验证证书链了。