.NET:RS256签名的JWT中的无效签名 [英] .NET: Invalid Signature in RS256 signed JWT

查看:570
本文介绍了.NET:RS256签名的JWT中的无效签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个Json Web令牌并使用不对称符号对其进行签名 RS256算法.用于签名的密钥应取自 X509证书,并由接收者使用公钥进行验证.

I need to create a Json Web Token and signing it with an asymetric RS256 algorithm. The key used for signing should be taken from a X509 certificate and be validated by the receiver using the public key.

使用HMAC和密码可以正常工作,但是使用代码创建的JWT 下面列出的内容会在 https://jwt.io

Using HMAC and password works fine, but the JWT created with the code listed below, produces constantlyI an "Invalid signature" at https://jwt.io

我在这里浏览了很多帖子,发现了很多有用的提示,但是都没有解决我的问题.也许我在理解上仍然有问题.

I got through many postings here, found a lot of usefull hints but none of them solved my problem. Maybe I've still a problem in understanding.

我知道,软件包System.IdentityModel.Tokens.Jwt实际上提供了我所需的一切, 但我想了解自己在做错什么.

I know, the package System.IdentityModel.Tokens.Jwt actually provides all I need, but I want to understand what I'm doing wrong.

        // Get certificate from local store
        X509Store store = new X509Store(StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2 x509Cert = (from X509Certificate2 c in store.Certificates where c.SubjectName.Name == $"CN={userName}" select c).First();

        if (x509Cert == null)
        {
            return string.Empty;
        }

        // Setup header
        var header = new { typ = "JWT", alg = "RS256" };
        var headerEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header)));

        // Setup payload/claims
        var payload = new
        {
            unique_name = $"{userName}@myCompany.com",
            role = "User",
            iss = x509Cert.Issuer,
            aud = "https://dev.myCompany.com",
            nbf = (Int32)DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds,
            exp = (Int32)DateTime.Now.AddMinutes(5).Subtract(new DateTime(1970, 1, 1)).TotalSeconds,
            jti = Guid.NewGuid(),
            x5t = x509Cert.Thumbprint
        };
        var payloadEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload)));

        // ... and sign, using the RSACertificateExtensions
        var rsa = x509Cert.GetRSAPrivateKey();
        var signed = rsa.SignData(Encoding.UTF8.GetBytes($"{headerEncoded}.{payloadEncoded}"), 
                                     HashAlgorithmName.SHA256, 
                                     RSASignaturePadding.Pss);

        var signatureEncoded = Convert.ToBase64String(signed);

        return $"{headerEncoded}.{payloadEncoded}.{signatureEncoded}";
    }

推荐答案

构建令牌时会出错:

  • 对于RS256,使用RSASignaturePadding.Pkcs1而不是RSASignaturePadding.Pss

需要base64url编码,而不是base64.用

It is needed base64url encoding, not base64. Change Convert.ToBase64String(bytes) with

 Convert.ToBase64String(bytes)
       .TrimEnd(padding).Replace('+', '-').Replace('/', '_');

使用static readonly char[] padding = { '=' };参见

这篇关于.NET:RS256签名的JWT中的无效签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