免费工具

JWT Secret 生成器

生成用于 HS256、HS384 或 HS512 签名的加密安全 JWT_SECRET。密钥通过 Web Crypto API 在浏览器本地创建,长度按 RFC 7518 下限设定——HS256 用 32 字节,HS512 用 64 字节。

格式
强度
生成的密钥
 

使用 Web Crypto API 在浏览器本地生成,不会向任何服务器发送数据。

什么是 JWT 密钥?

JSON Web Token 之所以可信,全靠它的签名。使用 HS256、HS384、HS512 算法时,这个签名是用一个共享密钥——也就是 JWT_SECRET——对 header 和 payload 计算出的 HMAC。用户登录时服务端用它签发令牌,之后的每个请求都先验签,再信任令牌里的声明。

这意味着密钥是攻击者与伪造令牌之间唯一的屏障。知道密钥的人可以为任意用户 ID、任意角色、任意过期时间签发 JWT。因此它必须是随机的、长度满足所选算法的要求、只存放在服务端,并且永远不进入版本控制。

JWT 密钥应该多长?

RFC 7518(JSON Web Algorithms)§3.2 规定 HMAC 密钥长度不得小于哈希输出长度。使用更短的密钥不只是削弱签名强度——它直接违反规范,jose 这类严格的库会直接拒绝:

算法哈希密钥最小长度
HS256SHA-25632 字节 (256 )
HS384SHA-38448 字节 (384 )
HS512SHA-51264 字节 (512 )

本工具默认生成 32 字节,正好是 HS256 的下限。如果你用 HS512 签名,请把强度切换到 64 字节(HS384 需要 48 字节,选 64 同样合适)。hex 格式每字节占两个字符,所以 32 字节密钥是一个 64 字符的字符串。

为什么短的、人类可读的密钥不行?因为 HS256 的安全性受限于密钥的熵,而不是 SHA-256 本身。一个由常见单词拼成的 12 字符密码大约只有 40 位熵;一台跑 hashcat JWT 模式的 GPU 机器每秒尝试数十亿个候选值,只需截获一个令牌就能离线破解出来。而随机的 256 位密钥完全不在暴力破解的范围之内。

对称(HS256)与非对称(RS256 / ES256)

HS256 是对称算法:同一个密钥既签名又验签。它速度快、令牌体积小、配置只需一个环境变量——当同一个后端既签发又消费自己的令牌时,这是正确的选择,绝大多数 Next.js 应用和单体服务都属于这种情况。

RS256 和 ES256 是非对称算法:私钥签名,公钥验签。当其他方需要验证令牌却不能拥有签发能力时使用它们——API 网关、移动端、微服务或任何第三方。公钥可以通过 JWKS 公开发布,私钥永远不离开签发方。

无论选哪种,都要在验签端固定允许的算法列表。让令牌 header 决定算法(臭名昭著的 alg: none 和 RS256 → HS256 混淆攻击)曾经攻破过真实系统;jsonwebtoken 和 jose 都支持显式传入 algorithms 列表,正是为了这个原因。

如何在 Node.js / Next.js 中使用 JWT 密钥

1. 把生成的密钥写入 .env 文件:

.env
# .env
# HS256 → 32 bytes (64 hex chars); HS512 → 64 bytes (128 hex chars)
JWT_SECRET=your-generated-secret

2. 使用 jsonwebtoken——经典的 Node.js 库——用密钥和显式指定的算法签名与验签:

lib/jwt.ts
// lib/jwt.ts — jsonwebtoken (Node.js runtime)
import jwt from "jsonwebtoken";

const secret = process.env.JWT_SECRET!;

export function signToken(payload: object) {
  return jwt.sign(payload, secret, { algorithm: "HS256", expiresIn: "1h" });
}

export function verifyToken(token: string) {
  // Always pin the algorithm list — never let the token pick it.
  return jwt.verify(token, secret, { algorithms: ["HS256"] });
}

3. 使用 jose——基于 Web Crypto 构建,因此也能在 Edge 运行时和 Next.js 中间件里运行——需要先把密钥编码为字节:

lib/jwt.ts
// lib/jwt.ts — jose (works in Edge runtime and middleware)
import { SignJWT, jwtVerify } from "jose";

const secret = new TextEncoder().encode(process.env.JWT_SECRET);

export async function signToken(payload: Record<string, unknown>) {
  return new SignJWT(payload)
    .setProtectedHeader({ alg: "HS256" })
    .setIssuedAt()
    .setExpirationTime("1h")
    .sign(secret);
}

export async function verifyToken(token: string) {
  const { payload } = await jwtVerify(token, secret, {
    algorithms: ["HS256"],
  });
  return payload;
}

用命令行生成 JWT 密钥

更喜欢终端?openssl 或 Node 的 crypto 模块能生成同类密钥——按你的算法选择字节数:

terminal
# HS256 — 32 bytes
openssl rand -hex 32

# HS512 — 64 bytes
openssl rand -hex 64

# Node.js, no openssl needed
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

用的是认证库而不是手写 JWT?请使用 NextAuth Secret 生成器 Better Auth Secret 生成器——它们需要的是同类密钥,只是变量名不同。

轮换 JWT 密钥

轮换密钥意味着所有用旧值签名的令牌都会验签失败——对于短生命周期的访问令牌这只是短暂的抖动,对于长生命周期的令牌则是一次全员登出。任何疑似泄露后都应立即轮换;即使没有泄露,也建议按固定周期(常见为每季度)轮换。

要做到零停机轮换,可以在令牌 header 中加入密钥 ID(kid),让验签端在一个令牌生命周期内同时接受当前和上一个密钥,然后再移除旧密钥。如果无法改动验签端,就在低流量时段轮换,并保持访问令牌的有效期足够短,把影响控制在可接受范围内。

常见问题

HS256 的 JWT 密钥应该多长?

至少 32 字节(256 位)随机数据,这是 RFC 7518 对 HS256 的下限,也是本工具的默认值,对应 64 个 hex 字符。HS384 需要 48 字节,HS512 需要 64 字节——两者都在上方选择 64 字节强度即可。

JWT_SECRET 应该用 hex 还是 Base64?

都可以——库把密钥当作字节处理,重要的是输入了多少随机字节。hex 不含特殊字符,对 .env 文件和 shell 脚本最友好,所以本页默认使用 hex。Base64 在相同熵下更短;只要避免出现引号或空格即可。

能用密码或口令短语当 JWT 密钥吗?

不能。HMAC 的安全性上限由密钥的熵决定,而任何人类记得住的东西 GPU 都猜得出来。hashcat、jwt_tool 这类工具只需截获一个令牌就能离线破解弱 HS256 密钥。请始终使用满足所需长度的随机生成密钥。

在浏览器里生成密钥安全吗?

安全。本工具使用 Web Crypto API 的 crypto.getRandomValues——与 openssl 和 Node 的 crypto.randomBytes 依赖同一等级的加密安全随机源。密钥完全在你的设备上生成,不会发送到任何地方。复制到环境变量后关掉标签页即可。

这个免费工具由 NEXTY.DEV —— Next.js SaaS 模板 构建和维护,模板内置用户认证、Stripe 支付和 AI 能力。