我想了解如何使用.NET Framework驗證JWT令牌的簽名。我正在使用在https://jwt.io/找到的令牌。C#如何驗證JWT令牌上的簽名?
如果我明白這應該如何工作,我可以使用HMACSHA256哈希算法與前兩個令牌和一個祕密值來獲取令牌的最後部分。如果匹配,那麼簽名是有效的。
在https://jwt.io/頁顯示計算散列以下述方式的例子:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload), secret
)
不幸的是在.NET Framework的HMACSHA256對象沒有這樣的方法。您必須傳入一個字節[]或流。也不存在任何祕密。但是,有一個構造函數將字節[]作爲鍵。爲了解決這個問題,我一直在將「secret」這個詞轉換成一個byte []來實例化HMACSHA256對象。
然後,我將base64編碼的header.payload字符串轉換爲byte [],並將其傳遞給HMACSHA256
對象的ComputeHash
方法。
這裏是我遇到問題的地方。 ComputeHash
的輸出是一個字節數組。無論我如何嘗試將此字節[]轉換回字符串,它都不會匹配簽名。我不明白我出錯的地方。令牌的簽名部分是散列值還是base64編碼的散列值?
這裏是我的代碼:
string jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
string[] parts = jwt.Split(".".ToCharArray());
string headerDotPayload = string.Format("{0}.{1}", parts[0], parts[1]);
string signature = parts[2];
byte[] secret = System.Text.UTF8Encoding.UTF8.GetBytes("secret");
byte[] input = System.Text.UTF8Encoding.UTF8.GetBytes(headerDotPayload);
var alg = new HMACSHA256(secret);
byte[] hash = alg.ComputeHash(input);
//Attempting to verify
StringBuilder result = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
result.Append(hash[i].ToString("x2"));
}
string verify1 = result.ToString(); //Does not match signature
string verify2 = System.Text.UTF8Encoding.UTF8.GetString(hash); //Does not match signature
byte[] verify3 = System.Text.UTF8Encoding.UTF8.GetBytes(signature); //Does not match value in the hash byte[]