Using Azure key-vault certificate for signing and verifying signed data
-
Introduction
At times when developing applications, we may come across scenarios where the data sent to a server via http has to be verified to check whether the data has been manipulated when traveling across the wire to the server. This verification is required to check for the authenticity of the data.
Today, let us discuss about how to digitally sign data, often referred as DigitalSignature, and verify the DigitalSignature and data sent to a server using azure key-vault certificate and C#. This DigitalSignature can be then sent along with the data as a part of the request header or by other means according to the usage.
Keywords
-
DigitalSignature – the data that’s digitally signed using a certificate
-
Data – the message or document sent to a server via http post request most often
-
Azure key-vault – a service provider in the cloud that provides a secure store for secrets.
Read more on azure key-vault at
https://azure.microsoft.com/en-us/services/key-vault/
Pre-requisites
• Have some basic understanding about azure
• Understanding of asymmetric cryptography
• Working knowledge in C#
• Azure subscription1. Setting up an Azure key-vault certificate
In this section lets us create a certificate on azure key vault.
-
First, create an azure key-vault resource, if you already have a Key-Vault resource you can use it.
-
In the left menu, under the “Settings” section select “Certificates”.
![0_1622449386123_1.jpg](Uploading 100%)
-
Once navigated to the certificate section, click on “Generate/Import”
-
The above action will take you to the page where it allows you to create or import a new certificate. Since we are creating a new certificate, select “Generate” from the “Method of Certificate Create” dropdown, and fill in the fields. Most of them can be left to the defaults selected. DON’T click on Create yet.
![0_1622448359734_9411b91e-e382-4412-802b-6ad6f3555987-image.png](Uploading 100%)
- Once you come to the bottom of the form, click for the highlighted section as shown in above image. This will open a side bar to configure the policies. Please make sure that you select the required policies from the drop down as you cannot change them once the certificate is created. As for this certificate, we need the “Digital Signature” selected under “X.509 Key Usage Flags”.
![0_1622448556832_d6bbe9bb-f290-4adf-82a3-14b466fc6648-image.png](Uploading 100%)
![0_1622448563570_ffa79f1b-4026-4ff6-81d8-67454f89fe46-image.png](Uploading 100%)
In addition, please check all the flags in order to avoid problems from other features that may be required. You can also select the “Key Size” according to your need.
- Finally, click “Ok”, and click on create button. This will create the certificate and it will take few minutes for the certificate to enable.
![0_1622448585292_80c991c5-1a01-47c4-ba99-b0d303ca86c6-image.png](Uploading 100%)
2. Configuring Access to Azure Key-Vault Using Active Directory
In order to use the certificate for signing and verifying the signed data from code we need to be authenticated in order to access the certificate.
In this section let’s understand how to configure an Active Directory app to access the certificate from code.• Create an Active Directory app
-
Go to “Azure Active Directory” in the azure portal menu.
-
Select “App Registrations”, then click on “New registration” to add a new application providing a meaningful name.
![0_1622448624789_5516e0a8-7383-406f-8d18-dfb049b4cf0f-image.png](Uploading 100%)
- Once the app has been created it will appear in the list as below. Copy the Application (Client) ID as it is required in the future.
![0_1622448639712_822d12d4-abc5-4b40-a2d1-78c3cd02fc65-image.png](Uploading 100%)
- Now navigate into the application details by clicking in the name of the app to generate a client secret. Click on the “Certificates and secrets” and then click on “+ New Client Secret”
![0_1622448670997_1de3862e-5bff-4753-a08e-d3754b7e854a-image.png](Uploading 100%)
Once the client secret is generated copy and have it pasted in a secure place along with the Application (Client) Id
- Now navigate back to the azure key-vault resource that you created and click on “Access Policies”, then click on “Add Access Policy”.
![0_1622448750087_659f6c15-3c29-4d71-a33c-4a01eca1d434-image.png](Uploading 100%)
This will take you to the “Add access policy” page to setup access policies.
Now let’s configure policies.
• From the “Configure from template (optional)”, select the highlighted ones according preference.
![0_1622448785376_cac15afc-f9bd-4f08-87d0-a67a09d14bdc-image.png](Uploading 100%)
• Similarly select the “key permissions”, “secret permissions” and “certificate permissions” accordingly. As in this case it has to be “certificate permissions”.
• From the “Select Principal”, select the name of the Application that we registered with Active Directory. In case the app doesn’t appear in the list, search the name of the application that was used to register with Active Directory.![0_1622448800282_726bf2d6-672f-42ba-ae68-2a8cefd5db43-image.png](Uploading 100%)
In this case the name of my Active Directory Application is “CFS-key-vault’. Select the proper application and click on “Add”.
Now this application’s Client-Id and Client-Secret can be used to access the certificate, sign and verify data from code.
3. Connecting to Key-Vault From Code
In this section let’s connect to the azure key-vault using the KeyVaultClient which is in the namespace Microsoft.Azure.KeyVault. The name space is also available as a nuget package at [https://www.nuget.org/packages/Microsoft.Azure.KeyVault/](link url)Let’s look at the code
public KeyVaultClient GetAzureKeyVaultClientInstance() { var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(AuthenticateClient)); return keyVaultClient; } private async Task<string> AuthenticateClient(string authority, string resource, string scope) { var clientCredential = new ClientCredential("<your active directory application (client) Id>", "<the client Secret of the active directory app>"); var authenticationContext = new AuthenticationContext(authority); var result = await authenticationContext.AcquireTokenAsync(resource, clientCredential); return result.AccessToken; }
• In the above code, the method GetAzureKeyVaultClientInstance(), returns an instance of a KeyVaultClient once the authentication is successful.
• The KeyVaultClient constructor takes in an instance of the KeyVaultClient.AuthenticationCallback() delegate as a constructor parameter which has a callback function AuthenticateClient.
• The private method AuthenticateClient() takes in three arguments as shown in the code.
• You must pass the active directory application client Id and client secret as parameters to the ClientCredential instance as constructor parameters in the private method AuthenticateClient().
• The rest of the code is self-explanatory.
• If the authentication is successful the GetAzureKeyVaultClientInstance() method will return an instance of a KeyVaultClient, else it will throw unauthorized exception.
• Now that we have an instance of the KeyVaultClient, we can use it to sign and verify signed data.4. Signing and Verifying Signed data using the certificate
In this section lets he how to sign and get the signed data verified using the certificate in azure key-vault.• Let us first sign data using the certificate.
Let’s walk through the code below
public async Task<ValueTuple<byte[], string, byte[]>> GetSignedResultAsync(string model) { try { var encodedToBytes = Encoding.UTF8.GetBytes(model); var digest = Hasher.GetSHA256Digest(encodedToBytes); using (var keyVaultClientInstance = azureKeyVaultClient.GetAzureKeyVaultClientInstance()) { var signedData = await keyVaultClientInstance .SignAsync(keyIdentifier: "<your azure key vault certificate key identifier>", algorithm: JsonWebKeySignatureAlgorithm.RS256, digest: digest); return (signedData.Result, signedData.Kid, digest); } } catch (Exception e) { throw new OperationFailedException("some error message"); } }
- The method GetSignedResultAsync() takes in string parameter which is a JSON serialized representation of the data intended to sign.
- The serialized JSON is the encoded using the Encoding which is in the namespace System.Text. Here in this example I have used UTF8, you can use other options as well.
- Then the encodedToByte variable is passed to a hashing function. In this case SHA256 which will return a hashed value which is referred to as a digest.
- Then in the using statement we can make use of the KeyVaultClient instance that was return after authorization to the azure key-vault. In the above code I have used a function to get an instance of the KeyVaultClient. Since the KeyVaultClient instance implements the IDisposable interface it is wrapped in a using statement.
- Now on the KeyVaultClient instance we can invoke the SignAsync() method on it.
The azure key vault key identifier is the identifier of the certificate. You can find the key identifier as shown below.
Go to you key vault resource. Click on “certificate” in the left blade, then navigate to a certificate you are interested in.
![0_1622448980758_84f66ed7-810d-475d-bb8a-ddf11b103a7d-image.png](Uploading 100%)
From here navigate into the certificate version.
![0_1622448994140_e9bfef56-465c-4e45-879d-f531f823ecb7-image.png](Uploading 100%)
![0_1622449001212_00cc5a9d-9864-4669-9f3c-c49bb1cda2b3-image.png](Uploading 100%)
- Now, scroll down to the bottom of the page to get the key identifier of the certificate
![0_1622449018301_35287089-e31e-4e92-a2da-17dbc26bce76-image.png](Uploading 100%)
• The green highlighted area provides key identifier. Copy the key-identifier and past it for the keyIdentifier argument of the SignAsync() of the KeyVaultClient instance.
- Now, pass the algorithm and digest as the second and third arguments of the SignAsync() method respectively.
- The SignAsync() will return a KeyOperationResult which has a property Result it. This Result is the DigitalSignature that was signed by the certificate in azure key-vault.
![0_1622449033942_668b83ae-76d0-47ac-9da9-5336ebe70ebe-image.png](Uploading 100%)
• Now we can verify the digital signature against the original model. Let’s see how.
Lets walk through the code snippet belowpublic async Task<bool> VerifySignedResultAsync(string algorithm, byte[] digest, byte[] signedResult) { using (var keyVaultClientInstance = azureKeyVaultClient.GetAzureKeyVaultClientInstance()) { var isVerified = await keyVaultClientInstance .VerifyAsync(keyIdentifier: "<your azure key vault certificate key identifier>", algorithm: algorithm, digest: digest, signature: signedResult); return isVerified; } }
• First, we need an instance of KeyVaultClient class. You can follow the steps explained above to get this done.
• VerifySignedResultAsync() takes in 3 arguments.- The first argument is the algorithm. Its mostly the same algorithm which is used to sign the data.
- The second argument is the digest. The digest is the same as explained above, which is the JSON serialized string hashed using SHA256.
- The third argument is the DigitalSignature or the signed result.
• The KeyVaultClient instance has a method VerifyAsync() which will take in the arguments passed to the VerifySignedResultAsync() method and the key identifier of the certificate. The VerifyAsync() will return a Boolean true if the signed data and the digest match, else will return false.
That’s it. Hope you have had a better understanding on how to sign and verify signed data and are able to apply to your application when needed.
Thanks. -
-
@root , why are the images not getting uploaded?
-
i'm checking . thanks for the reporting
-
image upload issue fixed
-
hello can you fix the images ? images are broken
-
@root will do when i have time