Public-Key-Pins配置后浏览器报错,哪里出问题了?

Tr° 洋泽 阅读 30

我在本地测试环境配置了Public-Key-Pins头,但访问页面时Chrome直接显示证书错误,页面完全无法加载。之前已经按文档生成了证书的指纹,备用密钥也配置了,但还是报错:


Public-Key-Pins: pin-sha256="a1b2c3d4..."; pin-sha256="e5f6g7h8..."; max-age=86400; includeSubdomains; report-uri=/hpkp-report

尝试过清除浏览器缓存、重启服务,甚至换其他浏览器测试,依然提示“Public Key Pinning Error – No certificates matched”。测试环境用的是自签名证书,会不会是因为证书问题导致HPKP生效反而更严格了?

我来解答 赞 9 收藏
二维码
手机扫码查看
2 条解答
程序员梦鑫
这个问题确实很典型,尤其是在测试环境里用自签名证书时。具体来说,HPKP(HTTP Public Key Pinning)是一个非常严格的机制,它会强制浏览器只接受你指定的公钥指纹,如果匹配不上,页面直接被阻断。你遇到的问题大概率是因为以下几个原因导致的。

首先,自签名证书本身的问题。HPKP要求你配置的公钥指纹必须与当前服务器证书链中的某个公钥完全匹配。如果你用的是自签名证书,而这个证书的公钥没有被正确提取并配置到 pin-sha256 中,那么浏览器自然会报错说“No certificates matched”。所以第一步,你需要确认你的证书生成和指纹提取是否正确。

这里我给你一个完整的步骤来验证和解决这个问题:

第一步,重新提取你的证书公钥指纹。假设你的证书文件是 server.crt,你可以用以下命令提取它的公钥指纹:

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

这个命令会输出一个Base64编码的SHA-256指纹,把它替换到你的 pin-sha256 配置中。

第二步,检查备用密钥的指纹。根据HPKP规范,你必须至少配置两个 pin-sha256,其中一个可以是当前证书的公钥指纹,另一个必须是备用密钥的指纹。备用密钥的作用是防止主密钥泄露或丢失后无法恢复。如果你没有备用密钥,可以用以下命令生成一个新的RSA密钥对,并提取其公钥指纹:

# 生成新的RSA密钥对
openssl genrsa -out backup.key 2048
# 提取公钥
openssl rsa -in backup.key -pubout -outform der | openssl dgst -sha256 -binary | openssl enc -base64

把生成的备用密钥指纹也加到你的 Public-Key-Pins 配置中。

第三步,调整 max-age 的值。在测试环境中,建议把 max-age 设置为一个很小的值,比如60秒。这是因为 max-age 定义了浏览器缓存HPKP策略的时间,如果设置得太大,一旦配置错误,会导致很长一段时间内页面无法访问。

Public-Key-Pins: pin-sha256="正确的主密钥指纹"; pin-sha256="正确的备用密钥指纹"; max-age=60; includeSubdomains; report-uri=/hpkp-report


第四步,验证配置是否生效。清除浏览器缓存后,用Chrome开发者工具查看响应头,确保 Public-Key-Pins 头已经正确返回。然后尝试重新加载页面,看看是否还会报错。

最后再补充一点,HPKP其实已经被很多浏览器厂商废弃了,比如Chrome从2017年开始就不再支持HPKP。如果你只是为了学习或者测试,那没问题,但如果是生产环境,强烈建议不要使用HPKP,因为一旦配置错误,后果非常严重,可能会导致整个站点不可用。现在更推荐使用CAA记录或者基于证书透明度(Certificate Transparency)的机制来增强安全性。

总之,按照上面的步骤一步步排查,应该能解决问题。如果还是不行,可以再检查一下证书链是否完整,尤其是根证书和中间证书的部分,有时候问题也可能出在这里。
点赞 2
2026-02-16 12:05
司马俊衡
测试环境用自签名证书配HPKP会直接跪,因为浏览器根本不会信任你的土造证书,删掉HPKP头先用HTTPS跑起来再说。等正式环境上CA签发的证书再搞HPKP,而且记得开report-only模式观察上报。

如果非要用HPKP,改成这样:

Public-Key-Pins-Report-Only: pin-sha256="a1b2c3d4..."; pin-sha256="e5f6g7h8..."; max-age=86400; includeSubdomains; report-uri=/hpkp-report

这个头只会报错不阻断,能让你看到具体哪个证书链对不上。
点赞 8
2026-02-05 21:04