JWT 是如何實作「數位簽名」的?揭秘 signature 的面紗

古古

2024/12/24


在上一篇的 JWT 是什麼?一次搞懂 JWT 的組成和運作原理 文章中,我們有介紹了 JWT 是由三個部分所組成,分別是:header、payload 以及 signature

而在 header、payload、signature 這三個部分中,他們各自負責的功能如下:

  • header: 用來設定這個 JWT 的簽名算法、以及此 Token 的類型
  • payload: 用來儲存使用者的數據,可以根據自己的需求進行客製化
  • signature: 用來儲存「簽名」的計算結果

因此這篇文章我們就會接著來探討,為什麼 JWT 透過 signature 的部分就可以實作出「數位簽名」的概念,並且也會介紹「數位簽名」到底是有多神奇,可以直接阻擋駭客的竄改。

本文為 JWT 系列文的最終章,會使用到前面所提到的所有概念(包括 JWT 的組成、非對稱加密、Hash),因此如果你對這些概念還不太熟悉,建議可以先回頭參考前面文章的介紹(建議按照順序閱讀,才會有最佳的閱讀體驗):

  1. Session 和 JWT 的差別在哪裡?
  2. 密碼學中的 Encode、Encrypt、Hash 的差別在哪裡?
  3. JWT 是什麼?一次搞懂 JWT 的組成和運作原理
  4. JWT 是如何實作「數位簽名」的?揭秘 signature 的面紗 (本文)

signature(數位簽名)的運作邏輯 #

前置作業 #

如果要實作 JWT 的數位簽名的機制,最常見的做法是使用 「非對稱加密」 來實作,所以在實作前,後端需要先生成一組「公鑰」和「私鑰」出來,等等就會使用這兩組密鑰來搭配實作「數位簽名」的功能。

而當後端生成好一對公鑰和私鑰之後,就可以開始來進行 JWT 的生成了!

補充:在非對稱加密中,公鑰是公開的、可以廣發給所有人,私鑰則是私有的,要自己保管好,絕對不可以洩漏。並且使用公鑰來加密的數據,只能使用私鑰來解密;使用私鑰來加密的數據,只能使用公鑰來解密。

JWT 的生成 #

在生成 JWT 時,首先後端要先根據自己的商業邏輯,填上 header 和 payload 中的值。

所以像是在下方的 payload 中,我就填上了 {"sub":"123", "name":"古古"...} 的資訊,用來表示這個 JWT 中所裝的使用者資訊,是名叫「古古」的使用者資訊。

這裡大家可以根據自己的需求,在 payload 中填上你想要的值,不管你在 payload 中填上什麼值,對後續的 signature 生成都不會有任何影響(只不過在生成 signature 之前,一定要先確定好 payload 中的值要填什麼就是了,一旦 signature 生成之後,就不能改 payload 中的值了)。

而當寫好 header 和 payload 中的值之後,此時後端需要對 header + payload 的值 Hash 一下(此處使用的是 SHA-256 Hash 演算法),所以此時就會計算出 header + payload 被 Hash 過後的結果,即是 srtp3k

接著後端要使用「私鑰」,將這個 hash value srtp3k 加密,因此就會得到一個加密過後的結果 ap9fPl...

而當後端產生出 ap9fPl... 這個加密過後的結果之後,後端必須將這個值放在 JWT 中的 signature 的欄位中,因此最後後端傳送出去的 JWT 結果,就會在 signature 的部分填上 ap9fPl... 的加密過後的值。

所以到這裡,就完成了第一階段的「JWT 的生成」了,因此此時後端就可以將這個 JWT Token 傳送給前端,交由前端保存這個 JWT Token。

JWT 的驗證 #

而當前端後續拿著這個 JWT 來請求 api 時,我們身為後端,就必須要驗證這個 JWT 的正確性(即是是否有被駭客竄改過),而要驗證 JWT 的正確性,就是去檢查其中的 signature 的值就可以了。

