1

I'm trying to create an instance of System.Security.Cryptography.RSA from a JSON Web Key Set (JWKS) that includes some RSA keys, but only includes their modulus (n), public exponent (e) and secret exponent (d), not the primes that were used during key generation (p and q).

This is the jwks that includes the private keys (test keys, of course): https://belgianmobileid.github.io/slate/private_jwks.json

Here's what I tried:

using System.Linq;
using System.Net;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;

class Program
{
    static void Main(string[] args)
    {
        var jwks = new WebClient().DownloadString("https://belgianmobileid.github.io/slate/private_jwks.json");
        var webKeySet = JsonWebKeySet.Create(jwks);

        // signing key has kid "s1"
        var signingkey = webKeySet.Keys.Single(key => key.KeyId == "s1");

        // throws System.Security.Cryptography.CryptographicException:
        // 'The specified RSA parameters are not valid; both Exponent and Modulus are required fields.'
        var rsa = RSA.Create(
            new RSAParameters
            {
                Modulus = Base64UrlEncoder.DecodeBytes(signingkey.N),
                Exponent = Base64UrlEncoder.DecodeBytes(signingkey.E),
                D = Base64UrlEncoder.DecodeBytes(signingkey.D),
                P = null, // unknown
                Q = null  // unknown
            });
    }
}

I'm certainly no cryptography expert, I'm just trying to parse the JWKS into something that I can use in code. Is this even possible without knowing p or q?

Steven Liekens
  • 13,266
  • 8
  • 59
  • 85

1 Answers1

1

p and q (as well as dp, dq and qi) are not mandatory to perform signature/encryption operations. But they drasticaly speed up the computation process (more than 10x faster).

You can recover these values from n, e and d.

You will also find a PHP implementation in this project.

If you have PHP 7.1 with GMP and JSON extensions installed, you can try the following command:

curl -OL https://github.com/web-token/jwt-app/raw/gh-pages/jose.phar
curl -OL https://github.com/web-token/jwt-app/raw/gh-pages/jose.phar.pubkey
chmod +x jose.phar

./jose.phar key:optimize '{"kty":"RSA","d":"FVSxl…96w"}'

For example, with the following key from the link you pointed out:

{"kty":"RSA","d":"FVSxlyJTtDwWxAkAIxexpZTaDd3EsiCTcjF9h5Ciu0fcZujvX7i-qC1Nhzxk5ScQ36j0vduDymsW4uTehJKmcIZAnw_oMtX9ikn85KiUGGVzoUu4TyaUGmoGmDGUIrqtKhXbhoFXmFrQrtMSjy-1V2J-I0nX7s-fqS3c2MPtmnPEMXkLpxHr2hStRiIQFIf3T7Dv4aX5-2o00JViEM-cXTQZJerkDjSgj7KhGP7EKnkTfV7sBAiuRnbtOFqrNNMjXpGWJQSPbof1_6oo3_R9Jw7TYTNMzIyXWDmpam_Zf_iPFltFRWTh9nUygCAvpnPXRgFkgJN2JuSY6oLrIG-HsQ","e":"AQAB","use":"sig","kid":"s1","alg":"RS256","n":"pJADu0nyhCrh9XIRTO42V6YQqAeNABGGo006hknHw86wYByjHMhpYYwHuxuyx44mO8iQIcJkh5NPlkcaDN90RH0JOxyEE1pES5C3LqntC0mAP6BWoqMhY8g4PT2EJyPjVYZcpaZw0VUp6E5kx847dbvhMe8KWy0geuCwrCgXVhWDRoIyV7r2k948zlmRJjbdjkNosYEFI43nicZ_jckTbs_8nzlxDQo8GtstdhR_oUbXyyBJM66SUA8KxWV6NG0zubNIYWxHIwlU938gdpTNfUMKm78f78iPyfuoPz2dTb6Z7OP7WZb06eRv41i_dS0Zh-sKKHrpUYXRf6VrOoU96w"}

The same key with primes will be:

