JWT令牌的秘密轮换
當您使用JSON Web令牌 ( JWT )或需要對有效載荷信息進行簽名或加密的任何其他令牌技術時,設置令牌的到期日期很重要,因此,如果令牌到期,則可以假定這可能被視為安全漏洞,您拒絕使用此令牌進行任何通信,或者您決定通過使用新的到期日期更新令牌來啟用該令牌。
但是使用某種類型的秘密輪換算法也很重要,因此用于簽名或加密令牌的秘密會定期更新,因此,如果該秘密受到威脅,則此密鑰泄漏的令牌會更少。 同樣,您也可以減少機密被破壞的可能性。
有幾種策略可以實現這一目標,但是在這篇文章中,我將解釋我如何在幾年前開發的一個項目中實施秘密輪換
具有HMAC算法的JWT令牌。
我將展示如何在Java中創建JWT令牌。
try {Algorithm algorithm = Algorithm.HMAC256("secret");String token = JWT.create().withIssuer("auth0").sign(algorithm);} catch (UnsupportedEncodingException exception){//UTF-8 encoding not supported } catch (JWTCreationException exception){//Invalid Signing configuration / Couldn't convert Claims. }請注意,這里您需要做的是創建一個算法對象設置HMAC算法,并設置用于簽署和驗證實例的密鑰。
因此,我們需要每X分鐘旋轉一次該算法實例,因此破解密碼的機率以及破解的密碼仍然有效的機率變得非常低。
那么如何旋轉秘密呢? 好吧,通過一個非常簡單的算法,每個人(即使您不是加密專家)也可以理解。 只是在浪費時間。
因此,要生成秘密,您需要一個字符串,在上一個示例中,它是秘密字符串,當然,它并不是那么安全,因此我們的想法是通過根(我們稱為“大爆炸”部分)來構成此秘密字符串+兼職。 總之,秘密是<bigbang> + <timeInMilliseconds>
Bing bang部分沒有任何奧秘,它只是靜態部分,例如my_super_secret 。
有趣的部分是時間部分。 假設您想每秒更新一次秘密。 您只需要這樣做:
long t = System.currentTimeMillis();System.out.println(t); System.out.println((t/1000)*1000);TimeUnit.MILLISECONDS.sleep(50);t = System.currentTimeMillis(); System.out.println((t/1000)*1000);我只是將0設置為毫秒部分,所以如果運行此命令,我將得到類似以下內容:
1515091335543 1515091335500 1515091335500請注意,盡管在第二和第三次打印之間已經過了50毫秒,但時間部分是完全相同的。 在同一秒內將是相同的。
當然,這是一個極端的示例,其中秘密每秒鐘更改一次,但其想法是您刪除要忽略的部分時間,并用0填充。 因此,首先,您要除以時間,然后再乘以相同的數字。
例如,假設您想每10分鐘旋轉一次秘密,您只需要除以600000就可以了。
這種方法有兩個問題可以解決,盡管其中一個并不是很大的問題。
第一個是因為如果您想每分鐘更改一次機密,則您要截斷時間,例如,第一次計算是在一分鐘的中間進行的,因此對于這種初始情況,輪換將在30秒后發生,并且不是1分鐘。 這不是一個大問題,在我們的項目中,我們沒有做任何修復。
第二個是在秘密輪換之前簽署的令牌所發生的情況,它們仍然有效,您還需要能夠驗證它們,而不是使用新的秘密,而是使用先前的一個。
為了解決這個問題,我們要做的是創建一個有效窗口,其中還保留了先前的有效機密。 因此,當系統收到令牌時,將使用當前機密驗證該令牌,如果該令牌通過,則我們可以進行其他任何檢查并使用它,如果未通過,則令牌將由先前的機密驗證。 如果通過,則重新創建令牌并使用新的秘密對其進行簽名;如果未通過,則顯然此令牌無效,必須拒絕。
要為JWT創建算法對象,您只需執行以下操作:
long currentTime = System.currentTimeMillis();try {return Algorithm.HMAC256("my_big_bang" + (currentTime/60000)*60000); } catch (UnsupportedEncodingException e) {throw new IllegalArgumentException(e); }我真正喜歡這種解決方案的地方是:
- 它很干凈,不需要系統上的其他元素。
- 不需要異步運行的觸發線程來更新密碼。
- 它確實性能出色,您無需訪問外部系統。
- 測試服務真的很容易。
- 驗證過程負責旋轉機密。
- 這確實很容易擴展,實際上,您無需執行任何操作,可以添加越來越多的同一服務實例,并且所有實例都將同時旋轉秘密,并且所有實例都將使用相同的秘密,因此輪換過程實際上是無狀態的,您可以按比例放大或縮小實例,所有實例將繼續能夠驗證其他實例簽名的令牌。
但是當然有一些缺點:
- 您仍然需要以安全的方式向每個服務共享機密的一部分(大爆炸部分)。 也許使用Kubernetes機密,Hashicorp的Vault,或者如果您不使用微服務,則可以將文件復制到具體位置,并在服務啟動和運行時閱讀大爆炸部分,然后將其刪除。
- 如果您的物理服務器位于不同的時區,則使用此方法可能會遇到更多問題。 另外,您需要使服務器或多或少同步。 由于您要存儲以前的令牌和當前令牌,因此不必在同一秒內同步它們,并且幾秒鐘的延遲仍然可能沒有問題。
因此,我們已經看到了一種非常簡單的秘密輪換方式,可以使令牌更安全。 當然,還有其他方法可以做到這一點。 在本文中,我只是解釋了我是如何在三年前開發的整體應用程序中做到這一點的,它確實運行良好。
我們不斷學習,
亞歷克斯
翻譯自: https://www.javacodegeeks.com/2018/01/secret-rotation-jwt-tokens.html
總結
以上是生活随笔為你收集整理的JWT令牌的秘密轮换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 9:欢迎来到Module Wo
- 下一篇: WIN7下建行捷德U盾支付完美解决!(白