检查自签名证书的指纹是否会提高安全性?

信息安全 tls 哈希 证书 公钥基础设施
2021-09-03 17:45:07

我目前正在为与局域网内的设备进行 TCP 通信的应用程序开发一个组件。我使用 TLS 来提供数据加密、集成和授权。但是,我必须使用在 5 年或更长时间内不会过期的自签名证书。

由于使用自签名证书会将我的应用程序暴露给中间人攻击,因此我正在考虑将证书的指纹硬编码到我的应用程序中。当设备发送我的证书时,我会将它的证书指纹与硬编码指纹进行比较。

现在,这是否提高了我的应用程序的安全性?攻击者是否可以生成具有相同指纹的自己的自签名证书?我还计划使用我将在 TLS 握手期间发送到设备的客户端证书。该设备必须检查我的证书的指纹。

这个解决方案有效吗?

提前感谢您的回答!

3个回答

SSL/TLS 中,客户端使用服务器的公钥。由于通常客户端事先不知道服务器的公钥,它希望通过公钥基础设施的魔力获得它:服务器的公钥将在证书中提供,客户端将能够验证:

  • 证书内容是真实的(即验证:签名和名称以及证书扩展名是正确的并链接到受信任的根);
  • 证书归预期的服务器所有(预期的服务器名称出现在Subject Alt Name证书扩展名中,如果没有 SAN 扩展名,则出现在其公用名中)。

现在,如果客户端已经知道公钥,那么所有这些都是不必要的复杂化;如果该密钥是先验已知的,则客户端可以直接使用它而忽略服务器发送的证书。

为了与协议的正式规范兼容,并且为了更容易地重用现有的库和实现,按照您的建议进行操作可能会更简单,即验证服务器的证书是位到位的预期证书,并让代码从中提取公钥。如果“指纹”是用抗第二原像(例如 SHA-1)的散列函数计算的,则可以用于该检查。这可以。


就您而言,我了解服务器是设备,客户端是您的应用程序。只要攻击者没有破坏设备的私钥,即从设备中提取它,您的应用程序就不会被愚弄(与假设备对话)。如果您有多个设备,那么每个设备都应该有自己的私钥/公钥对。如果所有设备都具有相同的密钥对,那么私钥就不能被认为是“私人的”:超过两三个人知道的秘密不是秘密,而是谣言。

然后,“安全”的方法是在受控条件下进行某种初始化阶段,在该阶段,应用程序实例学习其随后将连接到的设备的指纹(也许应用程序生成公钥/私钥对和自签名证书,并将其导入设备)。

这是SSH中使用的安全模型:从客户端到给定服务器的第一个连接需要明确的确认(客户端显示服务器的公钥指纹,并且人类用户应该通过例如打电话给服务器来验证它系统管理员);之后,客户端信任该公钥,因为它记住了指纹。


“记住密钥”模型运行良好,但您必须意识到它丧失了被称为撤销的 PKI 功能:一种用于传送损坏遏制信息的带外自动机制。如果其中一个设备的私钥被泄露,那么窃贼随后可以运行假设备并欺骗您的应用程序连接到它;为了避免这种情况持续存在,必须以某种方式警告应用程序必须不再接受给定的证书指纹。具有定期发布的 CRL 或 OCSP 响应的吊销检查是一种自动执行此操作的方法。当您记住指纹时,没有 PKI,因此没有 CRL。但需求可能仍然存在。

如果您遵循没有 PKI 的道路,并且嵌入了证书指纹,那么您必须决定是否需要一些东西来确保 CRL 正常完成工作。

你在这里所做的听起来有点类似于证书固定在某些情况下,这实际上可以提供比使用 CA 颁发的证书更好的安全性(因为您不必信任 CA)

缺点是它使证书管理(例如撤销、重新颁发)成为一个手动过程,这可能是一个真正的问题,具体取决于您的用例。

是的,这实际上与信任用于自签名证书的根证书相同。证书的验证过程是获取指纹并验证您从受信任的 CA 获得的签名是否与指纹匹配。直接验证指纹是等效的操作。