I am trying to verify ES512 jwt token using public key which is in string format:
I am trying to imitate a sample written for ES256 which is something like this:
// The code for ES256
public static void VerifyES512Jwt(string token,string publicKey)
{
byte[] publicKeyBytes = Convert.FromBase64String(publicKey);
string[] parts = token.Split('.');
string header = parts[0];
string payload = parts[1];
string signature = parts[2];
var keyType = new byte[] { 0x45, 0x43, 0x53, 0x31 };
var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 };
var key = keyType.Concat(keyLength).Concat(publicKeyBytes.Skip(publicKeyBytes.Length - 64)).ToArray();
CngKey cngKey = CngKey.Import(key, CngKeyBlobFormat.EccPublicBlob);
// the purpose is to get ECDsaCng and verify the payload data
ECDsaCng eCDsaCng = new ECDsaCng(cngKey);
bool result = eCDsaCng.VerifyData(payload, signatureBytes);
}
I am trying to use this code for ES512 and got stuck on getting the key
var keyType = new byte[] { 0x45, 0x43, 0x53, 0x31 };
var keyLength = new byte[] { 0x20, 0x00, 0x00, 0x00 };
var key = keyType.Concat(keyLength).Concat(publicKeyBytes.Skip(publicKeyBytes.Length - 64)).ToArray();
when used with the above it gives error in getting key:
CngKey cngKey = CngKey.Import(key, CngKeyBlobFormat.EccPublicBlob);
The public key and token I am using are as follows: public key:
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47 6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM Al8G7CqwoJOsW7Kddns=
Token:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE1NjUwOTk2ODgsImV4cCI6MTU5ODE4OTg4NSwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDozNTg4Iiwic3ViIjoiaHR0cDovL2xvY2FsaG9zdDo1MDM3NiIsImZpcnN0bmFtZSI6IkFydmluZCIsImxhc3RuYW1lIjoiS3VtYXIiLCJFbWFpbCI6ImFydmluZC5rdW1hckBzdHJlYW1hbWcuY29tIiwiSWQiOiIxMDEifQ.AVwAJeY44lKrnywnDs7CdUOu3gli2cGafSJ6iP3zT7lkZpd2QnL0k54aVmPVxAGuN5dDnzbYmMTdRl5u2QE92ccOAHrcf5yA2gsvhhAGuDAAeh6Io4VU7v5TOTvwWGRb-ubgdjUvagA_HSJOyeXvFR16_M_MzGfDnXfg02sj4y9VFjDr
ES512 uses ECDSA with P-521 and SHA-512.
A public key for P-521 (secp521r1, chap. 2.6.1) has a size of 2 x 66 = 132
bytes in uncompressed form (front byte 0x04
). MS specifies the public key for P-521 with the value 0x35534345
.
The key must therefore be generated as follows:
var keyType = new byte[] { 0x45, 0x43, 0x53, 0x35 };
var keyLength = new byte[] { 0x42, 0x00, 0x00, 0x00 };
var key = keyType.Concat(keyLength).Concat(publicKeyBytes.Skip(publicKeyBytes.Length - 132)).ToArray();
The data to be signed are header and payload (both Base64url encoded) including the separator (.
). The signature is also Base64url encoded. The verification must therefore be performed as follows:
byte[] headerPayloadBytes = Encoding.UTF8.GetBytes(header + "." + payload);
byte[] signatureBytes = Base64UrlDecode(signature);
bool verified = eCDsaCng.VerifyData(headerPayloadBytes, signatureBytes, HashAlgorithmName.SHA512);
Base64UrlDecode
accomplishes the Base64url decoding, see e.g. here for implementation details.