为开发人员简单解释 SSL 客户端证书

信息安全 tls 验证 证书
2021-08-14 13:31:20

我一直在考虑为我的 Web 应用程序使用客户端证书,非常希望有安全意识的用户将他们的私钥放在 HSM 上,这样即使机器被盗,他们也不会被盗,以及完全忘记的额外好处登录页面也很好(只要提供客户端证书,用户就会从第一个请求登录)。

然而,从我读过的内容来看,实现起来似乎很复杂,我完全迷失了(我很羞于问这样一个新手问题)。

我真的应该自己操作 PKI 并颁发证书吗?如果每个站点都这样做,用户将拥有一个充满不同证书的整个文件夹,这在可用性方面相当于 a passwords.txt即使每个人(即使用客户端证书的稀有网站)都这样做,如果可能的话,我想避免在该目录中添加另一个证书,并让用户重用他们已经拥有的证书(如果有的话)。

有没有办法让它们的行为就像 SSH 密钥一样,用户在注册期间提供任何密钥并且该密钥绑定到帐户?

关于在我的应用程序中验证它们,我发现的大多数文档都使 Web 服务器根据 CA(在这种情况下是我自己的 CA,这使我们回到 PKI 问题)检查证书,并在证书受信任时设置环境变量...这在我的情况下不起作用,因为我想摆脱 CA 并让客户提供他们自己的证书,所以基于我不能依赖于检查它们与 CA 的事实,什么我可以检查它们吗?客户端证书是否具有相当于我可以存储在我的数据库中并检查的 SSH 公钥?

最后,新客户将如何注册我的网站;他被要求出示证书,但他没有,他如何生成证书?

4个回答

编辑:我意识到这可能从下面的答案中不清楚......但从您的应用程序的角度来看,无论您自己运行 PKI/CA 还是使用一个或多个,都没有任何区别第三方 CA。即使您选择运行自己的 PKI,您也真的不想自己编写代码 - 因此您会使用现有的其中一个,它在逻辑上与应用程序是分开的,并且与 CA 的任何交互都将通过通常的协议。编辑结束

我真的应该自己操作 PKI 并颁发证书吗?

作为一般规则,除非您已经知道如何运行 PKI,否则您不应该这样做。它比你想象的复杂得多,而且事情可能出错的方式也更多。即使是以 PKI 为核心业务的公司有时也会出错;参见Diginotar,他们的证书基础设施遭到黑客攻击并最终破产

允许第三方证书,尤其是多个 CA 的证书,有其自身的缺陷。我有一张智能卡,其中包含我用来访问我的银行和几个政府网站的电子 ID。但我可能还有一个“软”证书,用于访问其他内容。如果您的站点接受这两个证书颁发机构,您是否有办法知道这两个证书指的是同一个人(或用户)?希望每个证书拥有一个用户,还是希望一个用户能够使用多个证书?证书过期时会发生什么 - 你怎么知道我的新证书仍然指向我?在设计应用程序和信任链时,需要仔细考虑这些问题。

有没有办法让它们的行为就像 SSH 密钥一样,用户在注册期间提供任何密钥并且该密钥绑定到帐户?

这只是编程的一个小问题......(换句话说,不是那么小,但并非不可能。)您可能还需要一些方法让用户也可以添加/删除证书。

关于在我的应用程序中验证它们,我发现的大多数文档都使 Web 服务器根据 CA(在这种情况下是我自己的 CA,这使我们回到 PKI 问题)检查证书,并在证书受信任时设置环境变量...这在我的情况下不起作用,因为我想摆脱 CA 并让客户提供他们自己的证书,所以基于我不能依赖于检查它们与 CA 的事实,什么我可以检查它们吗?客户端证书是否具有相当于我可以存储在我的数据库中并检查的 SSH 公钥?

您不会保存整个证书,您只需保存足够的信息,以便下次用户出示证书时可以验证该证书。这通常是证书序列号、CN 和颁发 CA。您可能还想存储到期日期,以便提醒用户在证书到期之前更新他们的证书。(这当然可以在您在登录时检查他们的证书时完成,但存储数据可能是明智的,这样您就可以通过电子邮件发送提醒,以防他们在收到警告期间没有登录。)

即使证书是由第三方 CA 颁发的,证书也会包含有关如何验证其有效性的信息。这通常是通过 OCSP(在线证书状态协议)进行的,它是对颁发 CA 的数据库的实时检查。还有 CRL,一个证书撤销列表,其中包含 CA 撤销哪些证书的信息。这不是实时的;CRL 将每隔一段时间重新发布一次。

最后,新客户将如何注册我的网站;他被要求出示证书,但他没有,他如何生成证书?

如果您选择使用第三方 CA,则应向他们提供指向您信任的一个或多个 CA 的链接。

如果您运行自己的 CA,您将向他们提供指向该 CA 的链接,该链接必须配置为允许(以前)匿名用户以及现有用户请求新证书。

最后,如果您想了解如何设置 PKI,可以尝试EJBCA,一种开源 CA/VA它将使您对所涉及的复杂性有一个基本的了解。

我在一家渗透测试公司工作,该公司需要客户证书才能登录我们的任何测试主机。证书确实要求您在进行身份验证时输入密码。这样做是为了增加一层安全性,而不是取代对密码的需求。如果证书不需要密码短语,那么是的 - 让某人持有密钥与向他们提供您的凭据一样糟糕。

目标和方法都相当值得怀疑。

用户的 PC 中没有 HSM(除非你们都在一家非常特殊的公司工作,该公司以某种方式为其员工提供加密硬件)。充其量,您会遇到使用智能卡的用户,但即便如此,他们也可能不会将智能卡用于您的站点,因为它太麻烦了。一个更现实的假设是,用户只需将私钥保存在他们的 HDD 上,要么使用弱密码,要么根本没有密码。因此,如果 PC 受到威胁,密钥就会受到威胁。这并不意味着公钥身份验证没有用,但您的假设似乎过于乐观。

客户端证书也不会消除对登录机制的需求。浏览器会要求用户选择一个证书并输入密码,这与标准的登录表单并没有什么不同(只是更丑)。同时,您的用户现在不得不担心备份他们的密钥和证书,他们可能必须找到一种方法将它们安全地携带到另一台机器上,并且如果密钥丢失或泄露,他们需要获取新证书. 所以这实际上是更多的工作。

我也不同意你的做法。HTTPS 的公钥加密基于一个非常具体的信任模型,即具有分层 CA 的 X.509 基础架构。您可能更喜欢不同的模型,但这就是协议的工作方式,也是所有相关服务器和客户端实现它的方式。试图“破解”证书验证可能会以灾难告终(如之前的一些答案所示)。所以,不,没有简单的出路。

如果您希望客户端证书既超级安全又超级方便,您会失望的。他们不是。虽然它们可能比密码更安全,但这是有代价的:为您做更多的工作,为您的用户做更多的工作,以及为您的应用程序带来更多的复杂性。

自签名证书将有效地用作 SSH 公钥。您必须将每个用户证书添加到您的受信任 CA 列表中。如果用户还没有证书,您可以在注册期间使用浏览器中的 java 脚本创建它。您可以要求用户存储使用强密码加密的私钥证书,因此它与纯文本 password.txt 不完全相同。私有证书将被加密和存储,只能使用密码解锁。当网站/webapp 想要进行身份验证时,您将查找(或让用户选择适当的私有证书,这是一个可用性问题)相应的证书,并且将提示用户输入要使用的私有证书的密码.