【问题标题】:JWT RS256: Is it safe to fetch public key over https?JWT RS256:通过 https 获取公钥是否安全?
【发布时间】:2017-01-21 03:55:55
【问题描述】:

我正在使用 RS256 算法签署 JWT。为了在客户端验证这些令牌,我需要访问公钥。

当我设置返回包含公钥的证书的不受保护的 API 路由 ('/api/certificate') 时,是否存在安全问题(欺骗、...)。我是否需要采取任何额外的安全措施?

【问题讨论】:

    标签: security https rsa jwt public-key


    【解决方案1】:

    几个概念经常混淆,也许不适合你,但让我试着在这个答案中解释一些事情。

    非对称加密显然需要公钥和私钥,两者基本上都只是数字。私钥是保密的,公众是公开的,任何人都可以拥有它。签名时,您使用私钥进行签名,然后任何人都可以使用公钥验证签名是由拥有相应私钥的人(即您)进行的。

    但问题是您如何分发您的公钥,或者在您的 jwt 示例中,客户如何获取它。正如您在问题中正确指出的那样,仅仅通过不安全的通道下载公钥是不够的,因为攻击者可以用自己的公钥替换它,从而导致攻击者能够签署令牌。

    对此的一种解决方案可能是按照您的建议通过 https 获取它,这实际上意味着使用第二组公私密钥对(网络服务器的密钥)来确保发送第一组密钥的安全。顺便说一句,理论上的问题仍然是相同的,它只是在后台为您固有地解决了:浏览器如何知道它在连接时从服务器接收的公钥实际上属于服务器。他们之间还没有安全通道。

    输入证书。

    证书是本质上将公钥与其所有者联系在一起的文档,这正是您想要的。当浏览器连接到网站时,服务器会发送其公钥连同它的证书,以便浏览器可以验证公钥实际上属于发送它的服务器(在本例中为域名)。如何验证它超出了这篇文章的范围,关键是证书是由另一个公钥签名的,证书可能由另一个公钥签名等等,并且链被一个这样的列表终止您的操作系统/浏览器供应商已经为您的计算机和/或浏览器设置了称为可信根证书。

    您也应该以同样的方式使用证书验证公钥。您甚至不需要为此承担 SSL (https) 传输的负担,验证公钥是否属于特定主题是证书的主要用途。

    因此,您所要做的不仅仅是从 API 中获取公钥,而是将其连同其证书一起获取。您可能已经这样做了,很少使用裸公钥。您很可能已经从服务器接收到 pfx 或 cer 或 crt 或其他任何内容。根据您正在开发的技术堆栈,您肯定可以使用内置机制来完全验证证书并确保其有效。不过请不要实施您自己的验证,因为这是一项棘手的工作,而且很难做到正确。如果证书通过验证,您可以相信您从 API 收到的公钥是真实的并且属于它声称属于的任何内容。不过可能有一些注意事项(例如,确保除了基本验证之外,您还检查了证书中其他人无法拥有的字段组合)。

    作为一项额外的安全措施,您还可以实施 证书固定,通过在客户端中拥有有效证书的指纹列表(在浏览器客户端,但概念还是一样的)。

    编辑(证书通过一般性到期验证后检查哪些字段等):

    在一般情况下,这取决于谁签署了证书以及它是什么类型的证书。

    由真实证书颁发机构 (CA) 签署的服务器证书只能将服务器域作为其公用名 (CN) 字段,真实 CA 通常不会签署其他任何内容,他们也不会签署证书对于 yourdomain.com,除非您可以证明您控制 yourdomain.com。所以在这种情况下,在证书通过验证后检查 CN 可能就足够了。不过,您确实需要检查 CN,因为任何人都可以从 GlobalSign 或 Thawte 或其他受信任的 CA 那里获得有效证书,这只是要花钱。他们不能拥有 yourdomain.com 的证书。

    如果您签署自己的证书,您也不会为任何人签署任何内容,因此在这种情况下,检查颁发者(您已签署)和 CN(为谁)就足够了。如果证书以其他方式通过验证(意味着受信任的根证书对其进行签名)应该没问题,因为攻击者通常无法在您的计算机上获得他的 CA 证书作为受信任的。

    一般来说,您想要检查别人无法拥有的东西。如果您依赖真正的 CA,这会更容易,而且通常最好检查指纹。

    【讨论】:

    • 您的回答读起来很有趣。我将尝试在使用 https 的基础上添加证书验证。正如你所说,我最好不要实现自己的验证,解析证书并检查整个名称字符串是个好主意吗?
    • 我在答案中添加了我的想法。
    • 感谢您的时间和全面的回答。我会接受的!
    • 好吧,我认为这并不能回答问题。客户端(浏览器或应用程序)生成 JWT 并使用自己的公钥对其进行签名。此密钥不能与证书关联,因为它是我们正在谈论的客户端的密钥。您没有证书客户端,而是服务器,域名。因此,如果您生成令牌客户端,您仍然需要通过 HTTPS 将公钥发送到具有有效证书的服务器。
    • @noun 我没有关注对不起。为什么客户端会生成 jwt?为什么要用它的 public 密钥来签名呢?即使它出于某种原因这样做,为什么服务器不能验证客户端证书?
    猜你喜欢
    • 2018-10-16
    • 2019-02-12
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多