Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

support quick seach jwk by kid #64

@wbpcode

Description

@wbpcode

Now we will try to iterate all the jwks to find a matched jwk and then verify it. Can we create a hash table based on the kid? And if kid of jwt is not empty, we can try a quick search first before the iteration?

Status verifyJwtWithoutTimeChecking(const Jwt& jwt, const Jwks& jwks) {
  // Verify signature
  std::string signed_data =
      jwt.header_str_base64url_ + '.' + jwt.payload_str_base64url_;[Wayne Zhang, 4 years ago: • Initial code](https://sourcegraph.com/github.com/google/jwt_verify_lib/-/commit/d856e7692ce470a961ac15d635570ac5379036f3)
  bool kid_alg_matched = false;
  for (const auto& jwk : jwks.keys()) {
    // If kid is specified in JWT, JWK with the same kid is used for
    // verification.
    // If kid is not specified in JWT, try all JWK.
    if (!jwt.kid_.empty() && !jwk->kid_.empty() && jwk->kid_ != jwt.kid_) {
      continue;
    }

    // The same alg must be used.
    if (!jwk->alg_.empty() && jwk->alg_ != jwt.alg_) {
      continue;
    }
    kid_alg_matched = true;

    if (jwk->kty_ == "EC") {
      const EVP_MD* md;
      if (jwt.alg_ == "ES384") {
        md = EVP_sha384();
      } else if (jwt.alg_ == "ES512") {
        md = EVP_sha512();
      } else {
        // default to SHA256
        md = EVP_sha256();
      }

      if (verifySignatureEC(jwk->ec_key_.get(), md, jwt.signature_,
                            signed_data)) {
        // Verification succeeded.
        return Status::Ok;
      }
    } else if (jwk->kty_ == "RSA") {
      const EVP_MD* md;
      if (jwt.alg_ == "RS384" || jwt.alg_ == "PS384") {
        md = EVP_sha384();
      } else if (jwt.alg_ == "RS512" || jwt.alg_ == "PS512") {
        md = EVP_sha512();
      } else {
        // default to SHA256
        md = EVP_sha256();
      }

      if (jwt.alg_.compare(0, 2, "RS") == 0) {
        if (verifySignatureRSA(jwk->rsa_.get(), md, jwt.signature_,
                               signed_data)) {
          // Verification succeeded.
          return Status::Ok;
        }
      } else if (jwt.alg_.compare(0, 2, "PS") == 0) {
        if (verifySignatureRSAPSS(jwk->rsa_.get(), md, jwt.signature_,
                                  signed_data)) {
          // Verification succeeded.
          return Status::Ok;
        }
      }
    } else if (jwk->kty_ == "oct") {
      const EVP_MD* md;
      if (jwt.alg_ == "HS384") {
        md = EVP_sha384();
      } else if (jwt.alg_ == "HS512") {
        md = EVP_sha512();
      } else {
        // default to SHA256
        md = EVP_sha256();
      }

      if (verifySignatureOct(jwk->hmac_key_, md, jwt.signature_, signed_data)) {
        // Verification succeeded.
        return Status::Ok;
      }
    } else if (jwk->kty_ == "OKP" && jwk->crv_ == "Ed25519") {
      Status status = verifySignatureEd25519(jwk->okp_key_raw_, jwt.signature_,
                                             signed_data);
      // For verification failures keep going and try the rest of the keys in
      // the JWKS. Otherwise status is either OK or an error with the JWT and we
      // can return immediately.
      if (status == Status::Ok ||
          status == Status::JwtEd25519SignatureWrongLength) {
        return status;
      }
    }
  }

  // Verification failed.
  return kid_alg_matched ? Status::JwtVerificationFail
                         : Status::JwksKidAlgMismatch;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions