本站启用HPKP

这算是我第一次个人明确指定我的证书商了吧。虽然 Comodo, StartSSL, Wosign 甚至 AlphaSSL 我都用过。

但是,个人在CNNIC签发的中级根被MCS滥用后,也觉得有必要注意证书避免被滥发的问题。

通过Jerry Qu 这篇文章,我认识了HPKP。

HTTP Public Key Pinning(HPKP),也是用来防范由「伪造或不正当手段获得网站证书」造成的中间人攻击,但有着与 CT 不同的思路。

—— 引用自 imququ 这篇文章

通过HPKP(HTTP Public Key Pining),我指定了根证书。

当不是指定证书签发的证书,在现代浏览器中,连接将会被阻断。

HPKP 官方文档见 RFC7469,目前 Firefox 35+ 和 Chrome 38+ 已经支持。

它的基本格式如下:

Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubdomains][; report-uri="reportURI"]

各字段含义如下:

pin-sha256 即证书指纹,允许出现多次(实际上最少应该指定两个);
max-age 和 includeSubdomains 分别是过期时间和是否包含子域,它们在 HSTS(HTTP Strict Transport Security)中也有,格式和含义一致;

report-uri 用来指定验证失败时的上报地址,格式和含义跟 CSP(Content Security Policy)中的同名字段一致;

includeSubdomains 和 report-uri 两个参数均为可选;

综合考虑安全性和易用性,一般推荐使用中间证书生成指纹;用知名 CA 的根证书也可以;不推荐使用站点证书,除非充分了解后果并且指定了有效的备用指纹。

建议至少要指定两个以上指纹!

因此,我指定了两个中间根证书,而不是SSL证书,这样子我可以用的证书范围不会太窄。

下面是我指定的列表:

  • COMODO ECC Certification Authority

Pin SHA256: 58qRu/uxh4gFezqAcERupSkRYBlBAvfcw7mEjGPLnNU=

[目的是兼容现有证书,可用于本站本身证书和CloudFlare的证书]

  • StartCom Certification Authority

Pin SHA256: 5C8kvU039KouVrl52D0eZSGf4Onjo4Khs8tmyTlV3nU=

[目的是保证备用证书可以随时启用,可用于本站备用的StartSSL证书和Wosign证书]

于是,增加HTTP报头如下(如果你增加meta的头部标签,也是可以的):

Public-Key-Pins: pin-sha256="58qRu/uxh4gFezqAcERupSkRYBlBAvfcw7mEjGPLnNU="; pin-sha256="5C8kvU039KouVrl52D0eZSGf4Onjo4Khs8tmyTlV3nU="; max-age=2592000; includeSubDomains

解释:上面的 pin-sha256,是把两个证书通过计算证书的公钥Public Key,再计算SHA-256指纹得到结果。

openssl x509 -in intermediate.pem -noout -pubkey | openssl asn1parse -noout -inform pem -out public.key

openssl dgst -sha256 -binary public.key | openssl enc -base64

你要是偷懒的话,就去SSL Labs查一下你的网站的证书的Pin SHA-256。

试用总结

本站启用HPKP以来,遇到了一些问题。

1.加入HPKP报头的证书应当尽量是中间证书
我们来看以下这个实例报头(来自我的网站):

Public-Key-Pins: pin-sha256="lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU="; pin-sha256="5C8kvU039KouVrl52D0eZSGf4Onjo4Khs8tmyTlV3nU="; pin-sha256="1qGEQ9NI25lPk0zNjmNdgzonrB5W+K+vfJfLT0Pqtos="; max-age=2592000; includeSubDomains

经过查询,是三个根证书:Addtrust, Startcom, Wosign。这么固定三个根证书有什么问题吗?有!
有些系统,预置了一些中级根;而这些中级根和根证书是交叉签名关系!也就是说,中级根作为根证书,其本身也可以独立存在。而服务器证书由中级根签发,浏览器在检查证书时,可能在检索到中级根时,就不会继续向上级根检索,从而直接出错阻断。

2.max-age 别太长
最近我的网站就出现了固定了 Addtrust Root 结果从Comodo ECC换成Comodo RSA就出错了。 各位可以刷新缓存试试。对于经常换证书的网站,三天的max-age足矣。