Jwk là gì

Jwk là gì

Tuan

·

Follow

Sep 18, 2020

·

7 min read

JWT, JWS và JWE

JSON Web Token (JWT) định nghĩa một chuẩn chứa dữ liệu để trao đổi giữa các bên. JWT trở thành một chuẩn IETF Standard vào tháng 5/2015 là RFC7519. Đã có nhiều ứng dụng sử dụng JWT. OpenID Connect là một trong số đó. Trong OpenID Connect (OIDC) thông tin id_token được biểu diễn dưới dạng JWT. Trong bảo mật API và microservices, JWT được sử dụng để trao đổi và xác nhận định danh người dùng.

Jwk là gì

Ví dụ một chuỗi JWT dưới đây do Google gửi về khi yêu cầu thông tin định danh của một người dùng:

eyJhbGciOiJSUzI1NiIsImtpZCI6Ijc4YjRjZjIzNjU2ZGMzOTUzNjRmMWI2YzAyOTA3NjkxZjJjZGZmZTEifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTEwNTAyMjUxMTU4OTIwMTQ3NzMyIiwiYXpwIjoiODI1MjQ5ODM1NjU5LXRlOHFnbDcwMWtnb25ub21ucDRzcXY3ZXJodTEyMTFzLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiZW1haWwiOiJwcmFiYXRoQHdzbzIuY29tIiwiYXRfaGFzaCI6InpmODZ2TnVsc0xCOGdGYXFSd2R6WWciLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXVkIjoiODI1MjQ5ODM1NjU5LXRlOHFnbDcwMWtnb25ub21ucDRzcXY3ZXJodTEyMTFzLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiaGQiOiJ3c28yLmNvbSIsImlhdCI6MTQwMTkwODI3MSwiZXhwIjoxNDAxOTEyMTcxfQ.TVKv-pdyvk2gW8sGsCbsnkqsrS0T-H00xnY6ETkIfgIxfotvFn5IwKm3xyBMpy0FFe0Rb5Ht8AEJV6PdWyxz8rMgX2HROWqSo_RfEfUpBb4iOsq4W28KftW5H0IA44VmNZ6zU4YTqPSt4TPhyFC9fP2D_Hg7JQozpQRUfbWTJI

Sau khi được giải mã sẽ cho kết quả đẹp và ý nghĩa hơn rất nhiều:

{alg:RS256,kid:78b4cf23656dc395364f1b6c02907691f2cdffe1}

JOSE Header

Phần đầu của chuỗi JWT được gọi là JOSE Header (Javascript Object Signing and Encryption). JOSE header chỉ ra rằng đây là một bản tin được signed. Google xác nhận định danh của người dùng bằng cách sign JWT, cái đang mang thông tin định danh của người dùng.

Jwk là gì

Một chuỗi Signed JWT được gọi là JWS (JSON Web Signature). Trong thực tế JWT không tồn tại riêng lẻ mà nó phải là JWS hoặc JWE (JSON Web Encryption).

Jwk là gì

Trong ví dụ trên cả hai thông tin algkid đều không được định nghĩa trong JWT nhưng có trong JWS. JWT chỉ định nghĩa 2 thông tin là typcty trong JOSE header.

typ (type): The typ element is used to define the media type of the complete JWT. A media type is an identifier, which defines the format of the content, transmitted on the Internet. There are two types of components that process a JWT: JWT implementations and JWT applications. Nimbus is a JWT implementation in Java. The Nimbus library knows how to build and parse a JWT. A JWT application can be anything, which uses JWTs internally. A JWT application uses a JWT implementation to build or parse a JWT. In this case, the typ element is just another element for the JWT implementation. It will not try to interpret the value of it, but the JWT application would. The typ element helps JWT applications to differentiate the content of the JWT when the values that are not JWTs could also be present in an application data structure along with a JWT object. This is an optional element and if present for a JWT, it is recommended to use JWT as the media type.
cty (content type): The cty element is used to define the structural information about the JWT. It is only recommended to use this element in the case of a nested JWT.

JWS không bắt buộc một loại thuật toán mã hóa nào. Tất cả các thuật toán phù hợp đều được chỉ ra trong RFC 7518 JSON Web Algorithm (JWA). Giá trị kid cung cấp thông tin về key được dùng để sign message. Bên nhận JWT nhìn vào kid sẽ biết ở đâu và làm thế nào để tìm key.

In a JWT, the members of the JSON object represented by the JOSE header describe the cryptographic operations applied to the JWT and optionally, additional properties of the JWT. Depending upon whether the JWT is a JWS or JWE, the corresponding rules for the JOSE header values apply. Both under the JWS and JWE, the JOSE header is a must or in other words there exists no JWT without a JOSE header.

Unsecured JWT

Là JWS mà thông tin algNone, tức là JWS không được signed. Khi sử dụng loại này cần bảo mật bằng các giao thức mã hóa như TLS.

Claim Set

Quay trở lại ví dụ của Google ở trên chuỗi JWT cũng chính là JWS. Sau khi sử dụng base64url-decoded để giải mã thông tin ta có phần thứ 2 của JWT như sau:

Jwk là gì

Các thông tin này được gọi là Claim Set, nó biểu diễn một JSON object với các thuộc tính được cấp bởi bên phát hành ở đây là Google. Các claim này phải duy nhất, nếu không sẽ có lỗi khi đọc hoặc lấy giá trị cuối cùng. JWT không quy định claim nào là bắt buộc, claim nào là tùy chọn. Ví dụ OIDC định nghĩa iss, sub, aud, exp, iat là các thông tin bắt buộc; auth_time, nonce, acr, amr azp là tùy chọn.

