c#如何验证签名JWT?

c#如何验证签名JWT?,c#,jwt,signature,C#,Jwt,Signature,我有一个令牌,一个包含公钥的文件,我想验证签名。 我试图验证签名是否正确 但是,decodedCrypto和decodedSignature不匹配 这是我的密码: public static string Decode(string token, string key, bool verify) { var parts = token.Split('.'); var header = parts[0]; var payload = part

我有一个令牌,一个包含公钥的文件,我想验证签名。 我试图验证签名是否正确

但是,decodedCrypto和decodedSignature不匹配

这是我的密码:

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();
    }
我确信令牌的签名是有效的。我试着在上验证,结果显示签名已验证。 所以问题是编码、解码的算法

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


使用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;
}

请注意,我还没有测试它,但我们在其中一个项目中使用了类似的实现

byte[]crypto=Base64UrlDecode(部分[2])

在这一行中,您是对
JWT
令牌的签名部分进行base64解码,但我知道该部分不是base64编码的。请尝试此代码。(我已注释掉不必要的行)


我终于从我的同事那里得到了一个解决办法

对于有相同问题的用户,请尝试我的代码:

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();
}

它对我有用。算法是RS256。

我知道这是一个旧线程,但我可以建议您使用
而不是自己编写。它有一些好的文档可以开始使用。我使用它没有任何问题。

这里的“BinarySecretSecurityToken”是什么?无参考资料here@ANguyen:它是
IdentityModel
library.System.IdentityModel是.NET Framework的一部分,System.IdentityModel.Tokens.Jwt u可以通过NuGet获取。如果您可以将密钥转换为证书或已经拥有证书,则可以将IssuerSigningKey与X509SecurityKey一起使用。computedJwtSignature返回“{�3.�R4p/�����G�o����1.�G��#�我的算法是rs256这行返回什么?(请输入值)
HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes,bytesToSign)
据我所知,RS256应该同时获得用于计算哈希的公钥和私钥,但您只提供了一个。我只需要一个公钥进行验证。我尝试了,它返回signnature verified。您只在jwt.io网站中放置了公钥?正如我看到的,那里需要公钥/私钥。最简单的答案是@Th在另一个线程中报告的omas@KarthickJayaraman我提到了上面的参考,但它不起作用。你不仔细看这个问题吗?这对我来说很好,非常感谢。注意:RSACryptServiceProvider和SHA256是可处置的。有没有类似于RS256的PS256实现?或者我必须更改哈希算法来解决这个问题吗?我不知道sh要传递私钥,只有上面提到的公钥..Java和Python有一些库,它们允许您只需传递算法和公钥就可以动态地完成这项工作。我对缺少.NET land的远程接近等价物感到疯狂…什么是“Base64UrlDecode”?我收到此错误:当前文件中不存在名称“Base64UrlDecode”context@NagarajAlagusudaram是否添加了引用?此库RS256实现仍然不起作用,因为它需要私钥来验证令牌签名
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();
}