libai8723 / front-end-dev-notes-bignerdbook

Github Pages
https://libai8723.github.io/front-end-dev-notes-bignerdbook/
1 stars 0 forks source link

Miscellaneous Weekly 2022-09-04 #59

Open libai8723 opened 2 years ago

libai8723 commented 2 years ago

关于JWTs

在最近的一段时间内,因为讨论Jalor的微服务应用比较多,所以遇到了非常多次关于JWT的名词,还是下决心把JWT搞清楚,到底是怎么回事吧。

1. RFC7519 - JSON Web Token

首先是JWT的RFC标准,其实非常短,也就是20多页,现在摘录一下重点。RFC的用词非常标准,并且准确,可以当做范文来读。

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties.

JWT是一种用于双方之间传递紧凑URL安全的一种声明表达形式

The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code(MAC) and/or encrypted.

在JWT中的声明是以JSON对象的方式来编码的,(声明)作为JSON Web Signature结构的载荷, 或者以文本形式存在作为JSON Web Encryption加密的载荷,使得声明可以被数字签名,或者使 声明的完整性通过MAC码来保证,或者使得声明被加密。

2. Introduction

JSON Web Token (JWT) is a compact claims representation format intended for space constrained environments such as HTTP Authorization headers and URI query parameters.

JWT是一种紧凑的声明表达形式,用来在空间受限的环境中使用, 例如:HTTP Authorization Headers或者是URI的查询参数中。

JWTs are always represented using the JWS Compact Serialization or the JWE Compact Serialization.

JWTs总是通过JWS紧凑序列化或者JWE紧凑序列化所表达,这里 JWS和JWE也分别对应2篇RFC。

JWS:https://www.rfc-editor.org/rfc/rfc7515.html @todo JWE:https://www.rfc-editor.org/rfc/rfc7516.html @todo

3. 术语,在JWT中会用到的

出现在JWS的RFC-7515中:

  1. JSON Web Signature (JWS)
  2. Base64url Encoding
  3. Header Parameter:A name/value pair that is member of the JOSE Header. 头部参数就是在JOSE中的键值对。
  4. JOSE Header:JSON object containing the parameters describing the cryptographic operations and parameters employed. The JOSE (JSON Object Signing and Encryption) Header is comprised of a set of Header Parameters. JOSE是JSON对象签名和加密头的缩写,本身就是一个JSON对象,包含了参数用来描述使用的密码学操作和参数。
  5. JWS Compact Serialization
  6. JWS Payload
  7. JWS Signature
  8. Unsecured JWS

出现在JWE的RFC-7516中:

  1. JSON Web Encryption (JWE)
  2. Content Encryption Key (CEK)
  3. JWE Compact Serialization
  4. JWE Encrypted Key
  5. JWE Initialization Vector

还有一些术语出现在Internet Security Glossary, Version 2 - RFC-4949:https://www.rfc-editor.org/rfc/rfc4949

  1. Ciphertext:密文,加密后的
  2. Digital Signature:A value computed with a cryptographic algorithm and associated with a data object in such a way that any recipient of the data can use the signature to verify the data's origin and integrity. 数字签名是使用加密算法计算出来的值,和一个数据对象关联起来,这样任何接收方,都可以使用这个签名来验证数据的来源和完整性。在RFC4949里面有对数字签名的详细的描述。
  3. Message Authentication Code (MAC):解释的不太清楚,到时候再看吧。A specific ANSI standard for a checksum that is computed with a keyed hash that is based on DES. 是基于DES算法的计算出来的一种校验码
  4. Plaintext:就是字面意思 Plain Text朴素的字符,也被称为 Clear Text。

在本RFC中出现的术语:

JSON Web Token (JWT):

A string representing a set of claims as a JSON object that is encoded in a JWS or JWE, enabling the claims to be digitally signed or MACed and/or encrypted.

JWT就是一段字符串,这段字符串使用JSON对象表达了一组 声明的集合,并且以JWS或者JWE来进行编码,使得这些声明 可以被数字签名,或者做校验(MACed),或者被加密。

JWT Claims Set: A JSON object that contains the claims conveyed by the JWT. 就是一个包含了JWT传递的若干声明的JSON对象

Claim: A piece of information asserted about a subject. A claim is represented as a name/value pair consisting of a Claim Name and a Claim Value. 声明就是关于某个主题的信息。一个声明被表达为名字/取值的对。

Claim Name: The name portion of a claim representation. A Claim Name is always a string.

一个声明的名字的部分,必须是一个String类型。

