1
votes

I think this question is not a dupe, so I will try to explain my situation.

I'm testing JWT, more specifically JOSE-JWT lib from Github, and well, I'm having troubles.

I'm generating a private-public key pair and sending to the client the public key, using PHP and phpseclib. Everything is correct as you can see there. My client is receiving the JSON and converting it to a object and extracting it to a string using JSON.NET.

I'm using BouncyCastle and an answer from Stackoverflow with a little modifications to read directly from a string instead from a File.

        public static RSACryptoServiceProvider GetRSAProviderFromPemFile(string pemfile)
        {
            return GetRSAProviderFromPemString(File.ReadAllText(pemfile).Trim());
        }

        public static RSACryptoServiceProvider GetRSAProviderFromPemString(string pemstr)
        {
            bool isPrivateKeyFile = true;

            if (pemstr.StartsWith(pempubheader) && pemstr.EndsWith(pempubfooter))
                isPrivateKeyFile = false;

            byte[] pemkey;
            if (isPrivateKeyFile)
                pemkey = DecodeOpenSSLPrivateKey(pemstr);
            else
                pemkey = DecodeOpenSSLPublicKey(pemstr);

            if (pemkey == null)
                return null;

            if (isPrivateKeyFile)
                return DecodeRSAPrivateKey(pemkey);
            else
                return DecodeX509PublicKey(pemkey);
        }

And both of them are giving me problems, with the answer and using docs from Jose repo:

            var payload1 = new Dictionary<string, object>()
            {
                { "sub", "[email protected]" },
                { "exp", 1300819380 }
            };

            Console.WriteLine("Jose says: {0}", JWT.Encode(payload1, pubkey, JwsAlgorithm.RS256));

Exception:

...

English equivalent: http://unlocalize.com/es/74799_Keyset-does-not-exist.html

And with Bouncy Castle:

            var claims = new List<Claim>();
            claims.Add(new Claim("claim1", "value1"));
            claims.Add(new Claim("claim2", "value2"));
            claims.Add(new Claim("claim3", "value3"));

            Console.WriteLine("Bouncy Castle says: {0}", Helpers.CreateToken(claims, pubkeyStr));

Exception:

...

CreateToken method extracted from here: https://stackoverflow.com/a/44857593/3286975

I did a little modification to this method:

    public static string CreateToken(List<Claim> claims, string privateRsaKey)
    {
        RSAParameters rsaParams;
        using (var tr = new StringReader(privateRsaKey))
        {
            var pemReader = new PemReader(tr);
            var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
            if (keyPair == null)
            {
                throw new Exception("Could not read RSA private key");
            }
            //var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters;
            rsaParams = DotNetUtilities.ToRSAParameters(keyPair.Public as RsaKeyParameters); //DotNetUtilities.ToRSAParameters(privateRsaParams);
        }
        using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
        {
            rsa.ImportParameters(rsaParams);
            Dictionary<string, object> payload = claims.ToDictionary(k => k.Type, v => (object)v.Value);
            return Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);
        }
    }

In both cases is like the encrypter methods are looking for the private key (in the client client????)... So, My question is why this examples are using private keys in the client-side, if the Wikipedia says this:

...

Source: https://en.wikipedia.org/wiki/Public-key_cryptography

And in several cases I found what I think is right:

https://connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-rsa-encryption

In this Java example, this uses public key to encrypt data, not private one.

I don't know why C# examples are using private keys in the client-side, this is ilogical, can somebody explain me why, and how can I solve this problems?

1

1 Answers

1
votes

I have found an answer for one of the two problems I have, and is that I haven't readed completely the JOSE-JWT repo, it says:

var payload = new Dictionary<string, object>()
{
    { "sub", "[email protected]" },
    { "exp", 1300819380 }
};

var publicKey=... //Load it from there you need

string token = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM);

I have realized tha Bouncy Castle is only a API to manipulate public-private keys, the encryptation-decrypting work is done by JOSE-JWT. So, my question is solved.