JWT 解码、验证与生成
{
"alg": "HS256",
"typ": "JWT"
}{
"sub": "1234567890",
"name": "John Doe",
"admin": true,
"iat": 1516239022
}sub· 主题1234567890name· 姓名John Doeadmin· 管理员trueiat· 签发时间1516239022→ 2018/01/18 09:30:22algHS256HMAC(对称)typ· 类型JWT免费在线 JWT 工作台:支持 13 种算法(HS256/RS256/ES256/PS256/EdDSA 等)的解码、验证与生成。PEM/JWK 双格式,自动生成密钥对,自动解析 exp/iat/nbf,浏览器本地处理,Token 零上传。
相关推荐
生成 HMAC-SHA256 密钥用于 JWT HS256 签名
JWT HS256 本质是 HMAC + Base64URL 编码,先学 HMAC 再用 JWT
JWT 内部使用的 Base64URL 编码原理
JWT Header/Payload/Signature 都是 Base64URL 编码
Base64URL 解码 JWT 三段内容
JWT 三段拆解后做 Base64URL 解码查看明文
需要加密 Payload 时改用 JWE / AES
JWT 默认明文可读,敏感 Payload 应改用 JWE / AES
HS256 签名底层的 SHA-256 哈希
HS256 = HMAC + SHA-256,先理解 SHA-256
用生成的 JWT 直接测 API 接口
JWT 调试完后直接拼到 Authorization: Bearer 头测试
正则表达式测试器
什么是JWT 解码、验证与生成?
JWT(JSON Web Token)是 IETF 在 RFC 7519 中定义的开放标准(RFC 7515 描述其 JWS 签名形式,RFC 7516 描述 JWE 加密形式,RFC 7517 定义 JWK 密钥),用于在 HTTP 请求、OIDC 流程、微服务调用之间安全传递「已声明」的用户信息。一个标准 JWT 字符串由三段 Base64URL 编码组成:Header(算法与类型)、Payload(Claims,承载用户数据)、Signature(用密钥对前两段的签名)。三段之间用英文点号 `.` 分隔,例如 `eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`。
**JWT ≠ 加密**。这是最常见的误解。Payload 默认是「明文可读」的——任何人都可以用 Base64URL 解码看到内容。JWT 提供的是「**防篡改**」而不是「**防窃听**」:服务端用密钥对 Header.Payload 重新签名并与原 Signature 对比,若一致则证明 Token 在传输中没被改过。这正是火车票「二维码可读 + 防伪钢印」的隐喻:检票员关心的是「票是不是真的」,而不是「二维码看不清」。
JWT 在 13 种算法之间做了明确分工。**HMAC 类**(HS256/HS384/HS512)用对称密钥签发和验证,速度快、实现简单,适合单机服务或同一信任域内的服务集群;密钥长度必须 ≥ 摘要长度(如 HS256 至少 32 字节)。**RSA 类**(RS256/RS384/RS512)用 RSASSA-PKCS1-v1_5,是最常见的非对称方案,签发方持私钥、验证方持公钥。**RSA-PSS 类**(PS256/PS384/PS512)用更新的 RSA-PSS 填充,安全性更高,AWS SigV4 与新晋 OIDC IdP 倾向使用。**ECDSA 类**(ES256/ES384/ES512)用椭圆曲线(分别为 P-256/P-384/P-521),签名更短、性能更好。**EdDSA**(主要为 Ed25519)签名速度极快、确定性签名(同一消息同一密钥必出同一签名),是 OAuth 2.1 与新协议的推荐算法。
安全是 JWT 在生产环境最容易踩雷的地方。OWASP 在 JWT Cheat Sheet 中强调至少 4 条红线:(1) 永远不要在 Payload 里放密码、身份证、银行卡、API Key 等明文敏感信息;(2) 服务端**不要相信** Token Header 中声明的 `alg`,必须用配置写死的算法校验,否则攻击者改 `alg: none` 就能绕过(这是历史上 CVE-2015-9235 等漏洞的根因);(3) HMAC 密钥不能用短字符串,至少 32 字节随机数;(4) 验证不能只看签名,还要校验 `exp`(过期时间)、`nbf`(生效时间)、`iss`(签发者)、`aud`(受众)。本工具在 UI 上把这些 Claims 全部高亮展示,就是为了让排障时一眼看出问题到底在「签名」「时间」还是「Claims」。
JWT 与 Session 不是替代关系。Session 把用户状态存到服务端(Redis / 数据库),JWT 把状态装进 Token 里。微服务架构、无状态 API、移动端、CORS 跨域场景下 JWT 更省事;但传统企业系统、要求实时撤销(如「踢人下线」)的场景仍更适合 Session。本工具同时适合「纯 JWT 调试」与「Session 转 JWT 迁移」中的 Token 解析、签名验证、Payload 编辑场景。
适用场景
- 在线解码 JWT:调试 OAuth 2.0 / OIDC 登录时快速拆解 Token,查看 Header 算法与 Payload Claims 实际值
- 验证 JWT 签名:用 Secret / 公钥实时校验 Token 签名,快速判断 401 Unauthorized 是「签名错」还是「过期」还是「算法不匹配」
- 联调生成测试 JWT:开发期间用一对测试密钥在浏览器内直接签发 JWT,避免每次都让后端临时改代码生成
- PEM ↔ JWK 转换:OIDC IdP 给的是 JWK、服务端要 PEM 时直接在线互转;或反过来,节省自己写 OpenSSL 脚本的时间
- 排查 401 Unauthorized:分步确认 Token 是否过期、alg 是否与网关一致、密钥是否匹配、PEM 格式是否正确
- 对比 RS256 与 PS256:很多 OIDC 服务用 RS256,AWS SigV4 体系偏好 PS256,本工具可一键切换算法并复用同一对 RSA 密钥对比结果
- 学习 JWT 原理:在浏览器里改 alg / 改 Payload / 改密钥,直观看到「为什么改一个字节签名就失效」,比看 RFC 文字快得多
使用方法
- 粘贴或输入 Token:把待调试的 JWT 字符串贴到输入框,工具自动拆解 Header、Payload、Signature 三段并 JSON 格式化展示
- 选择算法:在 HS256 / RS256 / ES256 / PS256 / EdDSA 之间切换,工具按 Header.alg 自动推断并提示不匹配
- 导入密钥:粘贴 HMAC Secret、或 PEM 字符串、或 JWK JSON;非对称算法可点击「生成密钥对」直接得到测试用密钥
- 验证或重新签名:Decode 模式用公钥验签并显示「✅ 签名通过 / ❌ 签名失败」;Encode 模式修改 Claims 后用私钥生成新 Token
Output Example
A real MP3 file encoded to a Data URI — copy-ready:
Header (Base64URL): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload(Base64URL): eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNzE2MjM5MDIyfQ
Signature: kZJfaYjK3iCkVFL5EL9zGRZ5SmD8_x2h6B5c7pVFfVGo
Header 解码:
{
"alg": "HS256",
"typ": "JWT"
}
Payload 解码:
{
"sub": "1234567890",
"name": "Jane Doe",
"iat": 1716239022 // 2024-05-20 14:23:42 UTC
}功能特点
- 解码 + 验证 + 生成三合一:粘贴 Token 一键拆解 Header/Payload/Signature;切换算法与密钥即可验证签名;改完 Claims 重新签名即可生成新 Token,覆盖完整 JWT 排障链路
- 13 种算法全支持:HS256/HS384/HS512(HMAC)、RS256/RS384/RS512(RSA-PKCS1-v1_5)、ES256/ES384/ES512(ECDSA)、PS256/PS384/PS512(RSA-PSS)、EdDSA,覆盖 OAuth 2.0、OIDC、JWS、API 网关、企业 SSO 全部主流场景
- PEM / JWK 双格式:RSA、ECDSA、Ed25519 密钥同时支持 PEM 字符串(带 -----BEGIN PUBLIC KEY----- 头)与 JWK JSON(kid/kty/n/e 等字段),直接对接 OIDC Discovery /.well-known/jwks.json 输出
- HMAC Secret 多种输入形式:支持原始字符串、Hex 字节、Base64 / Base64URL 编码的密钥,一键切换,避免「看起来一样但验签失败」
- 密钥对自动生成:RSA-2048、RSA-4096、P-256、P-384、Ed25519 随机生成密钥对并展示 PEM / JWK 双格式,方便联调时立即获得一对测试密钥
- Claims 语义增强:exp / iat / nbf 自动转可读时间,过期 / 未生效 / 已签发状态高亮,Header 中 alg / typ / kid 等关键字段单独标注
- 浏览器本地零上传:所有解析、验签、签名均通过浏览器原生 Web Crypto API 完成,Token、密钥、Payload 永远不出浏览器,符合「不把生产 Token 贴到陌生在线工具」的安全原则
- 一键复制:Header、Payload、Signature、生成的新 Token 可分别复制,用于文档、Issue、curl 测试命令
代码示例
50 行 Node.js:手写 HS256 签发与验签
javascript把 JWT 最核心的机制讲明白:Header + Payload 先 Base64URL 编码,再对 header.payload 做 HMAC-SHA256。生产中应改用 jsonwebtoken / jose 等库,但这一段足够你理解签名验证为什么失败。
const crypto = require('node:crypto')
function b64url(input) {
return Buffer.from(input)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '')
}
function hmacSign(data, secret) {
return b64url(crypto.createHmac('sha256', secret).update(data).digest())
}
function sign(payload, secret) {
const header = b64url(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
const body = b64url(JSON.stringify(payload))
const signature = hmacSign(`${header}.${body}`, secret)
return `${header}.${body}.${signature}`
}
function verify(token, secret) {
const [h, p, s] = token.split('.')
const expected = hmacSign(`${h}.${p}`, secret)
const a = Buffer.from(s)
const b = Buffer.from(expected)
return a.length === b.length && crypto.timingSafeEqual(a, b)
}
const SECRET = 'my-super-secret-key'
const payload = { userId: 42, role: 'admin', exp: Math.floor(Date.now() / 1000) + 3600 }
const token = sign(payload, SECRET)
console.log(token)
console.log(verify(token, SECRET)) // true
console.log(verify(token, 'wrong-key')) // false浏览器端:用 Web Crypto API 做 HMAC 签名
html本工具前端的核心思路:浏览器原生 crypto.subtle 直接完成 HMAC / RSA / ECDSA / RSA-PSS / Ed25519 验签,无需任何第三方库。复制这段到任意 HTML 页面即可签发 HS256。
<!doctype html>
<html>
<body>
<pre id="out"></pre>
<script>
const out = document.getElementById('out')
const b64url = buf =>
btoa(String.fromCharCode(...new Uint8Array(buf)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
const b64urlStr = str => b64url(new TextEncoder().encode(str))
async function sign(payload, secret) {
const header = b64urlStr(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
const body = b64urlStr(JSON.stringify(payload))
const data = new TextEncoder().encode(`${header}.${body}`)
const key = await crypto.subtle.importKey(
'raw',
new TextEncoder().encode(secret),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
)
const sig = await crypto.subtle.sign('HMAC', key, data)
return `${header}.${body}.${b64url(sig)}`
}
;(async () => {
const token = await sign({ user: 'alice', role: 'admin' }, 'browser-demo-secret')
out.textContent = token
})()
</script>
</body>
</html>Node.js:用 jose 验证 RS256(标准做法)
javascript生产代码中请用 jose / jsonwebtoken / pyjwt 等成熟库,不要自己写。这段展示如何用 jose 验证一个 RS256 签名的 JWT,验证失败时打印失败原因(alg 不匹配、签名错、过期、kid 找不到等)。
import { jwtVerify, importSPKI } from 'jose'
import { readFile } from 'node:fs/promises'
const token = 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.payload.signature'
const publicKeyPem = await readFile('public.pem', 'utf8')
try {
const { payload, protectedHeader } = await jwtVerify(
token,
await importSPKI(publicKeyPem, 'RS256'),
{
issuer: 'https://idp.example.com',
audience: 'my-app',
algorithms: ['RS256'], // 关键:白名单算法,禁掉 alg: none / HS256 替换攻击
}
)
console.log('alg =', protectedHeader.alg)
console.log('sub =', payload.sub)
} catch (err) {
console.error('verify failed:', err.code, err.message)
// 常见:ERR_JWT_EXPIRED / ERR_JWS_INVALID / ERR_JWS_SIGNATURE_VERIFICATION_FAILED
}Python:用 PyJWT 解析 Token 并打印 Claims
pythonPython 端调试 JWT 的最常用方式。PyJWT 的 decode() 默认会校验 exp / nbf / iat,并把结果直接转成 dict。
import jwt
token = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.SflKxw'
# 解析(不验签,仅看 Payload / Header)
print(jwt.get_unverified_header(token))
# {'alg': 'HS256', 'typ': 'JWT'}
print(jwt.decode(token, options={'verify_signature': False}))
# {'sub': '1234'}
# 完整验签
claims = jwt.decode(
token,
'my-super-secret-key',
algorithms=['HS256'],
audience='my-app',
issuer='my-service',
)
print(claims['sub'])5 类 JWT 签名算法对比:该选哪个?
JWT 不是单一算法,5 类算法在密钥、性能、安全、兼容性上各有取舍。先看场景再选算法,能少走很多弯路。
| 算法 | 类型 | 密钥 | 性能 | 典型场景 | 注意点 |
|---|---|---|---|---|---|
HS256 | HMAC 对称 | 同一 Secret | 极快 | 服务集群内部、可信环境、单体应用 | Secret 不能泄露给验签方;至少 32 字节随机 |
RS256 | RSA 非对称 | 私钥签 / 公钥验 | 中 | OIDC、API 网关、企业 SSO、公私钥需要分离 | 用 RSASSA-PKCS1-v1_5,跨语言需固定 padding |
PS256 | RSA-PSS 非对称 | 私钥签 / 公钥验 | 中 | AWS SigV4、AWS Cognito、新晋 OIDC IdP | 必须显式固定 saltLength(OpenSSL/jose=32,Go=hash 长度) |
ES256 | ECDSA 非对称 | 私钥签 / 公钥验 | 快 + 签名短 | Apple Sign in with Apple、移动端、低带宽场景 | 不同曲线(P-256/P-384/P-521)必须与服务端一致 |
EdDSA | Ed25519/Ed448 | 私钥签 / 公钥验 | 极快(确定性签名) | OAuth 2.1、新协议、高频验签 | Web Crypto 支持 Ed25519,Ed448 暂未全平台启用 |
最佳实践
生产环境的 Secret / 私钥永远不贴到任何在线工具
本工具虽然 100% 在浏览器本地处理(不上传任何 Token 与密钥),但调试流程一旦形成习惯,极易在后续把生产环境的长期 Secret / 私钥 / Access Token 误粘到陌生在线工具或截屏泄漏。长期 Token(Refresh Token、生产私钥、API Key)必须在本地受控环境处理;本工具只用于调试短期 Access Token、联调测试密钥对、学习 JWT 结构。
OWASP JSON Web Token Cheat Sheet服务端必须白名单算法,绝不信任 Token Header.alg
alg: none 攻击(CVE-2015-9235 等)和 HS256 替换攻击(用公钥当 Secret 骗 RSA 服务端)都源于服务端按 Header 声明的算法选验签逻辑。生产代码必须写死白名单 algorithms,例如 `algorithms: ['RS256']`,禁止让 Token 自己决定用哪个算法。调试时若发现 Header.alg 与服务端预期不一致,优先怀疑服务端配置而不是 Token 内容。
HS256 Secret 至少 32 字节随机数
HS256 用 HMAC-SHA256,密钥长度若低于摘要长度(32 字节)会显著降低暴力枚举成本。不要用 `'my-secret'`、`'password123'` 这类短字符串,也不要用业务名/公司名/年份拼接。标准做法:`openssl rand -base64 32` 或 `crypto.randomBytes(32).toString('base64url')` 生成后存到环境变量 / KMS / 密钥管理服务,绝不写进代码。
JWT 适合存用户敏感信息吗?生产 JWT 必须验证 exp / nbf / iat / iss / aud,不能只验签名
签名通过只证明「没被篡改」,但不证明「还没过期」「确实是这家 IdP 签的」「确实是给本应用签的」。生产环境必须强制校验 exp(过期)、nbf(生效时间)、iat(签发时间)、iss(签发者)、aud(受众)所有相关 Claim,缺一不可。OWASP 明确把这 4-5 项作为必查项。只验签名不验时间是大量 Token 泄露事件(refresh token 永远不过期)的根因。
Token 过期时间分层:Access 15-30 分钟,Refresh 7-30 天
Access Token 负责 API 调用,过期时间越短越安全(泄露后很快失效);Refresh Token 负责换 Access Token,过期时间可以长但必须存服务端、可撤销。常见经验值:Access 15-30 分钟,Refresh 7-30 天,配合 Refresh Token Rotation(每次用 Refresh 换 Access 时同时换新的 Refresh,旧 Refresh 立即失效)能在泄露检测与用户体验间取平衡。
无状态 vs 有状态认证:JWT ≠ Session 的替代品
JWT 把状态装进 Token 里,天然支持微服务横向扩展和 CORS 跨域,但撤销成本高(需要黑名单或短过期)。Session 把状态存到服务端 Redis / DB,能「踢人下线」但需要共享存储。**不是二选一**:短期 Access JWT + 服务端 Refresh Token 会话记录是最常见的混合方案,能同时拿到无状态扩展和实时撤销。需要实时撤销的金融/政务核心系统慎用纯 JWT。
JWT 适合存用户敏感信息吗?Payload 默认明文可读,敏感数据不要塞进 JWT
JWT(JWS)默认不加密 Payload,任何拿到 Token 的人用 Base64URL 一解码就看到内容。**绝对不要**把密码、身份证号、银行卡号、API Key、Access Token、Refresh Token 放进 Payload。JWT 适合放非敏感的 Claims(用户 ID、角色、过期时间、租户 ID),敏感数据由服务端按 sub 二次查询。需要加密 Payload 时改用 JWE(RFC 7516),但性能慢 2-5 倍,且增加密钥管理复杂度——优先考虑「非敏感 Claim + 服务端查询」模式。
什么是 JWT?RSA-PSS(PS256/PS384/PS512)跨语言联调务必先固定 saltLength
RS256 和 PS256 不能互验(不同 padding),PS256 还有个易踩的坑:`saltLength` 参数。OpenSSL 默认 32 字节、Node jose 默认 32 字节、Python PyJWT 默认等于 hash 长度(SHA-256=32)、Go 默认 `rsa.PSSSaltLengthEqualsHash`。跨语言联调时务必先固定同一个值(推荐 32 字节),否则同一对 RSA 密钥签出来的 PS256 Token 在不同语言验签会失败。
RS256 和 PS256 跨语言签名验证失败调试流程:用测试密钥对,不碰生产
联调或本地开发时,永远先生成一对全新的测试密钥(HS256 用随机 Secret、RS256/ES256/EdDSA 用工具一键生成的密钥对),绝不复用生产 IdP 的私钥或公司域名的 Secret。调试完成或本地测试结束后立即销毁测试密钥。本工具的「生成密钥对」功能正是为此设计,RSA-2048/4096、P-256/P-384、Ed25519 一键生成后立即可用,联调结束直接丢弃。
联调生成测试 JWT常见问题
JWT 三段结构分别是什么?
JWT 字符串由 `Header.Payload.Signature` 三段组成,每段都是 Base64URL 编码。Header 声明算法(如 HS256、RS256)和 Token 类型(typ: JWT);Payload 携带用户声明(Claims),常见字段有 sub(用户 ID)、iat(签发时间)、exp(过期时间)、nbf(生效时间)、aud(受众)、iss(签发者);Signature 是用密钥对前两段签名后的结果,作用是「防篡改」而不是「防偷看」。
解码 JWT 之后可以修改 Payload 吗?
可以查看和编辑,但**不能伪造**。一旦你改了 Header 或 Payload,原始 Signature 立刻失效,服务端验签会拒绝。要让修改后的 Token 重新可用,必须用相同算法和密钥**重新签名**——这正是本工具提供「解码 + 编辑 + 生成」三合一的原因:解码看一眼,改完直接生成新 Token 用于测试,避免每次都让后端临时改代码签发。
HS256、RS256、ES256、PS256、EdDSA 有什么区别?
HS256 是 HMAC + SHA-256,对称密钥(签发验签用同一 Secret),实现简单速度快。RS256 是 RSASSA-PKCS1-v1_5 + SHA-256,非对称(私钥签 / 公钥验),最常见的 OIDC 算法。PS256 是 RSA-PSS,RS256 的安全升级版,AWS SigV4 / Cognito 等服务偏好。ES256 是 ECDSA + P-256,签名短、性能好,Apple Sign in with Apple 默认使用。EdDSA(Ed25519)是下一代算法,签名确定且极快,OAuth 2.1 推荐。本工具支持全部 13 种算法,可在 UI 自由切换。
为什么我的 JWT 一直「Invalid Signature」?
最常见的 5 个原因:(1) 密钥不匹配——服务端 Secret / 公钥与工具中粘贴的不一致(注意 PEM 头尾、空行、空格);(2) Base64 与 Base64URL 混用——JWT 一定是 Base64URL(`+` → `-`、`/` → `_`、去掉 `=`),用标准 Base64 解码必然算错签名;(3) 算法选错——Header 写 HS256 但服务端按 RS256 验;(4) Secret 被错误地按 Hex / Base64 解码了一次——本工具的「Secret 输入格式」可显式指定 UTF-8 / Hex / Base64,避免双层解码;(5) 服务端时钟漂移导致 iat 比当前时间还靠后,被认为是「未生效」Token。
RS256 和 PS256 可以用同一对 RSA 密钥互相验签吗?
**不能**。RS256 用 RSASSA-PKCS1-v1_5,PS256 用 RSA-PSS,两者签名长度、填充方式、验签逻辑都不同。同一对 RSA 密钥签出来的 RS256 Token 用 PS256 验签必然失败,签名末尾可能还差几个字节。务必让签发方和验证方用同一种算法。RSA-PSS 还有 `saltLength` 参数,OpenSSL 默认 32、Node jose 默认 32、Go 默认等于 hash 长度,跨语言联调时务必先固定这个值。
什么是 alg: none 攻击?怎么防?
alg: none 攻击是 JWT 历史上最经典的漏洞(CVE-2015-9235 等)。攻击者把 Token Header 改成 `{"alg": "none"}` 并把 Signature 段清空,如果服务端按 Header 声明的算法选择「none 算法」就直接放行。还有一种变种:把 RS256 Token 改成 HS256,把公钥当作 Secret 来签,服务端如果让 Token 决定算法就会被骗。**防御方法只有一条**:服务端写死白名单 `algorithms: ['RS256']`,绝不让 Token 告诉服务端用哪个算法。本工具在 UI 上同时显示 Header.alg 与你实际选择的算法,并在不一致时高亮提示。
PEM 和 JWK 怎么互转?哪个更常用?
PEM 是带 `-----BEGIN PUBLIC KEY-----` 头尾的 Base64 字符串,传统 OpenSSL / Java / Go 体系最常用。JWK 是 JSON 结构(`{kty, n, e, kid, alg}` 等字段),OAuth 2.0 / OIDC 体系标准。OIDC IdP 一般通过 `/.well-known/jwks.json` 端点直接发布公钥 JWK;服务端用 JOSE 库(jose、PyJWT、jsonwebtoken)解析。互转在线就能做——本工具的 RSA / ECDSA / Ed25519 区段直接支持粘贴 PEM 或 JWK,并显示对方格式的等价表示。
JWT 可以在浏览器里直接验签吗?
可以。浏览器原生 Web Crypto API(`window.crypto.subtle`)支持 HMAC、RSA、ECDSA、RSA-PSS、Ed25519 的签名与验签,无需任何第三方库。本工具就是直接用 `crypto.subtle.importKey` + `crypto.subtle.verify` 在前端完成所有验签,所以完全不上传 Token 与密钥。但请注意:Web Crypto API 仅在 **HTTPS** 或 `localhost` 域下可用,且不能操作非密码学安全场景的密钥。
我的 Token 会上传到服务器吗?
不会。本工具所有解析、验签、签名都通过浏览器原生 Web Crypto API 在前端完成;Token、Header、Payload、Signature、Secret / 私钥、生成的密钥对都不会发送到任何服务器。打开浏览器开发者工具的 Network 面板可以看到没有任何出站请求承载 Token 内容。页面加载完成后断网仍可继续使用。
JWT 适合存用户敏感信息吗?
**不适合**。JWT Payload 默认是明文可读——任何拿到 Token 的人都能 Base64URL 解码看到内容,不存在加密。所以**绝对不要**把密码、身份证号、银行卡号、API Key、Access Token、Refresh Token 等明文敏感信息放进 JWT。需要加密请用 JWE(RFC 7516)而不是 JWS。JWT 适合放非敏感的 Claims(用户 ID、角色、过期时间、租户 ID),敏感数据由服务端按 sub 二次查询。
故障排查
签名失败:「Invalid Signature / signature is invalid」
Token 与验证密钥不匹配。常见原因:(1) 服务端用的密钥和你粘到工具里的密钥不一致(最常见);(2) 密钥含不可见字符(末尾空格、换行、零宽字符);(3) Base64 与 Base64URL 混用;(4) 算法选错(Header 写 HS256,服务端却按 RS256 验签,或反之)。先核对密钥字节级是否完全一致:注意 PEM 末尾的换行符、HMAC secret 末尾的空格、JWK 的 `k` 值是否被错误地 URL 解码过。再确认工具里选的算法与 Token Header.alg 一致。必要时用本工具的「解码 + 验签」功能直接复现,看错误是否在「解码成功 → 验签失败」这一步。
HTTP 401 Unauthorized:Token Expired / iat in the future
签名校验通过,但 `exp` 已过(Token Expired)、`nbf` 还未到(Not Before)、`iat` 比服务器当前时间还靠后(多见于时钟不同步)。另一种常见情况是 `aud`(audience)不对:Token 是给 App A 签的,被错放到 App B 校验。用本工具的 Claims 高亮区一眼看出 exp / nbf / iat 状态。exp 红色 = 已过期,请重新签发;nbf 红色 = 尚未生效,检查 iat 是否是未来时间;aud 红色 = 受众错,检查服务端是否配置了正确的 audience。
PEM / JWK 格式报错:无法导入密钥
PEM 字符串里多了空行 / 少了头尾标记(`-----BEGIN PUBLIC KEY-----`)、JWK 缺字段(`kty` / `n` / `e` / `kid`)、JWK 里的 `k` 值没去 Base64URL Padding(应为 `=` 补齐或严格去 `=`)、RSA 私钥被错当成公钥导入、Ed25519 私钥(32 字节 seed)误用 64 字节长度。用 `openssl rsa -in key.pem -pubout -outform PEM` 或 `openssl ec -in key.pem -pubout` 重新导出标准 PKIX PEM;JWK 用 OIDC Discovery `/.well-known/jwks.json` 的原始输出,不要自己手动转码。本工具会自动识别 PEM 头、缺失 Padding、JWK 关键字段缺失并给出提示。
RS256 与 PS256 跨语言签名验证失败
RS256 用 RSASSA-PKCS1-v1_5,PS256 用 RSA-PSS。两者**不能互验**——同一对 RSA 密钥签出来的 RS256 Token 用 PS256 验签必然失败,签名长度还可能差几个字节。确认签发方和验证方使用同一种算法。AWS SigV4 用 PS256,多数 OIDC IdP 用 RS256。RSA-PSS 还有 `saltLength` 参数,OpenSSL 默认 32、jose 默认 32、Go 用 `rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}` 才对得上,跨语言联调务必先固定这个值。
alg: none 攻击 / HS256 密钥替换攻击
服务端按 Token Header 中声明的 `alg` 选择验签算法,攻击者把 Header 改成 `alg: none`(无签名)或改成 `HS256`(用对称密钥当公钥来骗 RSA 服务端),绕过验证。历史上 CVE-2015-9235(jsonwebtoken)、CVE-2022-23529(多个 Node 库)都源自这里。服务端必须强制白名单算法,例如 `algorithms: ['RS256']`,禁止让 Token 告诉你用哪个算法。本工具在 UI 上同时显示 Header.alg 与你实际选择的算法,并在两者不一致时高亮提示——这就是在为「客户端不该信 Header.alg」做演示。
Privacy & Security
本 JWT 工作台 100% 在你的浏览器内运行,依赖浏览器原生 Web Crypto API。你粘贴的 Token、Header、Payload、Signature、HMAC Secret、RSA/ECDSA 私钥、生成的密钥对、所有签名验签计算都只在本地完成,不经过任何服务器,不写日志、不做埋点、不缓存 Token。我们没有能力访问你的输入(页面加载完成后即可断网使用)。安全最佳实践:永远不要把生产环境的长期 Token 与生产私钥贴到任何在线工具上,本工具适合调试、联调、学习、生成测试 Token,但**生产 Secret / 私钥应在本地受控环境处理**。
Supported Video Formats
| Format | MIME | Browser support | When to use |
|---|---|---|---|
| HS256 / HS384 / HS512 | HMAC + SHA-256/384/512 | 全平台 | 对称密钥算法。签发与验签用同一 Secret,简单高效,适合服务集群内部可信环境。Secret 至少 32 字节随机数。 |
| RS256 / RS384 / RS512 | RSASSA-PKCS1-v1_5 + SHA-2 | Web Crypto API | 最常见的非对称算法。签发用私钥,验签用公钥。多数 OIDC IdP、API 网关、企业 SSO 默认使用 RS256。 |
| PS256 / PS384 / PS512 | RSA-PSS + SHA-2 | Web Crypto API | RSA-PSS 是 RS256 的更新版,安全性更高。AWS SigV4、AWS Cognito、新晋 OIDC IdP 倾向使用。saltLength 必须显式指定。 |
| ES256 / ES384 / ES512 | ECDSA + P-256/P-384/P-521 | Web Crypto API | 椭圆曲线签名。签名长度短(ES256 仅 64 字节)、性能好,JWT 体积更小。Apple Sign in with Apple 默认使用 ES256。 |
| EdDSA(Ed25519) | Ed25519 / Ed448 | Web Crypto API | 下一代高性能签名算法。确定性签名(同一消息同一密钥始终同结果),无随机数风险,OAuth 2.1 推荐算法。 |
Authoritative References
- 安全字符串比较
- 二进制编码解码
- 凯撒密码
- 摩尔斯电码
- 十六进制编码解码
- 视频转 Base64
- Base64 转视频
- 图片转 Base64
- Base64 转图片
- 文本转 Base64
- Base64 转文本
- 文件哈希校验
- 文件转 Base64
- Base64 转文件
- 音频转Base64
- Base64转音频
- AES 加密解密
- DES 加密解密
- Base32 编码解码
- Base58 编码解码
- Base64 编码
- Base64 解码
- Base64 比较
- Base64 拆分
- Base64 多行合并
- Base64 格式化
- Base64 格式校验
- Base64 批量编码
- Base64 批量解码
- Base64 清理
- Base64 填充处理
- Base64 长度统计
- Base64 转十六进制
- Base64 DataURL 转换
- Base64-Hex 互转
- Base85 编码解码
- HMAC 生成与验证
- PBKDF2 密钥派生
- MD5 哈希值
- SHA-256 哈希
- SHA1 哈希
- SHA512 哈希
- JWT 解码、验证与生成
- HTML 编码解码
- Unicode 转义
- URL 编码
- URL Safe Base64
- MIME Base64
- Java 代码混淆
- JavaScript 代码混淆
- PHP 混淆
- Python混淆