舉例來說,當前端拿著剛剛的那一個 JWT 來請求 api 時,這時候我們身為後端,必須要先對當下的 header + payload 的區塊進行 Hash,先計算出 header + payload 的 Hash 值,因此此時就會得到一個 Hash 結果(即是下方區塊中的 srtp3k)。

這時候 JWT 中最精華的地方來了!!!當後端計算出 header + payload 的 Hash value 之後,後端只要使用「公鑰」將 signature 解密,然後比較一下「當初所計算出來 Hash 的值」和「現在所計算出來的 Hash 值」是否一樣,就可以知道此 JWT Token 是否有被竄改過了!

像是假設駭客偷偷修改 name 的值,將他從 古古 改為 我是駭客 的話,那麼當後端在收到這個 JWT 時,當下所計算出的 header + payload 的值就會是 Fy93HE而這個值就會和「使用公鑰解密 signature 所得到的原始 Hash 值 srty3k」不一樣,因此 JWT 就會驗證失敗,所以後端就會認為這個 JWT 中的內容有被偷偷修改過,因此就不相信裡面的數據。

所以總結來說的話,當後端收到 JWT 時,後端只要驗證一下 「當下 header + payload 所計算出來的 Hash 值」「使用公鑰解密 signature 所得到的值」 是否一樣,就可以知道這個 JWT 有沒有被偷偷修改了,這就是「數位簽名」的核心運行邏輯啦!!

所以大家以後就可以透過 JWT 的數位簽名的特性,將 JWT 直接儲存在前端中,後端就只要在收到 JWT 時驗證一下簽名就好,因此就不需要再儲存大量的數據在後端裡面了!讚!!

JWT 的數位簽名總結 #

所以總結上面的介紹,JWT 之所以可以透過 signature 的「數位簽名」來避免駭客的竄改,就是因為他使用了「非對稱加密」來實作數位簽名的機制。

而我們身為後端,在生成 JWT 時,需要使用「私鑰」來加密 header + payload 的數據,並將結果放在 signature 中。

並且在驗證前端傳過來的 JWT 時,需要使用「公鑰」來解密 signature 得到原始值,並且比較他和「當下 header + payload 所計算出來的 Hash 值」是否一樣,如果一樣的話,才表示 JWT 驗證成功,裡面的數據沒有被駭客所竄改,因此可以相信裡面的數據。

因此大家就可以透過這個步驟,在你的後端程式中實作 JWT 的相關程式了!

補充:本文是擷取自我開設的線上課程 「資安一把罩!Spring Security 零基礎入門」 的內容,如果你想了解更多的資安內容、以及如何應用 Spring Security,歡迎參考課程簡介 (輸入折扣碼「HH202501KU」即可享 85 折優惠)。

結語 #

這篇文章我們介紹了 JWT 的「數位簽名」的核心運作邏輯是什麼,數位簽名可以說是 JWT 中最重要的特性,就是因為有了數位簽名,才使得我們可以將 JWT 儲存在前端 Client 中,打破了以往只能將數據儲存在後端的設計方式,可以說是超級厲害的發明!!

如果你對後端技術有興趣的話,也歡迎免費訂閱 《古古的後端筆記》電子報 ,每週二為你送上一篇後端技術分享,那我們就下一篇文章見啦!

本文為 JWT 系列文的最終章,如果你想回顧前面的介紹,也可以參考前面的文章:

  1. Session 和 JWT 的差別在哪裡?
  2. 密碼學中的 Encode、Encrypt、Hash 的差別在哪裡?
  3. JWT 是什麼?一次搞懂 JWT 的組成和運作原理
  4. JWT 是如何實作「數位簽名」的?揭秘 signature 的面紗 (本文)

免費訂閱《古古的後端筆記》電子報

每週二學習後端技術,和 2700 人一起變強💪