I am trying the sign operation using an EC Key that I've created in Azure Key Vault.
The process should be straight forward:
A post request like this
POST {vaultBaseUrl}/keys/{key-name}/{key-version}/sign?api-version=7.4
that will include a JSON string in the body of the request like this one:
{
"alg": "ES256",
"value": "eyJhbGciOiAiRVMyNTYifQ.eyJrZXlBIjoidmFsdWUxIiwia2V5QiI6InZhbHVlMiIsImtleUMiOiAidmFsdWUzIn0"
}
I'm encoding the value using C#:
using Microsoft.IdentityModel.Tokens;
string header = "{\"alg\": \"ES256\"}";
string payload = "{\"keyA\":\"value1\",\"keyB\":\"value2\",\"keyC\": \"value3\"}";
var abc = Base64UrlEncoder.Encode(header) + "." + Base64UrlEncoder.Encode(payload);
I get a 400 Bad Request with the following message
{
"error": {
"code": "BadParameter",
"message": "Content of 'value' is not base64url.\r\nProperty 'value' is required.\r\n"
}
}
I've removed the first part that includes the algorithm, and I kept only the payload part, because the algorithm it's passed in the body of the request and I assumed that it's not needed, and I've tried to use the following body instead:
{
"alg": "ES256",
"value": "eyJrZXlBIjoidmFsdWUxIiwia2V5QiI6InZhbHVlMiIsImtleUMiOiAidmFsdWUzIn0"
}
But I also get a 400 Bad Request with the following message
{
"error": {
"code": "BadParameter",
"message": "Invalid length of 'value': 50 bytes. ES256 requires 32 bytes, encoded with base64url."
}
}
Definitely I am not passing the correct value in the body of the request, but I cannot figure it out what am I doing wrong.
I found out what I did wrong. In the body of the request, the value parameter expects a digest, not the payload. This is what I did (using Samuel's answer):
string HashWithSHA256(string value)
{
using var hash = SHA256.Create();
var byteArray = hash.ComputeHash(Encoding.UTF8.GetBytes(value));
return Base64UrlEncoder.Encode(byteArray);
}
string digest = HashWithSHA256(payload);
Now the body in the request looks like this:
{
"alg":"ES256",
"value":"cIbyvtAdTF7CYYKAtSJX8UPGRwF20R4nry9Di1NTke4"
}
I've tried this, with several payloads, and I was able to obtain the signature and to verify it (using the verify REST API operation). The verify operation always returns:
{
"value": true
}