Search code examples
digital-signatureazure-keyvault

Create a signature using ES256


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.


Solution

  • 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
    }