JWT 签名与验证
用你自己的密钥签发令牌,对照共享密钥、PEM、JWK 或实时 JWKS 验证令牌——并构建你的 API 发布的密钥集。全部加密都在浏览器里运行。
JWT 的可信程度,取决于它的签名。任何人都能读令牌——解码什么也证明不了——所以本工具做的是解码器做不到的那部分:用你的密钥签发令牌(HS256/384/512、RS256/384/512、ES256/384/512、EdDSA),对照共享密钥、PEM 或 JWK 公钥、粘贴的 JWKS 或实时 JWKS URL(按 kid 匹配)验证令牌,并构建你自己的 API 发布的 JWKS。配套指南签名与验证 JWT解释了为什么解码不等于验证、算法混淆攻击是怎么回事,以及“已验证”能证明什么、不能证明什么。不用密钥只想读令牌,请用JWT 解码器;密钥本身的生成与转换,见SSH 密钥套件。
最后更新:
签发令牌
这份密钥不到 32 个字符。短密钥经不起离线猜测——真正用的密钥,请用长随机密钥。
验证令牌
“已验证”表示签名与这把密钥匹配,且令牌在有效期内。它不表示签发方值得信任——那取决于密钥从哪里来。
构建与校验 JWKS
构建 JWKS
从生成的密钥、PEM 或粘贴的 JWK 添加密钥。每条记录都会得到一个 kid——能算出的用 RFC 7638 摘要,算不出的用随机 id,本页会如实标注。
本密钥集中的密钥
还没有密钥。请在上方生成一把,或粘贴 PEM 或 JWK。
校验 JWKS
转换密钥(PEM ⇄ JWK)
在“签发”标签页粘贴一把密钥、在那里生成一把,或在下方转换。HMAC 密钥没有 PEM 形式——oct JWK 就是密钥本身。
🔒 签名与验证在本地用 WebCrypto 完成。密钥与私钥永不发送、永不存储、永不记录——刷新页面,它们就消失了。
你的密钥永不离开本页
签名与验证使用浏览器自带的 WebCrypto,操作的是你粘贴或在这里生成的密钥。密钥与私钥只存在于页面内存中:不上传、不写入 localStorage 或 cookie,也不放进 URL。刷新或关闭页面,它们就消失了。唯一的例外是 JWKS URL 获取,由你自己发起:它只发送你输入的 URL,去取回公开密钥——绝不发送密钥。把生产密钥粘贴到任何地方之前,先读一读签名与验证 JWT。
如实说明的局限
EdDSA 需要较新的浏览器:老浏览器没有 WebCrypto Ed25519,本页会如实说明,而不是伪造签名。ECDSA P-256 是处处可用的后备方案。
加密 PEM(用口令锁住的私钥)第一版不支持。本页会公开拒绝——请先用 openssl pkcs8 -topk8 -nocrypt 解密,并且永远不要把口令粘贴进网页。
JWKS URL 获取依赖对方服务器发送 CORS 响应头。多数身份提供方会发送;不发送的,获取会如实失败,本页会提示你改为粘贴 JWKS。获取的永远只有公开密钥——JWKS URL 里绝不会有密钥。
什么时候签名胜过解码
解码 JWT 就是读它:头部和载荷是 base64url,拿到令牌的任何人都能看到这两段。正因如此,只靠解码器永远回答不了唯一真正重要的问题——签发方真的签过它吗?签名是这项工作的另一半:持有私钥(或 HMAC 密钥)的一方生成签名,验证方用公钥重算同样的数学。本页把这两半都留在你的浏览器里,因为涉及的密钥是任何网页工具处理过的最敏感输入。
这种区分在非对称算法上最重要。用 HS256,验证用的密钥就是签发用的密钥——能校验你令牌的人也能铸造令牌,在一个服务内部这没问题,出了这个范围就是泄露。用 RS256、ES256 或 EdDSA,签发密钥留在签发方手里,只有公钥会传播:你的 API 可以发布自己的 JWKS,新增一个 kid 来轮换密钥,让全世界的验证方都能校验令牌,而没有任何一方握有伪造令牌的能力。
本工具拒绝做的事
有两项拒绝是刻意的。第一是 alg: none:声称不需要签名的令牌会被直接拒绝,并给出原因——接受它的验证方就是在接受伪造品。第二是算法混淆:用 HMAC 密钥递上 RS256 令牌(或反过来)会带着明确警告失败,绝不会悄悄把密钥按另一族重新解释。这两种都是经典的 JWT 攻击,而这里的防护是结构性的——密钥所属的族必须与令牌的 alg 所属的族匹配,否则验证失败。
第三项拒绝更微妙:本页永远不会告诉你一个令牌是“可信的”。有效的签名只证明令牌由持有密钥的一方签发、且在有效期内——仅此而已。是否信任这把密钥,取决于它从哪里来:从身份提供方的 well-known URL 获取的 JWKS、你自己钉住的公钥、你生成的密钥。指南签名与验证 JWT会一步步讲清“已验证”能证明什么、不能证明什么。
JWT 术语,一一说清
JWT. JSON Web Token(RFC 7519):在各方之间传递声明的紧凑、URL 安全的方式——头部.载荷.签名,每段都是 base64url 编码。载荷任何人都能读;只有签名依赖密钥。
JWS. JSON Web Signature(RFC 7515):JWT 之下的签名格式。JWT 就是载荷为 JSON 声明集的 JWS。
JWK. JSON Web Key(RFC 7517):表示一把密码学密钥的 JSON 对象——kty,以及密钥材料(RSA 的 n/e、EC 的 x/y、Ed25519 的 x、共享密钥的 k)。
JWKS. JSON Web Key Set:带 "keys" 数组的对象——签发方发布公钥的标准方式,通常位于 /.well-known/jwks.json。
kid. 密钥 ID:说明哪把密钥签了这个令牌的头部声明。验证方拿它与 JWKS 比对;没有它时,若密钥集只有一把密钥就用那一把,本页会如实说明。
alg. 命名签名算法的头部声明(HS256、RS256、ES256、EdDSA……)。验证方必须钉住自己接受的算法——信任令牌自己的 alg 声明,就是混淆攻击。
HMAC. 基于哈希的消息认证码:对称签名——同一把密钥既签名又验证。快速简单;持有密钥的每个人都能铸造令牌。
RSASSA-PKCS1-v1_5. RS256/384/512 背后的 RSA 签名方案:对哈希做包装,再以私钥指数运算。确定性的——同一输入永远得到相同的签名字节。
EdDSA. Edwards 曲线数字签名算法:这里指 Ed25519——密钥小、验证快、签名确定性。WebCrypto 支持需要较新的浏览器。
常见问题
把私钥粘贴到本页安全吗?
在本页,密钥永不离开你的浏览器:签名在页面内存中用 WebCrypto 运行,不上传、不存储、不记录,刷新即清除。不安全的模式是服务器端签名器——你的私钥要穿过网络。即使在本地,也请用你信任的设备——如果机器是共用的,请把粘贴过的生产密钥当作已泄露。生成测试密钥请直接在这里生成,不要粘贴真实密钥。
为什么我的 RS256 令牌用密钥验证不了?
因为密钥和 RSA 密钥属于不同的族,本页拒绝混用——这项拒绝正是算法混淆防护。RS256 令牌需要签发方的 RSA 公钥(PEM、JWK 或 JWKS);密钥只能验证 HS256/384/512。如果你的公钥形式不对,可以转换:JWKS 标签页可以在 PEM ⇄ JWK 之间转换。
JWKS URL 获取实际发送了什么?
向你输入的 URL 发起一次 GET 请求,请求 JSON。不附带任何密钥、令牌或标识——返回的是一组公开密钥。如果服务器不发送 CORS 响应头,浏览器会阻止读取,本页会提示你改为粘贴 JWKS。
令牌在这里验证通过了,API 却拒绝它,为什么?
这里的验证只检查签名和时间窗口,对照的是你提供的密钥。API 还要检查声明:它期望的签发方(iss)、它服务的受众(aud),以及密钥 id(kid)是否仍是它信任的。用已轮换掉的密钥签发的令牌,或为另一个受众铸造的令牌,数学上验证通过,仍然会被拒绝——而且拒绝得没错。
EdDSA 在我的浏览器里用不了,怎么办?
Ed25519 需要较新的浏览器——老浏览器完全没有 WebCrypto Ed25519,本页会如实说明,而不是伪造。用 ES256(ECDSA P-256)作为后备方案:只要有 WebCrypto 的地方都支持,本页还能为你生成密钥。如果必须用 Ed25519,请升级浏览器。