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 这类严格的库会直接拒绝:
| 算法 | 哈希 | 密钥最小长度 |
|---|---|---|
| HS256 | SHA-256 | 32 字节 (256 位) |
| HS384 | SHA-384 | 48 字节 (384 位) |
| HS512 | SHA-512 | 64 字节 (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
# HS256 → 32 bytes (64 hex chars); HS512 → 64 bytes (128 hex chars)
JWT_SECRET=your-generated-secret2. 使用 jsonwebtoken——经典的 Node.js 库——用密钥和显式指定的算法签名与验签:
// 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 — 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 模块能生成同类密钥——按你的算法选择字节数:
# 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 能力。