I am trying to generate a simple JWT, using ES256 using KMS. Everything looks fine to the naked eye. But I get "Invalid signature" when I test it through jwt.io. The code is quite simple:
public async Task<string> GenerateJwt(object payload)
{
var encodedHeader = Base64Encoder.EncodeBase64Url(JsonSerializer.Serialize(_header));
var encodedPayload = Base64Encoder.EncodeBase64Url(JsonSerializer.Serialize(payload));
var signatureData = Encoding.ASCII.GetBytes(encodedHeader + "." + encodedPayload);
var signature = await _signingService.Sign(signatureData);
var encodedSignature = Base64Encoder.ReplaceSpecialUrlCharacters(Convert.ToBase64String(signature));
return encodedHeader + "." + encodedPayload + "." + encodedSignature;
}
The SigningService
looks something like this:
public async Task<byte[]> Sign(byte[] signatureData)
{
using var memoryStream = new MemoryStream(signatureData, 0, signatureData.Length);
var signRequest = new SignRequest()
{
KeyId = _signingKeyId,
Message = memoryStream,
SigningAlgorithm = SigningAlgorithmSpec.ECDSA_SHA_256
};
SignResponse signResponse = await _keyManagementService.SignAsync(signRequest);
return signResponse.Signature.ToArray();
}
_keyManagementService
is an IAmazonKeyManagementService
from AWSSDK.KeyManagementService 3.5.2.6
In KMS the key is set up like this:
- Key Spec: ECC_NIST_P256
- Key Usage: Sign and verify
- Signing algorithms: ECDSA_SHA_256
Public key in KMS (using localstack)
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEj7Cy/Gbx3jnuPdanuBSjuUmdnr7tQ/BcOytDlFoHWdNA1scc6RwNwqnNbmRE0BmwnlFNDVGxWU5oycTig8p0KQ==
Example on generated output
eyJhbGciOiJFUzI1NiJ9.eyJ0ZXN0MSI6MSwidGVzdDIiOiJ0d28iLCJ0ZXN0MyI6ZmFsc2V9.MEYCIQCiatnRhYGBKgdJj9LECe7mJ4bhhkVTvFSgpVI3Dm14pwIhAOrHAu0vqKvVwdgpAhaU7KOhiIBZdcEOuzfXrdXldCFQ
If it sign it with the built in tools (by just replacing the signatureData row above) with the same input I get it to validate in jwt.io.
var ecdsa = ECDsa.Create();
ecdsa.GenerateKey(ECCurve.NamedCurves.nistP256);
var signatureData = ecdsa.SignData(signatureData, HashAlgorithmName.SHA256);
Any input would be welcome as it feels like I've tested everything...