.NET Frameworkを使用してJWTトークンの署名を検証する方法を理解しようとしています。私はhttps://jwt.io/にあるトークンを使用しています。C#JWTトークンの署名を確認する方法は?
これがどのように動作するのか分かっていれば、最初の2つのトークンと秘密の値を持つHMACSHA256ハッシュアルゴリズムを使用して、トークンの最後の部分を取得できます。一致した場合、署名は有効です。
https://jwt.io/ページの例は、以下のようにハッシュを計算示す:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload), secret
)
残念ながら、.NET FrameworkのHMACSHA256オブジェクトはそのような方法を持っていません。バイト[]またはストリームを渡す必要があります。秘密の議論もありません。しかし、byte []をキーとして取り込むコンストラクタがあります。これを回避するために、私は「秘密」という単語を、それを使ってHMACSHA256オブジェクトをインスタンス化するbyte []に変換しています。
次に、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[]