Claim Value: The value portion of a claim representation. A Claim Value can be any JSON value.

一个声明的取值的部分,可以是任何的JSON Value

Nested JWT——内嵌的JWT A JWT in which nested signing and/or encryption are employed. In Nested JWTs, a JWT is used as the payload or plaintext value of an enclosing JWS or JWE structure, respectively.

Unsecured JWT: A JWT whose claims are not integrity protected or encrypted. 一个JWT,它的声明的部分没有做一致性保护或者加密。

Collision-Resistant Name:防碰撞名称 A name in a namespace that enables names to be allocated in a manner such that they are highly unlikely to collide with other names. Examples of collision-resistant namespaces include: Domain Names, Object Identifiers (OIDs) as defined in the ITU-T X.660 and X.670 Recommendation series, and Universally Unique IDentifiers (UUIDs) [RFC4122]. When using an administratively delegated namespace, the definer of a name needs to take reasonable precautions to ensure they are in control of the portion of the namespace they use to define the name.

防碰撞名称是一个精心设计好的命名空间,在这个空间中,使得 名字发生碰撞/冲突的几率非常小。

防碰撞命名空间的例子包括:域名(Domain names), Object Identifiers(OIDs) 以及UUIDs(Universal Unique IDentifiers)。当采用一种行政命令/管理手段来 实现的命名空间的时候,对于名字的定义着来说,要非常用心和注意,控制好 命名空间防止冲突。

StringOrURI A JSON string value, with the additional requirement that while arbitrary string values MAY be used, any value containing a ":" character MUST be a URI [RFC3986]. StringOrURI values are compared as case-sensitive strings with no transformations or canonicalizations applied.

一个JSON的字符串取值,有一些额外的要求,就是如果取值中包含 冒号的话,那就必须是一个URI。StringOrURI值是大小写敏感的。

NumericDate——数字化的日期 A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time, ignoring leap seconds. This is equivalent to the IEEE Std 1003.1, 2013 Edition [POSIX.1] definition "Seconds Since the Epoch", in which each day is accounted for by exactly 86400 seconds, other than that non-integer values can be represented. See RFC 3339 [RFC3339] for details regarding date/times in general and UTC in particular.

注意是秒数,不是million-second。

libai8723 commented 2 years ago

Chapter 3. JWT Overview

摘录:A JWT is represented as a sequence of URL-safe parts separated by period ('.') characters. Each part contains a base64url-encoded value. The number of parts in the JWT is dependent upon the representation of the resulting JWS using the JWS Compact Serialization or JWE using the JWE Compact Serialization.

一个JWT本身表达为一个URL-Safe的,被 . 隔开的的序列。每一个部分都是 一个base64url-encoded的值。但是有几部分的话,取决于使用JWS紧凑序列化 或者是JWE紧凑序列化。

现在就来看一个JWT的例子吧:

首先是JOSE Header的部分,我们使用下面的例子:

{"typ":"JWT",
 "alg":"HS256"}

为了避免歧义,RFC作者给了非常详细的说明:

To remove potential ambiguities in the representation of the JSON object above, the octet sequence for the actual UTF-8 representation used in this example for the JOSE Header above is also included below. (Note that ambiguities can arise due to differing platform representations of line breaks (CRLF versus LF), differing spacing at the beginning and ends of lines, whether the last line has a terminating line break or not, and other causes. In the representation used in this example, the first line has no leading or trailing spaces, a CRLF line break (13, 10) occurs between the first and second lines, the second line has one leading space (32) and no trailing spaces, and the last line does not have a terminating line break.) The octets representing the UTF-8 representation of the JOSE Header in this example (using JSON array notation) are:

[123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125]

在java的标准库里面是有Base64这个库的,可以直接使用:

        String joseHeader = "{\"typ\":\"JWT\",\r\n" +
                " \"alg\":\"HS256\"}";

        String encodedURL = Base64.getUrlEncoder()
                .encodeToString(joseHeader.getBytes());

这里的结果和RFC里面是一样的。

下面是JWT Claims Set:

{"iss":"joe",
 "exp":1300819380,
 "http://example.com/is_root":true}

然后在java里面使用Base64做编码就可以了,注意要使用withoutPadding()

        String encodedJWTClaims = Base64.getUrlEncoder()
                .withoutPadding()
                .encodeToString(jwtClaims.getBytes(StandardCharsets.UTF_8));

ok,看到这里了,下面计算HMAC值的时候,用到了基于某一个key的hash算法,在RFC2104:HMAC: Keyed-Hashing for Message Authentication有描述,需要看一下