You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用RS256算法签名JWT首次调用报错求助

RSA私钥签名JWT首次调用报错、二次调用正常的问题排查与解决

问题描述

我通过以下命令生成RSA私钥和公钥:

ssh-keygen -q -t rsa -N '' -P "" -b 4096 -m PEM -f private.key
openssl rsa -in private.key -pubout -outform PEM -out private.key.pub

随后用私钥签名JWT,代码如下:

const privateKey = fs.readFileSync("private.key");
const token = jwt.sign(
      { payload: "text" },
      privateKey,
      { algorithm: 'RS256' },);

但首次调用该方法时会抛出错误secretOrPrivateKey must be an asymmetric key when using RS256,再次调用则正常运行。我试过Stack Overflow上的其他方案但没解决,当前使用Ubuntu系统,Node.js版本为16.13.00。


问题原因

这种首次报错、二次正常的现象,核心原因是密钥文件读取的时机或完整性问题:

  • 虽然fs.readFileSync是同步方法,但如果密钥生成后立即执行签名逻辑,系统可能还未完成文件的持久化或元数据同步,导致首次读取到不完整的密钥内容,jsonwebtoken库无法识别为有效的RSA私钥,从而抛出错误。
  • 二次调用时,文件已经被系统缓存,readFileSync能读取到完整的密钥内容,验证自然通过。
  • 另外,Node.js 16.13.0属于较早的版本,其fs模块在某些文件系统场景下,同步读取可能存在短暂的内容不一致问题。

解决方法

1. 确保密钥生成完成后再执行签名逻辑

如果是脚本中连续执行密钥生成和签名操作,必须确保密钥生成命令完全执行完毕再调用Node.js代码:

  • Shell脚本中可使用wait命令等待密钥生成进程结束;
  • Node.js中通过子进程执行密钥生成时,需监听子进程的exit事件,确认完成后再读取文件。

2. 读取密钥时添加格式验证

在读取私钥后先验证格式有效性,避免传递无效内容给jwt.sign:

const fs = require('fs');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');

function getValidPrivateKey() {
  const keyContent = fs.readFileSync("private.key", 'utf8');
  // 检查是否为标准PEM格式RSA私钥
  if (!keyContent.includes('-----BEGIN RSA PRIVATE KEY-----') || !keyContent.includes('-----END RSA PRIVATE KEY-----')) {
    throw new Error('无效的RSA私钥格式');
  }
  // 提前尝试解析密钥,捕获格式错误
  try {
    crypto.createPrivateKey(keyContent);
    return keyContent;
  } catch (err) {
    throw new Error('解析私钥失败:' + err.message);
  }
}

// 使用验证后的密钥签名
const privateKey = getValidPrivateKey();
const token = jwt.sign({ payload: "text" }, privateKey, { algorithm: 'RS256' });

3. 缓存已验证的密钥

首次读取并验证通过后,将密钥缓存到内存中,后续调用直接使用缓存内容,避免重复读取文件:

let cachedPrivateKey = null;

function signJwt(payload) {
  if (!cachedPrivateKey) {
    const keyContent = fs.readFileSync("private.key", 'utf8');
    // 此处可加入上述密钥验证逻辑
    cachedPrivateKey = keyContent;
  }
  return jwt.sign(payload, cachedPrivateKey, { algorithm: 'RS256' });
}

4. 升级Node.js版本(可选)

Node.js 16.13.0的后续小版本修复了一些文件系统和加密模块的偶发问题,升级到16.x最新稳定版或更高版本(如18.x),可能直接解决这类文件读取异常。

内容的提问来源于stack exchange,提问作者FaFa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 11:42:48