In my recent project, we needed to generate JSON Web Key (JWK) containing the public key of an X509Certificate using RSA256 signing algorithm of 2048 key size.
Here is just a small piece of my discovery on how to extract the Modulus and Exponent of a public key for generating a JSON Web Key.
Create certificate in Azure Key Vault
We need a certificate to start with. The solution requires the certificate to be stored in Azure Key Vault. Creating one is a very straight forward process. Simply navigate to the Certificate section, and click on Generate/Import.
For demo purpose, I would just fill in the basic details, select PKCS#12 content type. Under Advanced Policy Configuration, select the RSA key type, and 2048 key size. Then, proceed to create the Certificate.
Generate JSON Web Key in C#
Now, we have a certificate to test with. In Visual Studio projects using either .NET Core 5.0 or Framework (version 4.7.2 at the time of writing), import the following NuGet packages:
Azure.Security.KeyVaults.Secret
Azure.Identity
Microsoft.IdentityModels.Tokens
Firstly, initiate connection to the Azure Key Vault, and retrieve the certificate content. I am using SecretClient instead of CertificateClient. You may use CertificateClient, however, it does not return the private key which, in this case, is fine as we don't need.
Then, initialise X509Certificate2 instance from the content, and extract the Modulus and Exponent of its public key to form the JSON Web Key.
//initialise the Secret client connection to Azure Key Vault.
var secretClient = new SecretClient(new Uri("https://ivsdev-mykeyvault.vault.azure.net/"), new DefaultAzureCredential());
//retrieve the certificate content to initialise the X509Certificate instance.
var secretValue = secretClient.GetSecret("MyFirstCertificate");
var certificateString = secretValue.Value.Value;
var certificate = new X509Certificate2(Convert.FromBase64String(certificateString));
//extract the RSA Public Key, and its parameters.
var publicKey = certificate.GetRSAPublicKey();
var param = publicKey.ExportParameters(false);
//extract and encode the Modulus and Exponent to Base64 string.
var modulus = Base64UrlEncoder.Encode(param.Modulus);
var exp = Base64UrlEncoder.Encode(param.Exponent);
//assign the parts to the JsonWebKey class.
var jsonwk = new JsonWebKey()
{
Kty = "RSA",
Use = "sig",
Alg = "RS256",
Kid = "some key id value",
N = modulus,
E = exp,
};
//or, simply use your own JSON model
var myjsonwk = new MyJsonWebKey()
{
kty = "RSA",
use = "sig",
alg = "RS256",
kid = "some key id value",
n = modulus,
e = exp,
};
Microsoft has a JsonWebKey model, however, its serialised string contains other components which are causing problems in the consuming party in my project. So, I ended up creating my own model to fit the purpose, and for a cleaner JSON string.
That's all for now.
Comments