当前位置: 首页 > 知识库问答 >
问题:

如何在没有x5c的情况下验证jwks的JWT签名

富钧
2023-03-14

我有一个JWT安全令牌,需要通过jwksendpoint进行验证。jwks中的数据如下所示:

{
  "keys": [
    {
      "kty": "RSA",
      "e": "AQAB",
      "use": "sig",
      "alg": "RS256",
      "n": "......",
      "kid": "2132132-b1e6-47e7-a30f-1831942f74bd"
    },
    {
      "kty": "RSA",
      "e": "AQAB",
      "use": "sig",
      "alg": "RS256",
      "n": "......",
      "kid": "tsp-app-a"
    },
    {
      "kty": "RSA",
      "e": "AQAB",
      "use": "sig",
      "alg": "RS256",
      "n": ".....",
      "kid": "tsp-app-b"
    }
  ]
}

我尝试了一个第三方api,但它看起来依赖于x5c密钥,这在我的案例中不存在。

我的代码是:

public static bool Validate(JwtSecurityToken jsonToken)
        {
            bool result = false;
            try
            {
                var headers = Jose.JWT.Headers<JWTHeader>(jsonToken.RawData);
                var payload = Jose.JWT.Payload<JWTPayload>(jsonToken.RawData);

                string jwk = "";
                using (HttpClient cli = new HttpClient())
                {
                    jwk = cli.GetStringAsync(MyclientUrlforWellknownjson).Result;
                }

                var jwkinfo = JsonSerializer.Deserialize<JWKS>(jwk);
                //Find right key. Match kid and alg,  (To be changed later. It is possible that there are multiple x5c elements in key)
                var jwkkey = (from item in jwkinfo.keys where item.kid == headers.kid && item.alg == headers.alg select item).SingleOrDefault();

                //If key was found then load its public key
                System.Security.Cryptography.X509Certificates.X509Certificate2 cert = null;
                if (jwkkey != null)
                {
                    //Get public key from well known information
                    byte[] key = System.Text.Encoding.ASCII.GetBytes(jwkkey.x5c[0]); //??todo 
                    //Create cert                   
                    cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(key);
                }

                var o = Jose.JWT.Decode(jsonToken.RawData, cert.PublicKey.Key);


            }
            catch (Exception ex)
            {

            }
            return result;
        }

如何在没有x5c的情况下通过jwks验证JWT?

共有1个答案

阎博易
2023-03-14

使用x5c只是一种方法,但您也可以使用参数e(公共指数)和n(模数)检索公钥,这也记录在jose jwt github页面上:

//If kid was found then load public key
if (jwkkey != null)
{
    RSACryptoServiceProvider key = new RSACryptoServiceProvider();
    key.ImportParameters(new RSAParameters
    {
        Modulus = Base64Url.Decode(jwkkey.n),
        Exponent = Base64Url.Decode(jwkkey.e)
    });
}

// get the public key in PEM format, e.g. to use it on jwt.io
var pubkey = Convert.ToBase64String(key.ExportSubjectPublicKeyInfo());
const string pemHeader = "-----BEGIN PUBLIC KEY-----";
const string pemFooter = "-----END PUBLIC KEY-----";
var publicKeyPem = pemHeader + Environment.NewLine + pubkey + Environment.NewLine + pemFooter;

var o = Jose.JWT.Decode(jsonToken.RawData, key);

您还可以再次以PEM格式导出公钥,如上面的代码所示,如下所示:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgIdJV4qWKyt3wkS66yBG5Ii9ew+eofuPU49TjlRIU5Iu5jX2mRMoHdcI7V78iKYSQHKYxz17cqzQyERxKnEiDgy/gwouStRgvPdm3H4rq//7p0t15SunsG2T1rEVf0sZEDnQ5qRkm7iqs6ZG1NqqIUtnOTd1Pd1MhbEqeENFtaPHvN37eZL82WmsQlJviFH4I9iZQVR/QT4GREQlRro8IjJTaloUyeDQTOQ+4ll1+4+g/ug2tZ+s9xleLzl5L9ZKSVJFhtMLn8WGaVldagarwa7kMLfuiVe8B5Lr7poQa4NCAR54ECPWoOHrABdPZKrkkxjVypTXUzL5cPzmzFC2xwIDAQAB
-----END PUBLIC KEY-----

然后使用该密钥在https://jwt.io上手动验证令牌

(在@Topaco提示后更正了密钥导出)

 类似资料:
  • “laravel/框架”:“5.7.*” “tymon/jwt认证”:“开发人员开发” 我正在尝试创建一个添加了自定义声明的JWT令牌,而不使用auth(这意味着我不希望从凭据创建令牌)。这是为了创建不需要登录的令牌,例如忘记/重置密码等。 使用Tymon/JWTAuth(https://github.com/tymondesigns/jwt-auth)由于最新的Laravel存在问题,因此建议加

  • Im使用dgrijalva/jwt go 令牌(过期令牌): jwks: 在那里看到的大多数示例iv'e都使用'kid',并且不相关,因为我的令牌头没有它,它有'x5t'字段。。 我还必须注意一件事,我的签名似乎是base64编码的,而不是base64 url编码的(这几乎扰乱了解析方法的使用)。我试过使用jwt。Parse()我尝试过手动加密头和有效负载sha256,而不是RS256和base6

  • 我正在实施 Apple 的应用证明服务。 作为该过程的一部分,我收到一个EC密钥和一个签名。 示例密钥: 签名样本: sha256哈希示例: 如果我把它放入几个txt文件,如下所示: 然后我可以用Openssl验证签名,就像这样 (以上产出) 验证正常 我可以使用Bouncy Castle验证签名,如下所示: 由于我不想在这里分享我的整个证书,因此可以按如下方式实现相同的示例: 然而,我真的想避免

  • 我在JavaFX应用程序上通过hibernate-validation使用Java Beans验证,因此,没有框架来帮助连接。我将这些依赖项添加到我的项目中: 我发现这可以使<code>modelObject</code>得到验证: 我的问题是,每次验证时都创建一个新的工厂和验证器不好吗?我应该将它们缓存在某个地方并重复使用它们吗?验证器有多昂贵和多线程?

  • 我有以下Spring启动应用程序与最小的配置 应用性质 pom.xml 控制器 Spring Boot Oauth2似乎不使用公钥,正如我在代码中看到的: OAuth2ResourceServerProperties 但是,我没有给,但应用程序可以验证没有公钥。 在引擎盖下,它使用和验证器。 另一方面,使用,需要公钥进行离线验证 Spring Boot Oauth如何在没有公钥的情况下进行验证?

  • 问题内容: 我想将时间戳添加到我的PDF文档中(不带数字签名)。我怎样才能做到这一点? 我可以使用Itext使用数字签名来做到这一点(我在这里有TSAClient): 但是在没有数字签名的情况下如何做类似的事情?使用Bouncy Castle或Itext或Pdfbox …或其他库。 问题答案: 在iText中,您正在寻找 也比照。JavaDoc文档: 您可能需要阅读章节5.4.1 在数字签名中为P