jwt-dotnet / jwt

Jwt.Net, a JWT (JSON Web Token) implementation for .NET
Other
2.12k stars 462 forks source link

RSA256 does not work Says Invalid Algorithm name #418

Closed mdhruv1 closed 2 years ago

mdhruv1 commented 2 years ago

These are the steps I am following. I am trying to make a jwt token using RS256 having a public and private key Generate a pem file using openssl on mac then copy it

The code below I was able to get to work on hmac but not for RSA256. I get an error not a valid algotrithm for RS256.

If you can take a look at this code below and guide to do RS256 that will be awesome. The exact steps u used for generating a certificate.

   public Boolean createJWT_old(string model, string serial, string assetid, out string encodedJWT)
        {
            const string cIssuer = "Online JWT Builder";
            const int cTokenExpiryHrs = 1;
            const string cAudience = "www.bbbb.com"; // app://passlink
            const string cSubject = "injector@bbbb.com";

            var payload = new Dictionary<string, object>
            {
                { "iss"  , cIssuer},
                { "iat"  ,(long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds},
                { "exp"  ,(long)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds+ cTokenExpiryHrs * 3600)},
               // { "exp"  ,(DateTimeOffset.UtcNow.AddHours(cTokenExpiryHrs)).ToUnixTimeSeconds()},
               // { "exp"  ,(long)(DateTimeOffset.UtcNow.AddHours(cTokenExpiryHrs) -  new DateTime(1970, 1, 1)).TotalSeconds},
                { "aud" , cAudience},
                { "sub" , cSubject},
                { "model" , model},
                { "serial" , serial},
                { "asset" , assetid}
            };
            try
            {
                IJwtAlgorithm algorithm =
                    new HMACSHA256Algorithm();
                    //new RS256Algorithm()

                IJsonSerializer serializer = new JsonNetSerializer();
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

                encodedJWT = encoder.Encode(payload, this.encodeSecret);
                return true;
            }
            catch (Exception e)
            {
                encodedJWT = Constants.cErrCreateFailed;
                Console.Error.WriteLine(e.Message);
                return false;
            }
        }
abatishchev commented 2 years ago

Hi, happy to help. Can you please update your code with the exact way you construct the algorithm object and the cert you pass to its constructor.

mdhruv1 commented 2 years ago

To create the certs I used mac with the following commands:

openssl req -new -newkey rsa:512 -nodes -keyout CA_PrivateKey.key -out CA_SigningRequest.csr
choose country US
common name = passconnect
challenge pwd = password

openssl x509 -req -days 2000 -in CA_SigningRequest.csr -signkey CA_PrivateKey.key -out CA_Certificate.crt

openssl pkcs12 -export -out CA_Certificate.pfx -inkey CA_PrivateKey.key -in CA_Certificate.crt
password=password

This works in core net 3.0 . When I try to use this code in dot net framework 4.0 say invalid algorithm name,

   private static void testCertificates()
    {
        const string cIssuer = "Passlink";
        const int cTokenExpiryHrs = 1;
        const string cAudience = "www.bbbb.com"; // app://passlink
        const string cSubject = "info@bbbb.com";

        X509Certificate2 certificate = new X509Certificate2("CA_Certificate.pfx", "password");

        IJwtAlgorithm algorithm = new RS256Algorithm(certificate);

        IJsonSerializer serializer = new JsonNetSerializer();

        IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();

        IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

        var payload = new Dictionary<string, object>

{

{ "iss" , cIssuer},

{ "iat" ,(long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds},

{ "exp" ,(long)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds+ cTokenExpiryHrs * 3600)},

{ "aud" , cAudience},

{ "sub" , cSubject},

};
        var encodedJWT = encoder.Encode(payload, "");
        Console.WriteLine(encodedJWT);
    }
abatishchev commented 2 years ago

Perhaps you didn't mean to close it. Did you?

abatishchev commented 2 years ago

Make sure this code works with our error:

var certificate = ...
Debug.Assert(certificate.PublicKey is not null);
Debug.Assert(certificate.HasPrivateKey);

Also post full exception message and stack trace.

mdhruv1 commented 2 years ago

I did not close it. I will post the stack trace tomorrow

Dhruv

Sent from my iPad

On Jun 18, 2022, at 10:33 PM, Alexander Batishchev @.***> wrote:

 Perhaps you didn't mean to close it. Did you?

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you modified the open/close state.

mdhruv1 commented 2 years ago

I did a screen shot an this is the entire code here in  a text file.

The private key exists and so does the public key . The algorithm in certificate says "sha1RSA"  . I am getting invalid algorithm. Which algorithm should I be using.This works fine in dot net core 3.0. I am trying to use it on .net 4.0 I know it is old but have to use it for an embedded legacy device

----start using System; using System.Collections.Generic; using System.Linq; using System.Text; using JWT;

using JWT.Algorithms; using JWT.Serializers;

namespace RSA {     class Program     {         static void Main(string[] args)         {

            testCertificates();         }         private static void testCertificates()

