.NET: Invalid Signature in RS256 signed JWT

别来无恙 提交于 2020-01-05 07:18:27

问题


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.

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.

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

回答1:


You have some errors building the token:

  • For RS256 use RSASignaturePadding.Pkcs1 not RSASignaturePadding.Pss

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


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

With static readonly char[] padding = { '=' }; See this



来源:https://stackoverflow.com/questions/47472465/net-invalid-signature-in-rs256-signed-jwt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!