【问题标题】:C# How to verify signature on JWT token?C#如何验证JWT令牌上的签名?
【发布时间】:2016-12-08 01:55:02
【问题描述】:

我正在尝试了解如何使用 .NET Framework 验证 JWT 令牌的签名。我正在使用在 https://jwt.io/ 找到的令牌。

如果我了解这应该如何工作,我可以使用 HMACSHA256 散列算法和前两个令牌和一个秘密值来获取令牌的最后一部分。如果匹配,则签名有效。

https://jwt.io/ 页面上的示例显示了通过以下方式计算哈希:

HMACSHA256(
        base64UrlEncode(header) + "." +
        base64UrlEncode(payload), secret
)

不幸的是,.NET Framework 中的 HMACSHA256 对象没有这样的方法。您必须传入一个 byte[] 或一个流。也没有秘密的论据。但是,有一个构造函数将 byte[] 作为键。为了解决这个问题,我一直在将“秘密”这个词转换为一个字节[],用它来实例化 HMACSHA256 对象。

然后我将 base64 编码的 header.payload 字符串转换为 byte[] 并将其传递给 HMACSHA256 对象的 ComputeHash 方法。

这是我遇到问题的地方。 ComputeHash 的输出是一个字节数组。无论我如何尝试将此 byte[] 转换回字符串,它都不会与签名匹配。我不明白我哪里错了。令牌的签名部分是哈希值还是 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[] 

【问题讨论】:

    标签: c# hash json-web-token


    【解决方案1】:

    令牌的签名部分是哈希值还是 base64 编码 哈希值?

    这是一个 Base64 Url 编码的哈希值。您需要对计算的哈希值进行编码以验证相等性。

    查看以下单元测试,了解您的验证出错的地方。

    [TestClass]
    public class JwtUnitTest {
        [TestMethod]
        public void VerifySignature() {
    
            string jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
            string[] parts = jwt.Split(".".ToCharArray());
            var header = parts[0];
            var payload = parts[1];
            var signature = parts[2];//Base64UrlEncoded signature from the token
    
            byte[] bytesToSign = getBytes(string.Join(".", header, payload));
    
            byte[] secret = getBytes("secret");
    
            var alg = new HMACSHA256(secret);
            var hash = alg.ComputeHash(bytesToSign);
    
            var computedSignature = Base64UrlEncode(hash);
    
            Assert.AreEqual(signature, computedSignature);
        }
    
        private static byte[] getBytes(string value) {
            return Encoding.UTF8.GetBytes(value);
        }
    
        // from JWT spec
        private static string Base64UrlEncode(byte[] input) {
            var output = Convert.ToBase64String(input);
            output = output.Split('=')[0]; // Remove any trailing '='s
            output = output.Replace('+', '-'); // 62nd char of encoding
            output = output.Replace('/', '_'); // 63rd char of encoding
            return output;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-11-01
      • 2018-05-29
      • 2019-06-14
      • 2016-06-10
      • 2018-11-25
      • 2018-09-30
      • 2017-09-18
      • 2020-05-11
      • 1970-01-01
      相关资源
      最近更新 更多