ES256 的 JWT 签名要求

Posted

技术标签:

【中文标题】ES256 的 JWT 签名要求【英文标题】:JWT signing requirements for ES256 【发布时间】:2019-04-12 10:51:54 【问题描述】:

我正在尝试通过使用 ES256 为我的 JWT 生成签名来编译我唱歌的最后一部分。

根据jwt.io,我可以使用 HMAC SHA256 对其进行签名-如果我的标头使用 ES256,我会感到有些困惑-这是否意味着我必须使用 ES256 算法对其进行签名?

这是我必须ES256的要求。


"alg": "ES256",
"kid": "DSR74G",
"typ": "JWT"

【问题讨论】:

tools.ietf.org/html/rfc7518#section-3.4 如果 alg 是 ES256,那么你正在使用 ECDSA 签名。如果 alg 是 HS256,那么您正在使用 HMAC-SHA256 进行签名。你需要哪个?如果您需要使用一个系统签名并使用其他系统进行验证,请选择 ECDSA。如果您只需要从一个系统进行签名和验证并且不会改变,那么 HMAC 就可以了。 我必须使用 ES256 并使用 Google Scripts - 这是否意味着我必须使用 ECDSA 才能使用 ES256? 【参考方案1】:

RFC 7518 定义(in section 3.1)“alg”值和 MAC 算法之间允许的配对。 ES256必须ECDSA using P-256 and SHA-256配对作为MAC算法。

由于您面临 Apple 要求使用 ES256,这意味着您必须使用 ECDSA。

【讨论】:

【参考方案2】:

当您的密钥有问题时,我们会得到“无效的客户端”,或者在使用 ES256 验证授权码时会得到“子”。使用下面的代码,您的问题将得到解决,因为我已经解决了我的问题。

代码:

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;

【讨论】:

以上是关于ES256 的 JWT 签名要求的主要内容,如果未能解决你的问题,请参考以下文章

ES256 JWT 验证 - SignatureException:签名的无效编码:java.io.IOException:序列标签错误

JWT:我应该使用哪种签名算法?

JWT 签名算法 HS256 与 RS256

.NET:RS256 签名的 JWT 中的签名无效

无法验证 RS256 签名的 JWT

Jwt介绍