.NET:RS256 签名的 JWT 中的签名无效

Posted

技术标签:

【中文标题】.NET:RS256 签名的 JWT 中的签名无效【英文标题】:.NET: Invalid Signature in RS256 signed JWT 【发布时间】:2018-05-08 10:06:19 【问题描述】:

我需要创建一个 Json Web 令牌并使用非对称签名 RS256 算法。用于签名的密钥应取自 X509 证书并由接收方使用公钥进行验证。

使用 HMAC 和密码可以正常工作,但是使用代码创建的 JWT 下面列出,在https://jwt.io 处不断产生“无效签名”

我在这里浏览了很多帖子,发现了很多有用的提示,但没有一个能解决我的问题。可能我理解上还是有问题。

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

        // 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";
    

【问题讨论】:

抱歉,跳过了第一行代码 公共静态字符串创建(字符串用户名) 您可以点击编辑(就在您的问题下方)来编辑您的问题并添加缺失的行。之后您还可以删除您的 cmets。 【参考方案1】:

您在构建令牌时遇到了一些错误:

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

需要base64url编码,不是base64。将Convert.ToBase64String(bytes) 更改为


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

static readonly char[] padding = '=' ; 见this

【讨论】:

以上是关于.NET:RS256 签名的 JWT 中的签名无效的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JWT.IO 网站创建 RS256 JWT?

无法验证 RS256 签名的 JWT

django rest框架使用jwt RS256解码签名错误

在 Knock (rails) 中验证用 RS256 签名的 JWT 令牌

VBA:如何根据 VBA 中的私钥生成带有 RS256 的签名?

无效签名 - Google JWT API