You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用根证书验证FIDO联盟Metadata的JWT签名?

解决FIDO联盟Metadata JWT签名验证失败问题

你的问题出在直接使用根证书公钥验证JWT签名——FIDO的Metadata JWT是由GlobalSign的中间CA证书签名的,而非根证书直接签名。正确的流程是先验证中间证书的合法性(用根证书),再用中间证书的公钥验证JWT签名。

以下是修正后的代码:

import requests
from jwcrypto import jwt, jwk, jws
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

# 下载并加载GlobalSign根证书
root_cert_resp = requests.get("http://secure.globalsign.com/cacert/root-r3.crt")
root_cert = x509.load_der_x509_certificate(root_cert_resp.content, default_backend())

# 下载FIDO Metadata JWT
jwt_data = requests.get("https://mds3.fidoalliance.org/").content.decode("ascii")

# 解析JWT头部,获取签名用的中间证书(x5c字段)
jwt_obj = jws.JWS()
jwt_obj.deserialize(jwt_data)
header = jwt_obj.jose_header
x5c_chain = header.get("x5c", [])
if not x5c_chain:
    raise ValueError("JWT头部未包含证书链x5c字段")

# 加载中间证书(链中的第一个是签名证书)
intermediate_cert_pem = f"-----BEGIN CERTIFICATE-----\n{x5c_chain[0]}\n-----END CERTIFICATE-----".encode()
intermediate_cert = x509.load_pem_x509_certificate(intermediate_cert_pem, default_backend())

# 验证中间证书是否由根证书签发
intermediate_cert.verify_directly_issued_by(root_cert)

# 从中间证书提取公钥,转为JWK格式
pub_key_pem = intermediate_cert.public_key().public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
)
public_key = jwk.JWK.from_pem(pub_key_pem)

# 验证并解析JWT
final_jwt = jwt.JWT(jwt=jwt_data, key=public_key)
print(final_jwt.claims)

关键说明:

  • 证书链验证:JWT头部的x5c字段包含了签名证书链,第一个元素就是直接签名JWT的中间CA证书,需要先验证该证书是根证书的合法下属。
  • 公钥格式:提取公钥时使用SubjectPublicKeyInfo格式(而非PKCS1),这是JWK兼容的标准格式,避免格式不匹配导致的验证失败。

内容的提问来源于stack exchange,提问作者gřmězupť

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:43:17