JWT是Json Web Token的全稱,它是一種基於JSON的令牌規範,用於在網路上聲明某種主張。 它常被用來傳送與使用者相關的資訊聲明,作為身分驗證、會話處理和存取控制機制的一部分,用於會話追蹤技術。會話追蹤技術是保持HTTP狀態的解決方案,常見的有Cookie,Session等
JWT格式
JWT 內容如下
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.5mhBHqs5_DTLdINd9p5m7ZJ6XD0Xc55kIaCRY5r6HRA
由 3 部分組成:header(標頭),payload(有效負載)和signature(簽名)
header是一個JSON對象,儲存描述資料型別type和簽名演算法alg,例如HSA256,RSA256 | { “alg”: “HS256”, “typ”: “JWT”} | 透過 Base64UrlEncode編碼後產生如下內容: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 |
payload存放一些傳輸的有效聲明,可以使用官方提供的聲明,也可以自訂聲明。 | { “sub”: “1234567890”, “name”: “John Doe”, “iat”: 1516239022} | 透過 Base64UrlEncode編碼後產生如下內容: eyJzdWIiOiIx…omit…MjM5MDIyfQ |
signature是 JWT 的核心部分,構成較為複雜,且無法被反編碼。 | 透過HMACSHA256( base64UrlEncode(header) + “.” +base64UrlEncode(payload), secret )產生如下內容: 5mhBHqs5_DTLdINd9p5m7ZJ6XD0Xc55kIaCRY5r6HRA |
一般來說,頒發token的網站會透過對header和payload進行hash處理,並使用秘密簽名金鑰產生簽名。 無論使用何種方法,這個過程都能確保自從token發布以來,網站能夠驗證資料沒有被竄改。
JWT的一些名詞介紹
- JWS ( JSON Web Signature):指的是簽名過的JWT
- JWE ( JSON Web Encryption):部分payload經過加密的JWT
- JWA ( JSON Web Algorithms ):目前JWT所用到的密碼學演算法
- nonsecure JWT:指定的是當header的簽名演算法被設定為none的時候,該JWT是不安全的,因為所有人都可以修改。
常見的JWA
JWT 最常見的幾種JWA(簽名演算法)為HS256(HMAC-SHA256) 、RS256(RSA-SHA256) 還有 ES256(ECDSA-SHA256)。這三種演算法都屬於訊息簽名演算法,它們產生的簽名都是不可逆的。 它們之間的區別在於訊息簽名和簽名驗證所需的key是不同的。
- HS256:該演算法使用相同的「secret_key」進行簽署和驗證(對稱加密)。 一旦secret_key洩露,安全性將完全喪失。HS256僅適用於集中式認證,必須由可信任方進行簽署與驗證。這個演算法在傳統的單體應用中得到了廣泛應用,但是在任何分散式的架構中,請不要使用它!
- RS256:使用RSA私鑰進行簽名,以及RSA公鑰進行驗證。 即使公鑰洩漏,也不會有任何影響,只要確保私鑰的安全即可。只要提供公鑰,RS256可以將驗證任務委託給其他應用程式。
- ES256:和RS256採用相同的方式進行私鑰簽章和公鑰驗證。 儘管兩種演算法在速度上略有差異,但ES256的簽章長度較短(可節省流量),且與RS256相比,演算法強度相當。
HS256和RS256的簽名差別如下
HS256:
signature = HMACSHA256( base64UrlEncode(header) + "." +base64UrlEncode(payload), secret );
RS256:
signature = RSASHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload), publicKey, privateKey)
JWT header
以下是用戶可控制的參數, 每個都告訴接收伺服器在驗證簽名時要用哪個金鑰
- JWK ( JSON Web Key):用JSON的格式去裝載各種加解密金鑰資訊;
- JWKs( JWK set ):將很多金鑰放到一個JSON陣列
- jku(JSON Web key URL): 提供一個 URL,網站可以從中取得一組包含正確的金鑰。
- kid(key ID): 提供一個 ID,在有多個金鑰可供選擇的情況下,伺服器可以使用該 ID 來識別正確的金鑰。 根據密鑰的格式,這可能有一個匹配的kid參數。
- kty (Key Type):金鑰類型。定義使用的加密演算法類型,例如RSA加密或橢圓曲線加密EC
JWK
網站可以使用一個可選的JWK header參數,將其公鑰以JWK格式直接嵌入到令牌本身,如下
{ "kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"typ": "JWT",
"alg": "RS256",
"jwk": {
"kty": "RSA",
"e": "AQAB",
"kid": "ed2Nf8sb-sD6ng0-scs5390g-fFD8sfxG",
"n": "yy1wpYmffgXBxhAUJzHHocCuJolwDqql75ZWuCQ_cb33K2vh9m"
} }
JWK規範其他細節可參考https://datatracker.ietf.org/doc/html/rfc7517
JWT相關攻擊技巧可參考以下
refer