Security 如果你能解码JWT,它们的安全性如何?

Security 如果你能解码JWT,它们的安全性如何?,security,jwt,express-jwt,Security,Jwt,Express Jwt,如果我得到一个密码,并且我可以解码有效载荷,那怎么安全呢?难道我不能从报头中取出令牌,解码并更改有效负载中的用户信息,然后用相同的正确编码秘密将其发送回去吗 我知道它们必须是安全的,但我真的很想了解这些技术。我遗漏了什么?JWTs可以是签名的,也可以是加密的,或者两者都可以。如果令牌已签名但未加密,则每个人都可以读取其内容,但如果您不知道私钥,则无法更改它。否则,接收者将注意到签名不再匹配 回答你的评论:我不确定我是否正确理解你的评论。可以肯定的是:你知道并理解数字签名吗?我将简要解释一个变体(

如果我得到一个密码,并且我可以解码有效载荷,那怎么安全呢?难道我不能从报头中取出令牌,解码并更改有效负载中的用户信息,然后用相同的正确编码秘密将其发送回去吗


我知道它们必须是安全的,但我真的很想了解这些技术。我遗漏了什么?

JWTs可以是签名的,也可以是加密的,或者两者都可以。如果令牌已签名但未加密,则每个人都可以读取其内容,但如果您不知道私钥,则无法更改它。否则,接收者将注意到签名不再匹配

回答你的评论:我不确定我是否正确理解你的评论。可以肯定的是:你知道并理解数字签名吗?我将简要解释一个变体(HMAC,它是对称的,但还有许多其他变体)

假设Alice想给Bob发送JWT。他们都知道一些共同的秘密。马洛里不知道这个秘密,但想干涉并改变JWT。为了防止这种情况发生,Alice计算
散列(有效载荷+机密)
,并将其作为签名附加

在接收消息时,Bob还可以计算
散列(有效负载+机密)
以检查签名是否匹配。 但是,如果Mallory更改了内容中的某些内容,她将无法计算匹配的签名(这将是
散列(newContent+secret)
)。她不知道这个秘密,也没有办法找到它。 这意味着如果她改变了什么,签名将不再匹配,Bob将不再接受JWT

让我们假设,我向另一个人发送消息
{“id”:1}
,并用
Hash(content+secret)
签名。(+在这里只是串联)。我使用SHA256散列函数,得到的签名是:
330e7b0775561c6e95797d4dd306a150046e239986f0a133230fda0235bda8c
。现在轮到你了:扮演马洛里的角色,试着在消息上签名
{“id”:2}
。你不能,因为你不知道我用了哪个秘密。如果我认为收件人知道秘密,他可以计算任何邮件的签名并检查其是否正确。

您可以转到,粘贴您的令牌并阅读内容。起初,这对很多人来说是不和谐的

简而言之,JWT并不关心加密。它关心验证。也就是说,它总能得到“这个令牌的内容是否被操纵”的答案?这意味着用户对JWT令牌的操作是徒劳的,因为服务器将知道并忽略该令牌。服务器在向客户机发出令牌时根据有效负载添加签名。稍后,它将验证有效负载和匹配的签名

逻辑问题是,不关注加密内容的动机是什么

  • 最简单的原因是,它假设这在很大程度上是一个已解决的问题。例如,如果与web浏览器之类的客户端打交道,您可以将JWT令牌存储在一个安全的cookie中(不通过HTTP传输,仅通过HTTPS传输)和
    httpOnly
    (Javascript无法读取),并通过加密通道(HTTPS)与服务器对话。一旦您知道服务器和客户端之间有一个安全通道,您就可以安全地交换JWT或任何您想要的东西

  • 这使事情变得简单。一个简单的实现使采用更容易,但它也让每一层做它最擅长的事情(让HTTPS处理加密)

  • JWT不是用来存储敏感数据的。一旦服务器接收到JWT令牌并对其进行验证,它就可以在自己的数据库中查找用户ID,以获取该用户的其他信息(如权限、邮政地址等)。这使JWT保持较小的大小,并避免意外的信息泄漏,因为每个人都知道不要将敏感数据保存在JWT中


  • 这与cookies本身的工作原理没有太大区别。Cookie通常包含未加密的有效负载。如果您使用HTTPS,那么一切都很好。如果您没有,那么建议您自己加密敏感cookie。不这样做意味着中间人攻击是可能的——代理服务器或ISP读取cookies,然后在以后假装是你的情况下重放它们。出于类似的原因,JWT应该始终通过HTTPS之类的安全层进行交换。

    json web令牌(JWT)中的内容并非天生安全,但有一个用于验证令牌真实性的内置功能。JWT是由句点分隔的三个散列。第三是签名。在公钥/私钥系统中,颁发者使用私钥对令牌签名进行签名,私钥只能通过其相应的公钥进行验证

    理解颁发者和验证者之间的区别很重要。令牌的接收方负责验证令牌

    在web应用程序中安全使用JWT有两个关键步骤:1)通过加密通道发送,2)在收到签名后立即验证签名。公钥密码的非对称性使得JWT签名验证成为可能。公钥验证JWT是否由其匹配的私钥签名。没有其他密钥组合可以执行此验证,因此阻止了模拟尝试。遵循这两个步骤,我们可以在数学上确定JWT的真实性


    更多阅读:

    只有服务器上的JWT私钥才能解密加密的JWT。知道私钥的人将能够解密加密的JWT


    将私钥隐藏在服务器中的安全位置,并且永远不要告诉任何人私钥。

    我建议使用jwt.io中没有的特殊算法对JWE进行解密

    参考链接:

    这个答案可能太晚了,或者你已经找到了答案,但我还是觉得这会有帮助
    jwt.generate('PBES2-HS512+A256KW', 'A256GCM', payload, pwd, (error, token) => {
      jwt.parse(token).verify(pwd, (error, parsedToken) => {
        // other statements
      });
    });