忙于采集的蜜蜂,无暇在人前高谈阔论 [登录·注册]

吕滔博客

首页 开发 运维 工具 摄影

Public-Key-Pins:配置 HPKP(Public Key Pinning Extension for HTTP)

工具 memory 发布于December 18, 2016 标签: Nginx

HPKP 格式及说明

HTTP Public Key Pinning(HPKP)的格式如下:

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 均为可选。
为了验证合法性,pin-sha256 必须由网站当前证书链中的证书生成。例如我的网站证书有三级,用根证书、中间证书、站点证书中的任何一个生成指纹都可以。用站点证书生成指纹的好处是安全性最高,缺点是证书重签之后指纹就变了,如果之前没提供备用指纹,老用户无法访问;用根证书生成指纹安全性最差,因为每个根证书都对应很多中间证书,攻击者只要攻破其中一个,就可以签出能被 HPKP 策略信任的站点证书。
综合考虑安全性和易用性,一般推荐使用中间证书生成指纹;用知名 CA 的根证书也可以;不推荐使用站点证书,除非充分了解后果并且指定了有效的备用指纹。
备用指纹是为那些必须更换中间或者根证书的场景准备的 —— 例如原来的 CA 突然倒闭或者被黑了。本站当前使用的证书由 RapidSSL SHA256 CA – G4 签发,我的pin-sha256 包含了它的指纹;同时我还用 Let’s Encrypt Authority X1 这个中间证书生成了备用指纹。这样如果后续本站改为使用 Let’s Encrypt Authority X1 签发的证书,老用户也不会受影响。

生成 pin-sha256

从已知的密钥对(*.key)生成:

openssl rsa -in lvtao.net_ssl.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

从已知的证书申请文件(*.csr)生成:

openssl req -in lvtao.net.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

从已知的证书(*.crt)生成:

openssl x509 -in lvtao.net_bundle.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

nginx配置:

add_header Public-Key-Pins 'pin-sha256="第一个base64"; pin-sha256="备用base64"; max-age=时长; includeSubDomains';

Public-Key-Pins:
  pin-sha256="GRAH5Ex+kB4cCQi5gMU82urf+6kEgbVtzfCSkw55AGk=";
  pin-sha256="lERGk61FITjzyKHcJ89xpc6aDwtRkOPAU0jdnUqzW2s=";
  max-age=15768000; includeSubDomains

一般来说,应至少提供两个 fingerprint(其中一个留做备用),而 max-age 应该尽量地长。

相关推荐

添加新评论

网站状态

  • 栏目分类:49个
  • 发布文章:1512篇
  • 用户评论:729条
  • 开博至今:4069天

正则速查

[abc] 匹配中括号中的单个字符,如a或b或c
[^abc] 匹配除了a、b、c等字符的其他单个字符
[a-z] 匹配一个字符范围,如a到z
[a-zA-Z] 匹配一个字符范围,如a-z 或 A-Z
^ 匹配行的开始
$ 匹配行的结束
\A 匹配一个字符串的开始
\z 匹配一个字符串的结束
. 匹配任意单个字符
\s 匹配空白字符,如空格,TAB
\S 匹配非空白字符
\d 匹配一个数字
\D 匹配非数字
\w 匹配一个字母
\W 匹配非字母
\b 匹配字符边界
(...) 引用所有括号中的内容
(a|b) a或者b
a? 零个或1个a
a* 零个或多个a
a+ 1个或多个a
a{3} 3次重复的a
a{3,} 3次或3次以上重复的a
a{3,6} 3到6次重复的a

修正符

/g 查找所有可能的匹配
/i 不区分大小写
/m 多行匹配
/s 单行匹配
/x 忽略空白模式
/e 可执行模式,PHP专有
/A 强制从目标字符串开头匹配
/D 使用$限制结尾字符,则不允许结尾有换行
/U 只匹配最近的一个字符串;不重复匹配

最新回复

  • 夏目贵志: 我终于懂了是什么意思了!!!
  • 柳溪: 支持博主 很详细!
  • memory: 谢谢。以前没用到checkEmail,是注释掉的,所以这儿我也没...
  • 一个默默无闻的码农: function checkEmail的if里的变量写错了
  • memory: 谢谢大神鼓励。哈哈 有没想到的地方还望多多指正
  • 梦康: 感谢分享,前几天我刚接触这个命令,之前都没用到过。总结非常全面。
  • 梁兴健: Parse error: syntax error, unexp...
  • 耐火砖: 感谢博主分享,很有用
  • memory: 额。。。
  • 亚克力浴缸: 还好我不是学这些的,不然打错那个都不知道
  • memory: 哈哈。写的太2了,将就着吧。我自己看也晕了...
  • 亚克力浴缸: 看晕了,头大
  • 泽泽: 至少手机上图根本没动
  • memory: 呵呵,难道你现在看到的不是gif图?
  • 泽泽: 原文是gif图,无脑抓取也要读一读吧
  • 亚克力浴缸: 学习了 in 参数
  • asd: 感谢博主,功能已实现