JWT signing requirements for ES256

Viewed 9634

I am trying to compile the final part of my singing by generating the signature for my JWT using ES256.

According to jwt.io, I can sign it with HMAC SHA256 - here is where I get a bit confused, if my header uses ES256 - does this mean I have to sign it using ES256 algorithm?

It is a requirement that I have to ES256.

{
"alg": "ES256",
"kid": "DSR74G",
"typ": "JWT"
}
2 Answers

RFC 7518 defines (in section 3.1) the allowed pairings between "alg" values and the MAC algorithm. ES256 must be paired with ECDSA using P-256 and SHA-256 as the MAC algorithm.

Since you are facing a requirement from Apple to use ES256, that means you have to use ECDSA.

We get "invalid client" when there is problem in your key or "sub" when verifying authorization code with ES256. Use the below code and your problem will be solved, as I have solved my problem.

Code:

private static CngKey GetPrivateKey()
    {
        using (var reader = File.OpenText(ConfigurationManager.AppSettings["key2"].ToString()))  //put your key's path  like C:\ABC.p8
        {
            var ecPrivateKeyParameters = (ECPrivateKeyParameters)new PemReader(reader).ReadObject();
            var x = ecPrivateKeyParameters.Parameters.G.AffineXCoord.GetEncoded();
            var y = ecPrivateKeyParameters.Parameters.G.AffineYCoord.GetEncoded();
            var d = ecPrivateKeyParameters.D.ToByteArrayUnsigned();
            return EccKey.New(x, y, d);
        }
    }
   var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

    var issueTime = DateTime.Now;

    var iat = (int)issueTime.Subtract(utc0).TotalSeconds;
    var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds;
    var payload = new Dictionary<string, object>()
    {
        { "sub", "com.xyzttt" },  // you registered app 
        { "aud", "https://appleid.apple.com"},
        { "iss", "ABCDEFGHttt" },  //Team id 
        { "exp", exp },   }, //current time + @@@@ 
        { "iat", iat } } // current time
    };
    var extraHeader = new Dictionary<string, object>()
    {
          { "alg", "ES256" },
          { "kid", "5ABCDEFGH123tt21"}, //key id
    };
    var sb = GetPrivateKey(); 

    var ecdsa = new ECDsaCng(sb);

    byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(extraHeader, Formatting.None));
    byte[] claimsBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));


    var Rpayload = Base64UrlEncode(headerBytes) + "." + Base64UrlEncode(claimsBytes);
    var signature = ecdsa.SignData(Encoding.UTF8.GetBytes(Rpayload), HashAlgorithmName.SHA256);
    var data = Base64UrlEncode(signature);
    string token = Rpayload + "." + data;
   
    return token;
Related