{"kty":"RSA","d":"FVSxlyJTtDwWxAkAIxexpZTaDd3EsiCTcjF9h5Ciu0fcZujvX7i-qC1Nhzxk5ScQ36j0vduDymsW4uTehJKmcIZAnw_oMtX9ikn85KiUGGVzoUu4TyaUGmoGmDGUIrqtKhXbhoFXmFrQrtMSjy-1V2J-I0nX7s-fqS3c2MPtmnPEMXkLpxHr2hStRiIQFIf3T7Dv4aX5-2o00JViEM-cXTQZJerkDjSgj7KhGP7EKnkTfV7sBAiuRnbtOFqrNNMjXpGWJQSPbof1_6oo3_R9Jw7TYTNMzIyXWDmpam_Zf_iPFltFRWTh9nUygCAvpnPXRgFkgJN2JuSY6oLrIG-HsQ","e":"AQAB","use":"sig","kid":"s1","alg":"RS256","n":"pJADu0nyhCrh9XIRTO42V6YQqAeNABGGo006hknHw86wYByjHMhpYYwHuxuyx44mO8iQIcJkh5NPlkcaDN90RH0JOxyEE1pES5C3LqntC0mAP6BWoqMhY8g4PT2EJyPjVYZcpaZw0VUp6E5kx847dbvhMe8KWy0geuCwrCgXVhWDRoIyV7r2k948zlmRJjbdjkNosYEFI43nicZ_jckTbs_8nzlxDQo8GtstdhR_oUbXyyBJM66SUA8KxWV6NG0zubNIYWxHIwlU938gdpTNfUMKm78f78iPyfuoPz2dTb6Z7OP7WZb06eRv41i_dS0Zh-sKKHrpUYXRf6VrOoU96w","p":"yFRFPKiUCelQ2c-vfy_09Ckd3TnGWFExHoiG7lOoRDxIWZjHy5ApSZ1S5Hx8pLcmJltpn3ad5LcgVv1hHUmcfw4NuyY1mduC4HUNKb6sZWQZJKDss1mJFFmL3Yg026Sy-_cK2wp0AP2nMqZ3JT3Pm6PsLn6VqKFNqAZNbnp4wrM","q":"0ktANeYxLEB1uEDkSQgQ6pSppBnNMHishDZPjLNuy2AzfP5tP1sqsg0Xbyr1gtJX9mccz3BwpmQCNZiWWhmLepvERK1gEb97eEmqVK1RwbRU0_z4osZcxudZxhI3QdyTOXYfp3n0SuIb4W-MWy8X4yZsiRf7K1eCJm1THcSUU-k","dp":"XxhRvZewnnvY22xRPKkBOJ4EBS4Vz3rLPFlG4_9mUu3i0lVKEoGed8lsvfWyHWarf23JV98w2I9tlJ226fY1icKcFgjvTNf86pvl4bkXkRHRNagGdKS-A6D2WfT8Un9-T0lYJ95wbr_6DHsk99K9qH5J8VA5rtDTUj2bqCQPCy0","dq":"dzTM-0C3kxwfHwk53uRBopgO6cTueZGOSYv34Aw-u-6WgT5Ac2-cbj3ZkNzLOxM9ZaHhxP05_jgmwHb0k7JzTFdMFJorISRoOzGW6lUtSR6OD3URBERphx7R1uOwixccJbB-FROelWxC3bG74Fx7r_myAKylZlY-osXKHc-3PTE","qi":"s0SZ_zJImz6abac_i8XJmVBq8wa08NL1DHXTKJxaBJcQqUbQ6xIs5Hxxouezv8wWe8O4G4NDVwQHGZINVjwzLyjTK2J1FRvAzm1ei-PB9C9RdgnK4ELCIIuJizOFVgFiRf4rzsTtpPtX1tsihUIL3geYucng9UqYJpkj8AumqAY"}

Spomky-Labs
  • 15,473
  • 5
  • 40
  • 64
  • Thanks, I came across the same document and tried to implement it in C# but found that it was pretty buggy. I found another version of the algorithm that is shorter and works better here: https://www.di-mgt.com.au/rsa_factorize_n.html – Steven Liekens Oct 12 '18 at 15:11
  • I wrote this which gave me the same answer for (p, q) that you got https://gist.github.com/StevenLiekens/7e9d7c8914909d32edd7cc92c284a3d6 – Steven Liekens Oct 12 '18 at 15:12