c#如何验证签名JWT?

anh*_*v13 14 c# signature jwt

我有一个令牌,一个包含公钥的文件,我想验证签名.我试图基于验证签名.

但是,decodingCrypto和decodingSignature不匹配.

这是我的代码:

public static string Decode(string token, string key, bool verify)
    {
        var parts = token.Split('.');
        var header = parts[0];
        var payload = parts[1];
        byte[] crypto = Base64UrlDecode(parts[2]);

        var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
        var headerData = JObject.Parse(headerJson);
        var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
        var payloadData = JObject.Parse(payloadJson);

        if (verify)
        {
            var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload));
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var algorithm = (string)headerData["alg"];
            var signature = HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign);
            var decodedCrypto = Convert.ToBase64String(crypto);
            var decodedSignature = Convert.ToBase64String(signature);

            if (decodedCrypto != decodedSignature)
            {
                throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature));
            }
        }

        return payloadData.ToString();
    }
Run Code Online (Sandbox Code Playgroud)

我确定令牌的签名是有效的.我尝试在https://jwt.io/上验证,它显示Signature已验证.所以问题是编码,解码的算法.

有人能解决这个问题吗?算法是RS256

在此输入图像描述

anh*_*v13 13

我终于得到了同事的解决方案.

对于那些有同样问题的人,请尝试我的代码:

public static string Decode(string token, string key, bool verify = true)
{
    string[] parts = token.Split('.');
    string header = parts[0];
    string payload = parts[1];
    byte[] crypto = Base64UrlDecode(parts[2]);

    string headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
    JObject headerData = JObject.Parse(headerJson);

    string payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
    JObject payloadData = JObject.Parse(payloadJson);

    if (verify)
    {
        var keyBytes = Convert.FromBase64String(key); // your key here

        AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes);
        RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
        RSAParameters rsaParameters = new RSAParameters();
        rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
        rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.ImportParameters(rsaParameters);

        SHA256 sha256 = SHA256.Create();
        byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(parts[0] + '.' + parts[1]));

        RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
        rsaDeformatter.SetHashAlgorithm("SHA256");
        if (!rsaDeformatter.VerifySignature(hash, FromBase64Url(parts[2])))
            throw new ApplicationException(string.Format("Invalid signature"));
    }

    return payloadData.ToString();
}
Run Code Online (Sandbox Code Playgroud)

这个对我有用.算法是RS256.

  • 非常感谢。当心:RSACryptoServiceProvider和SHA256是一次性的 (2认同)

Hel*_*aon 6

怎么样使用JwtSecurityTokenHandler?它可能看起来像这样:

public bool ValidateToken(string token, byte[] secret)
{
    var tokenHandler = new JwtSecurityTokenHandler();

    var validationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningToken = new BinarySecretSecurityToken(secret)
    };

    SecurityToken validatedToken;
    try
    {
        tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
    }
    catch (Exception)
    {
       return false;
    }

    return validatedToken != null;
}
Run Code Online (Sandbox Code Playgroud)

请注意,我尚未测试过,但我们在其中一个项目中使用了类似的实现

  • 这里的“BinarySecretSecurityToken”是什么?这里没有参考 (2认同)

Cod*_*ute 6

我知道这是一个旧线程但我可以让recommended你使用这个库而不是自己写.它有一些很好的文档来开始.我没有任何问题使用它.