        {

            const string cIssuer = "pass";

            const int cTokenExpiryHrs = 1;

            const string cAudience = "www.bbbb.com"; // app://passlink

            const string cSubject = @.***";

            System.Security.Cryptography.X509Certificates.X509Certificate2 certificate = new System.Security.Cryptography.X509Certificates.X509Certificate2(@"C:\Users\test\Documents\Visual Studio 2015\Projects\WpfApplication1\WpfApplication1\bin\Debug\ext\CA_Certificate.pfx", "password");

            IJwtAlgorithm algorithm = new RS256Algorithm(certificate);

            IJsonSerializer serializer = new JsonNetSerializer();

            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();

            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

            var payload = new Dictionary<string, object>             {

            { "iss" , cIssuer},

            { "iat" ,(long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds},

            { "exp" ,(long)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds+ cTokenExpiryHrs * 3600)},

            { "aud" , cAudience},

            { "sub" , cSubject},

            };             try             {                 var encodedJWT = encoder.Encode(payload, "");                 System.Console.WriteLine(encodedJWT);             }             catch(Exception e)             {                 System.Console.WriteLine(e.Message);             }

            

        }     } }

--- end

This is the PFX . I

On Saturday, June 18, 2022 at 10:38:43 PM EDT, Alexander Batishchev ***@***.***> wrote:  

Make sure this code works with our error: var certificate = ... Debug.Assert(certificate.PublicKey is not null); Debug.Assert(certificate.HasPrivateKey); Also post full exception message and stack trace.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you modified the open/close state.Message ID: @.***>

mdhruv1 commented 2 years ago

I wonder what algorithm should I use if I repeat the steps and I get "sha512RSA" when I look at the certificate.m_signature.Algorithm.Friendlyname= "sha512RSA"

I am getting invalid algorithm when I use RS512:

 IJwtAlgorithm algorithm = new RS512Algorithm(certificate);

These are the steps I used to create the certificate

openssl req -x509 -nodes -sha512 -newkey rsa:2048 -keyout 512key.pem -out 512cert.pem -days 3650

openssl pkcs12 –export –in 512cert.pem –inkey 512key.pem –CSP “Microsoft Enhanced RSA and AES Cryptographic Provider” –out 512pfx.pfx

to do a p12 conversion

openssl pkcs12 -export -out 512Cert.p12 -in 512cert.pem -inkey 512key.pem
abatishchev commented 2 years ago

Hi! Sorry, still can't find the full exception stack trace. Please post it here so I could assist you better.

mdhruv1 commented 2 years ago

This is the stack trace:

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
   at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
   at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
   at JWT.Algorithms.RSAlgorithm.Sign(Byte[] bytesToSign)
   at JWT.JwtEncoder.Encode(IDictionary`2 extraHeaders, Object payload, Byte[] key)
   at RSA.Program.testCertificates() in c:\users\test\documents\visual studio 2015\Projects\RSA\RSA\Program.cs:line 108

Attached is the pfx I have used for the certificate.

mdhruv1 commented 2 years ago

This is the stack trace:

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
   at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
   at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
   at JWT.Algorithms.RSAlgorithm.Sign(Byte[] bytesToSign)
   at JWT.JwtEncoder.Encode(IDictionary`2 extraHeaders, Object payload, Byte[] key)
   at RSA.Program.testCertificates() in c:\users\test\documents\visual studio 2015\Projects\RSA\RSA\Program.cs:line 108

Attached is the pfx I have used for the certificate

This is certificate file I am using attached . I had emailed you the file

mdhruv1 commented 2 years ago

All I am trying to do is to use a RS256 certificate to encode and decode a JWT token. I am using .net 4.0 if you can help me with a work example that will be awesome.

abatishchev commented 2 years ago

I see, so the exception isn't from the library but from the PKI API of .NET. I think it's a mismatch between RSxyz and the certificate you've created and pass.

Please list the exceptions you're getting when using other algorithms.

mdhruv1 commented 2 years ago

getting when using other algorithms.

This code works when I use HMAC.

How can I specify for RS256 to use "sha1RSA" as the algorithm. That i not clear to me. That should solve the issue I think

abatishchev commented 2 years ago

HMAC is a symmetric (hashing) algorithm and doesn't use a certificate, hence works.

I meant try RS work a different number, which represents the length of the key. It should match the parameters you pass when create the underlying certificate.

abatishchev commented 2 years ago

Namely RS512.

mdhruv1 commented 2 years ago

So how does that work . Zipped the PFX file . The algortitm in certificate says SHA1RSA so what should i be using

CA.zip

I used the 512 instead of 256 still says invalid algorithm.

abatishchev commented 2 years ago

I'm not familiar with openssl.exe but I see you pass 512 so you should use RS512, I guess. Try to run on .NET 6 and .NET 4.6.2 to make sure it's not a lower framework version issue.

mdhruv1 commented 2 years ago

I have opened another issue . The example for RSA256 the var token = encoder.Encode(payload); It is missing parameters . If we can edit it and see that will be awesome

abatishchev commented 2 years ago

Thanks! I'll fix the documentation.

For the issue itself, I'd suggest to ask on Stack Overflow, there will be more experts in the area with experiencing for .NET 4.0, I don't have it, sorry.