Signature

Phần cuối cùng trong chuỗi JWT ở trên được gọi là signature; cũng được mã hóa base64url-encoded. Trong ví dụ này Google sử dụng RSASSA-PKCS1-V1_5 và SHA-256.

Serialization

Một Signed JWT được truyền tải qua mạng. Trước khi truyền qua mạng nó cần được serialized. Theo JWS/JWE spec có 2 loại: JWS/JWE compact serialization và JWS/JWE JSON serialization.

JWS (JSON Web Signature)

JWS Compact Serialization

Gồm 3 thành phần: JOSE header, JWT payload, JWS Signature được ngăn cách bởi dấu chấm(.).

Jwk là gì

Qúa trình tạo một JWS Compact như sau:

  • Tạo một JSON object bao gồm tất cả các headers. Thông tin public key tương ứng với key được dùng để signed được chứa một trong các thuộc tính jku, jwk, kid, x5u, x5c, x5t and x5t#s256.
  • Tính base64url-encoded cho cho object trên theo UTF8 encoding để có được phần đầu của JWS.
  • Tạo payload hay chính là phần nội dung được signed. Thường thì payload là một dạng JSON. Tuy nhiên cũng có thể là XML.
  • Tính base64url-encoded cho phần payload trên để có được phần thứ hai của JWS.
  • Tạo bản tin để được ký: ASCII(BASE64URL-ENCODE(UTF8(JOSE Header)) . BASE64URL-ENCODE(JWS Payload))
  • Tính chữ ký cho phần thông tin trên với key là private key tương ứng với public key trong JOSE header.
  • Tính toán base64url-encoded cho phần chữ ký; chính là phần thứ 3 của JWS.
  • Ghép 3 phần lại với nhau ta có được chuỗi JWS.

JWS JSON Serialization

Loại này hiếm khi được sử dụng nên tôi không trình bày ở đây.

JWE (JSON Web Encryption)

Chuẩn hóa cách biểu diễn mã hóa nội dung của một đối tượng JSON. JWE cũng sử dụng 2 loại Serialization như JWS.

JWE Compact Serialization

Khác với JWS, JWE loại này gồm tới 5 phần như trong hình

Jwk là gì

JOSE header tương tự với JWS ngoại trừ thêm 2 thuộc tính mới là: enczip. enc định nghĩa content encryption algorithm và nên là thuật toán đối xứng Authenticated Encryption with Associated Data (AEAD). Thuộc tính alg được dùng để định nghĩa thuật toán mã hóa cho Content Encryption Key (CEK).

Authenticated Encryption with Associated Data (AEAD) is a block cipher mode of operation which simultaneously provides confidentiality, integrity, and authenticity assurances on the data; decryption is combined in single step with integrity verification.

Ví dụ:

{alg:RSA-OAEP,enc:A256GCM}

Thành phần thứ 2 là khóa mã hóa được sử dụng trong các thuật toán mã hóa. Một số thuật toán mã hóa yêu cầu một initial vector, thường được sinh ngẫu nhiên và được chứa trong phần thứ 3. Phần thứ 4 là mã hóa encode base64 cho nội dung đã được mã hóa bởi Content Encryption Key (CEK), JWE initialization vector và Additional Authentication Data (AAD) bằng thuật toán mã hóa trong enc . Thuật toán AEAD cũng đồng thời chỉ ra thông tin AAD. Phần cuối của JWE là mã hóa encode base64 của Authentication tag được sinh ra trong quá trình mã hóa của AEAD.

JWE được signed như sau:

  • Tìm ra key management mode bởi thuật toán được sử dụng để xác định giá trị CEK. Thuật toán này được chỉ ra trong alg.
  • Tính giá trị CEK và JWE Encrypted Key dựa trên key management mode. CEK sẽ được dùng để mã hóa JSON payload.
  • Tính base64url-encode của JEW Encrypted Key để có phần thứ 2 của JWE.
  • Sinh ngẫu nhiên giá trị của JWE Initialization Vector và dùng base64url-encode để có được phần thứ 3 của JWE.
  • Nếu cần nén thông tin payload thì payload cần được nén bằng thuật toán được chỉ ra trong zip.
  • Tính toán AAD là giá trị ASCII của encoded JOSE header.
  • Mã hóa payload đã nén bằng CEK, JWE initialization vector và AAD theo thuật toán được chỉ ra trong enc
  • Sau khi mã hóa xong sẽ sinh ra thông tin ciphertext và Authentication tag.
  • Tính base64url-encode của Authentication tag để có được phần thứ 5 của JWE.

BASE64URL-ENCODE(UTF8(JWE Protected Header)) .
BASE64URL-ENCODE(JWE Encrypted Key) .
BASE64URL-ENCODE(JWE Initialization Vector) .
BASE64URL-ENCODE(JWE Ciphertext) .
BASE64URL-ENCODE(JWE Authentication Tag)

Tổng kết

Trên đây là toàn bộ giới thiệu về JWT, JWE và JWS. Chi tiết về cách thức thực hiện thường đều đã được cài đặt trong các thư viện của từng ngôn ngữ. Việc của chúng ta là hiểu ý nghĩa và áp dụng sao cho đúng.

Cám ơn các bạn đã dành thời gian đọc. Các bạn cứ đóng góp ý kiến và tôi sẽ liên tục cập nhật.