JWT RS256:通过 https 获取 public 密钥是否安全?
JWT RS256: Is it safe to fetch public key over https?
我正在使用 RS256 算法签署 JWT。为了在客户端验证这些令牌,我需要以某种方式访问 public 密钥。
当我设置未受保护的 API 路由('/api/certificate')时是否存在安全问题(欺骗,...)returns 包含 [=17] 的证书=] 键。我需要采取任何额外的安全措施吗?
几个概念经常混淆,也许不适合你,但让我试着在这个答案中解释一些事情。
非对称加密显然需要一个 public 和一个私钥,两者基本上都只是数字。私钥是保密的,public 就是 public,任何人都可以拥有它。签名时,您使用私钥进行签名,然后任何人都可以使用 public 密钥验证签名是由拥有相应私钥的人(即您)创建的。
但问题是您如何分发 public 密钥,或者在您的 jwt 示例中,客户如何获得它。正如您在问题中正确指出的那样,仅通过不安全的通道下载 public 密钥是不够的,因为攻击者可以用自己的密钥替换它,从而导致攻击者能够签署令牌。
一个解决方案是按照您的建议通过 https 获取它,这实际上意味着使用第二组 public-私钥对(网络服务器的密钥)来确保发送第一个私钥。理论上的问题仍然是相同的顺便说一句,它只是在后台为您固有地解决了:浏览器如何知道它在连接时从服务器接收到的 public 密钥实际上属于服务器。他们之间还没有安全通道。
输入证书。
证书本质上是将 public 密钥与其所有者相关联的文档,而这正是您想要的。 当浏览器连接到网站时,服务器将其 public 密钥 连同其证书 一起发送,以便浏览器可以验证 public 密钥确实属于服务器(此域名中的域名案例)发送它。如何验证它超出了这个 post 的范围,重点是证书是由另一个 public 密钥签名的,证书可以由另一个 public 密钥签名,等等., 并且链由您的 OS/browser 供应商已经为您的计算机 and/or 浏览器设置的所谓可信根证书列表终止。
您也应该以同样的方式使用证书验证 public 密钥。 您甚至不需要 SSL (https) 传输的负担, 验证 public 密钥属于特定主题是证书的主要目的。
因此,您所要做的不仅仅是从 API 中获取 public 密钥,而是获取它及其证书。您可能已经在这样做了,裸键 public 很少使用。您很可能已经从服务器接收到 pfx 或 cer 或 crt 或其他任何内容。根据您正在开发的技术堆栈,您肯定可以使用内置机制来完全验证证书并确保其有效。但请不要实施您自己的验证,因为这是一项棘手的工作,而且很难做到正确。如果证书通过验证,您可以相信从 API 收到的 public 密钥是真实的,并且属于它声称属于的任何对象。不过可能有一些注意事项(例如,确保除了基本验证之外,您还检查证书中其他人无法拥有的字段组合)。
作为一项额外的安全措施,您还可以实施证书固定,通过在客户端中包含有效证书的指纹列表,使其更安全地抵御某些类型的攻击(在浏览器客户端中较少,但概念仍然相同)。
编辑(在证书通过过期的一般验证后要检查哪些字段等):
一般情况下,这取决于谁签署了证书以及它是什么类型的证书。
由真正的证书颁发机构 (CA) 签署的服务器证书只能将服务器域作为其通用名称 (CN) 字段,真正的 CA 通常不会签署任何其他内容,他们也不会签署yourdomain.com 的证书,除非你能证明你控制 yourdomain.com。因此,在这种情况下,在证书通过验证后检查 CN 可能就足够了。不过,您确实需要检查 CN,因为任何人都可以拥有来自 GlobalSign 或 Thawte 或其他受信任的 CA 的有效证书,这只是要花钱。他们不能拥有的是 yourdomain.com.
的证书
如果您签署自己的证书,您也不会为任何人签署任何东西,因此在这种情况下,检查颁发者(您签署的)和 CN(为谁)就足够了。如果证书以其他方式通过验证(意味着受信任的根证书对其进行了签名)应该没问题,因为攻击者通常无法在您的计算机上获得他的 CA 证书。
总的来说就是你想查别人查不到的东西。如果您依赖真正的 CA,这会更容易,而且通常最好检查指纹。
我正在使用 RS256 算法签署 JWT。为了在客户端验证这些令牌,我需要以某种方式访问 public 密钥。
当我设置未受保护的 API 路由('/api/certificate')时是否存在安全问题(欺骗,...)returns 包含 [=17] 的证书=] 键。我需要采取任何额外的安全措施吗?
几个概念经常混淆,也许不适合你,但让我试着在这个答案中解释一些事情。
非对称加密显然需要一个 public 和一个私钥,两者基本上都只是数字。私钥是保密的,public 就是 public,任何人都可以拥有它。签名时,您使用私钥进行签名,然后任何人都可以使用 public 密钥验证签名是由拥有相应私钥的人(即您)创建的。
但问题是您如何分发 public 密钥,或者在您的 jwt 示例中,客户如何获得它。正如您在问题中正确指出的那样,仅通过不安全的通道下载 public 密钥是不够的,因为攻击者可以用自己的密钥替换它,从而导致攻击者能够签署令牌。
一个解决方案是按照您的建议通过 https 获取它,这实际上意味着使用第二组 public-私钥对(网络服务器的密钥)来确保发送第一个私钥。理论上的问题仍然是相同的顺便说一句,它只是在后台为您固有地解决了:浏览器如何知道它在连接时从服务器接收到的 public 密钥实际上属于服务器。他们之间还没有安全通道。
输入证书。
证书本质上是将 public 密钥与其所有者相关联的文档,而这正是您想要的。 当浏览器连接到网站时,服务器将其 public 密钥 连同其证书 一起发送,以便浏览器可以验证 public 密钥确实属于服务器(此域名中的域名案例)发送它。如何验证它超出了这个 post 的范围,重点是证书是由另一个 public 密钥签名的,证书可以由另一个 public 密钥签名,等等., 并且链由您的 OS/browser 供应商已经为您的计算机 and/or 浏览器设置的所谓可信根证书列表终止。
您也应该以同样的方式使用证书验证 public 密钥。 您甚至不需要 SSL (https) 传输的负担, 验证 public 密钥属于特定主题是证书的主要目的。
因此,您所要做的不仅仅是从 API 中获取 public 密钥,而是获取它及其证书。您可能已经在这样做了,裸键 public 很少使用。您很可能已经从服务器接收到 pfx 或 cer 或 crt 或其他任何内容。根据您正在开发的技术堆栈,您肯定可以使用内置机制来完全验证证书并确保其有效。但请不要实施您自己的验证,因为这是一项棘手的工作,而且很难做到正确。如果证书通过验证,您可以相信从 API 收到的 public 密钥是真实的,并且属于它声称属于的任何对象。不过可能有一些注意事项(例如,确保除了基本验证之外,您还检查证书中其他人无法拥有的字段组合)。
作为一项额外的安全措施,您还可以实施证书固定,通过在客户端中包含有效证书的指纹列表,使其更安全地抵御某些类型的攻击(在浏览器客户端中较少,但概念仍然相同)。
编辑(在证书通过过期的一般验证后要检查哪些字段等):
一般情况下,这取决于谁签署了证书以及它是什么类型的证书。
由真正的证书颁发机构 (CA) 签署的服务器证书只能将服务器域作为其通用名称 (CN) 字段,真正的 CA 通常不会签署任何其他内容,他们也不会签署yourdomain.com 的证书,除非你能证明你控制 yourdomain.com。因此,在这种情况下,在证书通过验证后检查 CN 可能就足够了。不过,您确实需要检查 CN,因为任何人都可以拥有来自 GlobalSign 或 Thawte 或其他受信任的 CA 的有效证书,这只是要花钱。他们不能拥有的是 yourdomain.com.
的证书如果您签署自己的证书,您也不会为任何人签署任何东西,因此在这种情况下,检查颁发者(您签署的)和 CN(为谁)就足够了。如果证书以其他方式通过验证(意味着受信任的根证书对其进行了签名)应该没问题,因为攻击者通常无法在您的计算机上获得他的 CA 证书。
总的来说就是你想查别人查不到的东西。如果您依赖真正的 CA,这会更容易,而且通常最好检查指纹。