过去几年来,用户数据的安全和隐私一直是一个日益关注的问题。与此同时,JWT作为应对此问题的一项技术越来越广泛应用。了解JWT将使您在其他软件工程师中脱颖而出。JWT乍看起来很简单,但实际上很难理解。
在本文中,我们将主要探讨JWT和JWS,此外,还将简要介绍JWE、JWA和JWK。本文旨在让读者在不深入探讨该主题的情况下理解JWT的概念。
它们是什么?
在深入研究之前,如果我们了解JWT、JWS、JWE、JWA和JWK之间的联系会更好。
JWT、JWS、JWE、JWA和JWK之间的关系如下图所示:
从上图可以看出:
JSON Web Token(JWT)是一个抽象概念,以JSON Web Signature(JWS)和JSON Web Encryption(JWE)的形式表示。
JSON Web Signature(JWS)和JSON Web Encryption(JWE)使用在JSON Web Algorithm(JWA)中定义的签名和加密算法来保证其安全性。
在JSON Web Algorithm(JWA)中定义的签名算法的公钥可以作为JSON Web Key(JWK)进行托管。
既然我们知道它们之间的关系,让我们更深入地了解一下JWT、JWS、JWE、JWA和JWK。
JSON Web Token(JWT)
首先,让我们来看看RFC 7519中对JWT的定义。
“JSON Web Token (JWT) 是一种紧凑的声明表示格式,特别适用于空间受限的环境,如HTTP授权头和URI查询参数。JWT将声明编码为JSON对象,作为JSON Web Signature(JWS)结构的有效载荷或JSON Web Encryption(JWE)结构的明文,使得声明能够进行数字签名、完整性保护(通过消息认证码(MAC))和/或加密。JWT始终使用JWS紧凑序列化或JWE紧凑序列化进行表示。”
从文本中,我们可以了解到JWT不是一种结构,而是一组声明,以JWS或JWE的形式来保证其安全性。在最基本的形式中,JWS和JWE之间的区别在于每个人都可以看到JWS的有效载荷,而JWE的有效载荷是加密的。
在本文中,我们将更多地探讨JWS而不是JWE。
JSON Web Algorithm(JWA)
JWA(RFC 7518),即JSON Web Algorithm,是一项规范,定义了用于创建JWT的散列和加密算法。
例如,以下是我们可以使用的散列算法,用于创建具有JWS结构的JWT。
S结构的JWT的散列算法示例:
HS256:使用HMAC SHA-256算法进行散列。
HS384:使用HMAC SHA-384算法进行散列。
HS512:使用HMAC SHA-512算法进行散列。
除了散列算法之外,JWA还定义了用于加密和解密JWE中有效载荷的算法。以下是一些例子:
RSA-OAEP:使用RSA算法和OAEP填充进行加密和解密。
A128GCM:使用AES-GCM算法进行加密和解密。
JWA确保JWT在创建和处理过程中使用安全的算法。
JSON Web 密钥 (JWK)
JWK ( RFC 7517 ) 代表 JSON Web 密钥。JWK 是一种 JSON 数据结构,包含有关哈希函数的加密密钥的信息。这是一种以 JSON 格式存储哈希密钥的方法。
{ "kty":"EC", "crv":"P-256", "x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", "y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0", "kid":"Public key used in JWS spec Appendix A.3 example" }
JWK通常用于托管具有非对称密钥(私钥和公钥)的哈希函数的公钥,因此消费者可以自己获取密钥。
JSON 网络签名 (JWS)
JWS ( RFC 7515 ),代表 JSON Web Signature,是 JWT 使用的结构之一。这是 JWT 最常见的实现。JWS 由 3 部分组成:JOSE 标头、有效负载和签名。
以下是 JWS 紧凑序列化的示例。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
如果我们解码 JWS,我们将得到 JOSE(JavaScript 对象签名和加密)标头:
{ "alg": "HS256", "typ": "JWT" }
有效负载:
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
下一部分是签名。我们不会解码它,因为它是一个字节值。
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
与 JWT(在 JWS 结构中)相关的最常见问题是如何保证其安全,因为每个人都可以解码 JWT 并查看其数据。JWT 是安全的,因为不是每个人都可以创建它,只有拥有密钥的人才能创建它。
JSON 网络加密 (JWE)
与 JWS 不同, JWE ( RFC 7516 ) 使用加密算法对其内容进行加密。唯一能看到 JWT 内部内容的是拥有密钥的人。
JWE紧凑序列化的结构如下:
BASE64URL(UTF8(JWE Protected Header)) || ’.’ || BASE64URL(JWE Encrypted Key) || ’.’ || BASE64URL(JWE Initialization Vector) || ’.’ || BASE64URL(JWE Ciphertext) || ’.’ || BASE64URL(JWE Authentication Tag)
让我们看一个例子:
eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.RD09fEltrYPVNoGt2KY1Odv_5eDxkU4VX1f__P8b9zl9uzh5bmvvJy35dL-hYlUib1g63qnWBEfeSyDk5cAIQiMt6PZCBQzuWQJQlQtuo2UPLZznmLPqah37uHKB4a57q_lWf_W9soyZbO7Zj7QRNz4ZR4s5ozRHArSZcc1pAL-pYuHKyeh6Ey8t4bk66wkthjjfOjXvIfOlgbemhibegmE4GpQL6F-m0teqcAE-OxkaBRTmmb4AD5HdrCJWCIIuC52fzuWrhcoNmHM74ggtWUUjlHaKpwcVE-IWINTFaz5Pi9u4U3vnVNOZwDwB0TLSQvqnPwTZ-bYWNj8vH4TS_w.Pjo5QK1u1otxgcuBR7e8ew._OElhHugS2L6Kp04HhbFt6dLij_KXhO654RmT4JKyswYBX0wqRWt7ZzAE6eCHfJSJdMQYxqVSNloGb4OSIzYcTEo174lBZBINkHW-w2K6E0.QBDgBFizm80HLVkZvfBPCg
该示例使用RSA_OAEP_256密钥管理算法 和AES_128_CBC_HMAC_SHA_256作为其加密算法。如果我们解密 JWE,我们将得到:
{ "iss": "https://codecurated.com", "exp": 1651417524, "iat": 1651417224 }
解码 JWT
现在让我们通过以下示例更深入地了解 JWT:
eyJhbGciOiJIUzI1NiIsImtpZCI6IjIwMjItMDUtMDEifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJyaWxpYW4gRmlyZGF1cyIsImlhdCI6MTY1MTQyMjM2NX0.qsg3HKPxM96PeeXl-sMrao00yOh1T0yQfZa-BsrtjHI
示例中的JWT是具有JWS紧凑序列化结构的JWT。我们需要用(点)分割 JWT .,然后 Base64 对其进行解码以查看其中的内容。
对 JWT 进行拆分和解码后,我们将得到三部分:
JOSE(JavaScript 对象签名和加密)标头
有效载荷 Payload
签名 Signature
JOSE Header
eyJhbGciOiJIUzI1NiIsImtpZCI6IjIwMjItMDUtMDEifQ
对字符串进行 Base64 解码后,我们将得到:
{ "alg": "HS256", "kid": "2022-05-01" }
JWT 的这一部分称为 JOSE 标头。通过 JOSE 标头,JWT 可以告知客户端如何处理 JWT。
让我们分解一下 JWT 中的两个字段:
alg:包含有关 JWT 签名算法的信息。
kid:包含用于验证JWT的密钥的id信息。我们将在 JWK 部分对此进行更多探讨。
alg是唯一的强制标头,也是大多数情况下唯一需要的标头,但还有更多标头。
有效载荷Payload
抛开 JOSE 标头,让我们看一下第二部分,即有效负载。
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkJyaWxpYW4gRmlyZGF1cyIsImlhdCI6MTY1MTQyMjM2NX0
我们解码后:
{ "sub": "1234567890", "name": "Brilian Firdaus", "iat": 1651422365 }
JWT 的这一部分称为有效负载。有些字段带有术语 JWT 声明 ( sub、name、iat)。因此,现在似乎是谈论 JWT 主张的好时机。
JWT 声明分为三种类型:
登记索赔 Registered Claims
公众索赔 Public Claims
私人索赔 Private Claims
让我们从注册索赔开始一一分解。注册声明是最初记录在 RFC 7519 中的声明。
iss(Issuer):表示JWT的发行者是谁。
sub(Subject):表示请求JWT的用户id。
aud(受众):显示谁是 JWT 的目标消费者。
exp(Expiration):JWT 的过期时间。
您可以在此处查看完整列表。根据 RFC 7519 的规定,这些声明都不是强制性的,但它们对于保护您的 JWT 至关重要。 datatracker.ietf.org/doc/html/rfc7519#section-4.1
我们将探讨的下一种索赔类型是私人索赔。这些主张可以是任何东西。由 JWT 创建者或消费者决定声明名称和功能。
警告:指定私有声明时,需要注意不要造成名称冲突。
最后一个是公共声明,这是通过 IETF 公开注册的一类声明。
大多数人没有任何用例需要他们注册他们的索赔。为了获得最佳实践,您可以搜索公共声明列表并使用适合您的用例的声明。
签名Signature
如果您已经读到这一部分,您可能想知道是什么让 JWT 安全,因为每个人都可以看到它的内容。嗯,JWS 的有效负载是供所有人阅读的。JWT 的安全性在于消费者可以验证谁是颁发 JWT 的人。
JWT中的签名部分是使用哈希函数创建的。如果您不熟悉哈希函数,它是一种将一个对象映射到另一个对象的算法。哈希函数有两个关键特征,使其适合保护 JWT:
它只有一种方式
哈希过程的结果总是相同的
在本文中,我们将探讨 JWT 中使用的 2 个最常见的哈希函数:
HMAC SHA-256
ECDSA256
现在,让我们分解示例中使用的签名:
qsg3HKPxM96PeeXl-sMrao00yOh1T0yQfZa-BsrtjHI
它是使用HS256MAC 算法和密钥(以 base64 形式)生成的:
7TgIAQCcYUA27bCI5+m7InRwp/mzQ+ArnFW/4c0Q51U=
MACHS256算法接收字节值作为其密钥参数并产生字节值作为其输出。因此,与标头和有效负载不同,如果我们尝试解码签名,我们将获得字节值。
让我们更深入地探讨一下数字签名或 MAC 算法。
HMAC SHA-256
我们将探讨的第一个算法是 HMAC SHA-256 ( HS256),这是一种使用带有对称密钥的哈希函数的 MAC 算法。具有对称密钥的哈希函数意味着哈希函数只有一个密钥。因此,JWT 的生产者和消费者将使用相同的密钥来签名和验证 JWT。使用此算法的优点是不需要太多 CPU 资源来创建哈希。
信息: 建议 hs256 密钥的最小字节长度为 32 字节。密钥必须使用加密安全的伪随机数生成器生成,以确保其随机性。
ECDSA-256
与HMAC不同,ECDSA-256(ES256)是一种使用非对称密钥的哈希函数的算法。使用非对称密钥的哈希函数意味着我们需要生成两个密钥。一个密钥被称为私钥,它可以用于对JWT签名进行签名和验证。另一个密钥称为公钥,只能用于验证JWT签名。
顾名思义,公钥可以存储在公共空间(通常作为JWK)中,因此需要验证JWT签名的客户端可以快速获得它。相反,私钥必须是安全的,并被视为凭证。
选择哪个哈希函数?
我们已经学习了两种算法,HS256和ES256,但什么时候该选择一种而不是另一种?通过思考JWT的生产者和消费者是否不是同一个组件,您可以很容易地做出决定。
如果JWT的使用者是同一个组件,那么您可以使用HS256算法。这个散列函数最常见的用例是当您使用JWT制作身份验证系统时。
另一方面,如果JWT是由不同的组件生成和使用的,则可以使用ES256。通过这种方式,您可以保护您的密钥,并确保没有其他人(甚至公钥所有者)可以代表您创建JWT。
警告:有些人认为HS256是一种反模式,因为JWT被认为是用来提高安全性的,但大多数使用该算法的用例都会降低安全性。
例如,假设您计划将JWT用作身份验证会话,而不是数据库。在这种情况下,您的系统会更加不安全,因为您无法使JWT过期,因此无法启动会话。
将公钥存储为JWK(JSON Web密钥集)
如果您计划让公众使用和验证您的JWT,建议将公钥作为JWK托管在URL上。这样,如果消费者想要验证您的JWT,他们可以查询托管JWK的特定URL并获取公钥。
{ "keys": [ { "kty": "EC", "kid": "2022-05-01", "x": "g_pYyqY7Htj8Aa989Ura0_mwRdqJPEnhknKzaUrztj8", "y": "MwOFYLE-VYre92hU0iDjNx36dk7cX6xdGgdgLIPt6Ts", "crv": "P-256" }, { "kty": "EC", "kid": "2020-01-01", "x": "6bw04ZlSMjxVzC7gXv75XAposOVTONh45ZPR0AeYaoU", "y": "vYyCSIt0m5k4Q5A_uW8h3nEYJvgA8PgREErLcaiAHgQ", "crv": "P-256" } ] }
您可能已经注意到 JSON 中有多个密钥,这就是它被称为 JSON Web Key Set的原因。如果您的产品使用多个密钥,您可以将每个密钥托管在 JWK 中。要确定使用哪个密钥,您需要kid在 JOSE 标头中添加 或 key id 字段。
{ "alg":"ES256", "kid":"2022-05-01" }
这样,客户端将通过比较kidJOSE 标头 JWT 中的密钥与 JWK 中的密钥来知道要获取哪个密钥。其他字段组合起来将形成公钥。
Takeaway
在这篇文章中,我们了解到:
JWT 是一个关于如何允许一方或多方安全地交换信息的抽象概念。JWT 的实现以 JWS 或 JWE 的形式出现。
JWS和JWE之间的区别在于,JWS允许每个人都看到其有效负载,而JWE则通过使用加密方法不允许它。
即使每个人都可以看到其有效负载,JWS 仍被认为是安全的,因为 JWS 的创建者可以使用 MAC 或签名验证算法通过其签名进行验证。这样,消费者就可以确定创建 JWT 的人就是预期的人。
我们探索了两种类型的算法,HS256和ES256。HS256当JWT的生产者和消费者是相同组件时适合,而ES256当生产者和消费者是不同组件时适合。
我们可以使用 JSON Web Key Set 来托管具有非对称密钥的哈希函数的公钥。您需要kid在 JWT 的 JOSE 标头中设置该字段,以便消费者可以将其与 JWK 中的字段进行比较,以获得兼容的密钥。文章来源:https://www.toymoban.com/diary/system/528.html
文章来源地址https://www.toymoban.com/diary/system/528.html
到此这篇关于JWT 介绍及相关概念 (JWS、JWE、JWA、JWK)的文章就介绍到这了,更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!