上传文件
  1. base64hub
  2. Web 与令牌工具
  3. JWT 编码器

JWT 编码与签名工具

以 JSON 编辑头部和载荷,选择算法并粘贴密钥或私钥,签名后的令牌会随输入实时更新。对于 RSA、ECDSA 和 EdDSA,工具还能生成全新的密钥对及对应的 JWKS。

免费 无需注册,不限次数 本地 不上传任何内容 密钥 RSA、P-256/384/521 和 Ed25519 密钥对 更新于 2026年10月27日
令牌

在你的浏览器中处理。此页面无法将你的数据发送到任何地方: 我们如何确认

如何创建签名的 JWT

  1. 选择 算法。头部(JSON) 中的 alg 字段会自动跟随所选算法。
  2. 编辑 载荷(JSON)。+ iat 设为现在 会插入当前时间,+ exp 设为 1 小时后 会把过期时间设为一小时之后;两者都使用秒,这是 JWT 规范的要求。
  3. 对于 HS256、HS384 或 HS512,输入 密钥,并把 密钥格式 设为文本、Base64 或 Hex。对于其他算法,粘贴私钥或按 生成密钥对。
  4. 按 复制令牌,或按 在解码器中打开 进行检查:解码并验证 标签页会打开,并自动填好令牌和验证密钥。

页面加载时的示例是一个用密钥 base64hub-demo-secret 签名的有效 HS256 令牌,你可以改动一个声明,看签名随之变化。

选择算法

算法密钥类型谁能验证令牌中的签名
HS256共享密钥(HMAC-SHA256)持有同一密钥的任何人43 个字符
RS256、PS256RSA 私钥,2048 位或更长持有公钥的任何人342 个字符(RSA-2048)
ES256P-256 曲线上的 EC 私钥持有公钥的任何人86 个字符
EdDSAEd25519 私钥持有公钥的任何人86 个字符

当同一个服务负责签名和验证时(例如由同一后端校验的会话令牌),HS256 是最简单的选择。一旦需要第二方来验证,与对方共享 HMAC 密钥也就让对方能够签发令牌,这时应改用非对称算法,只公开公钥。ES256 和 EdDSA 生成的令牌比 RSA 短得多,这对 Cookie 和请求头很重要。PS256 是使用 PSS 填充方案的 RSA;只有在所有验证方都支持时才选它。

列表中的 none 用于测试解析器。alg: none 的令牌签名为空,任何接受它的服务器都可能被任何人欺骗,所以工具会对此发出警告。

本编码器接受和生成的密钥

签名时,它接受 PEM PKCS#8 密钥(BEGIN PRIVATE KEY)、PKCS#1 RSA PRIVATE KEY、SEC1 EC PRIVATE KEY 或私钥 JWK。如果不用生成器,而是用 OpenSSL 制作测试密钥:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out rsa.pem
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ec.pem
openssl genpkey -algorithm ed25519 -out ed.pem
openssl pkey -in ec.pem -pubout -out ec.pub

生成密钥对 会根据算法,在浏览器中用 WebCrypto 生成 RSA-2048、P-256、P-384、P-521 或 Ed25519 密钥。你会得到 PKCS#8 PEM 格式的私钥、SPKI PEM 格式的公钥,以及一个 JWKS,其 kid 是该密钥的 RFC 7638 指纹。这个 JWKS 就是你应该通过 jwks_uri 提供给验证方下载的内容。

对于 HS256,密钥按字节使用。如果你的服务器从环境变量读取密钥并先做 Base64 解码,这里也要把 密钥格式 设为 Base64,否则签名对不上。Base64 密钥生成器 的 JWT 密钥预设生成的值是 Base64URL,解码后为 32 字节。

载荷中应该放哪些声明

一个实用的访问令牌通常包含 iss(谁签发的)、sub(关于谁)、aud(给哪个 API 用)、iat 和一个较短的 exp。如果需要吊销单个令牌,再加上 jti。时间是自 1970 年起的整秒数;在 JavaScript 中生成时请用 Math.floor(Date.now() / 1000),因为 Date.now() 返回的是毫秒。

载荷只是签名,从不加密。任何看到令牌的人都能用 JWT 解码器 解码,所以不要放入密码、API 密钥,以及你不会打印到日志中的个人数据。

在代码中签名 JWT

这种格式简单到可以手工构造,调试库的时候很有帮助。下面这个 Node.js 函数,对同样的输入生成的令牌与 PyJWT 的 jwt.encode(payload, secret, algorithm="HS256") 完全一致:

const crypto = require("crypto");

const b64url = (obj) => Buffer.from(JSON.stringify(obj)).toString("base64url");

function signHS256(payload, secret) {
  const input = b64url({ alg: "HS256", typ: "JWT" }) + "." + b64url(payload);
  const sig = crypto.createHmac("sha256", secret).update(input).digest("base64url");
  return input + "." + sig;
}

console.log(signHS256({ sub: "user-42", iat: 1767225600, exp: 1767229200 },
                      "replace-me-with-32-random-bytes!"));

它输出 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQyIiwiaWF0IjoxNzY3MjI1NjAwLCJleHAiOjE3NjcyMjkyMDB9.F3xnXnXW8nUQy-Ay37DF626Lb5lHPKI3IFvqoEf3mTw。在本页输入同样的头部、载荷和密钥,会得到同样的字符串。工具在签名前会压缩 JSON,所以缩进无关紧要,但键的顺序有关,因为签名覆盖的是确切的字节。生产环境请使用有人维护的库;编码相关内容见 Node.js 中的 Base64。

常见问题

HS256 的密钥应该多长?

至少 256 位,也就是 32 个随机字节。RFC 7518 要求密钥长度不短于哈希输出。类似密码的短密钥可以仅凭一个令牌离线暴力破解,所以请用 Base64 密钥生成器 生成。

应该用 HS256 还是 RS256?

如果签发和验证令牌的是同一个服务,用 HS256,因为双方共享同一个密钥。如果其他方也必须验证,用 RS256、ES256 或 EdDSA,因为他们只拿到公钥,无法自己签发令牌。

为什么我的私钥报错?

受密码保护的密钥(BEGIN ENCRYPTED PRIVATE KEY)会被拒绝。用 openssl pkey -in key.pem -out plain.pem 去掉密码,再粘贴结果。密钥类型也必须与算法匹配:EC 密钥不能签名 RS256。

怎样给令牌添加 kid?

按 生成密钥对 后,从 JWKS 输出中复制 kid,添加到头部 JSON 中,例如 "kid": "…"。验证方会用它从自己的密钥集中挑选正确的密钥。