我需要用加密软件在信息上签名.NodeJS中的sign()函数以获取有效的JWT.

Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==

我试图得到一个签名:

const getJWT = () => {
  const privateKey =
    "Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==";
  const payload = {
    iss: "test",
    aud: "test.com",
    iat: 1650101178,
    exp: 1650101278,
    sub: "12345678-1234-1234-1234-123456789123"
  };
  const token = encode(payload, privateKey);
  return token
};

const encode = (payload, key) => {
  const header = {
    typ: "JWT",
    alg: "EdDSA"
  };
  const headerBase64URL = base64url(JSON.stringify(header));
  const payloadBase64URL = base64url(JSON.stringify(payload));
  const msg = Buffer.from(`${headerBase64URL}.${payloadBase64URL}`);
  const keyDecoded = Buffer.from(key, "base64");
  const signature = crypto.sign("Ed25519", msg, keyDecoded); //Here is the problem
  const signatureBase64url = base64url(Buffer.from(signature));
  return `${msg}.${signatureBase64url}`;
};

我收到了这个错误:

internal/crypto/sig.js:142
  return _signOneShot(keyData, keyFormat, keyType, keyPassphrase, data,
         ^

Error: error:0909006C:PEM routines:get_name:no start line

  library: 'PEM routines',
  function: 'get_name',
  reason: 'no start line',
  code: 'ERR_OSSL_PEM_NO_START_LINE'

如何将私钥调整为有效格式?

推荐答案

crypto.sign()方法要求Ed25519使用PKCS#8格式的私钥.您的密钥是一个原始密钥,由原始私有32字节密钥和原始公共32字节(base64编码)串联而成.DER编码的PKCS#8密钥可以按如下方式导出和导入:

  • Base64解码你的密钥.使用原始64字节密钥(即原始私钥)的前32字节.
  • 为专用Ed25519密钥(十六进制)指定以下前缀:302e020100300506032b657004220420
  • 导入DER编码的PKCS#8键.

因此,getJWT()中的密钥导入必须更改如下:

const privateKey = toPkcs8der('Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==');

具有

const toPkcs8der = (rawB64) => {
    var rawPrivate = Buffer.from(rawB64, 'base64').subarray(0, 32);
    var prefixPrivateEd25519 = Buffer.from('302e020100300506032b657004220420','hex');
    var der = Buffer.concat([prefixPrivateEd25519, rawPrivate]);
    return crypto.createPrivateKey({key: der, format: "der", type: "pkcs8"})
}

此外,在encode()函数中:

  • 拆下管路const keyDecoded = Buffer.from(key, "base64")

  • Create the signature 具有

    const signature = crypto.sign(null, msg, key)
    

    请注意,对于Ed25519,必须将null作为sign()调用中的第一个参数传递.算法来自密钥.

通过这些更改,NodeJS代码将返回以下JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJ0ZXN0IiwiYXVkIjoidGVzdC5jb20iLCJpYXQiOjE2NTAxMDExNzgsImV4cCI6MTY1MDEwMTI3OCwic3ViIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MTIzIn0.f7WG_02UKljrMeVVOTNNBAGxtLXJUT_8QAnujNhomV18Pn5cU-0lHRgVlmRttOlqI7Iol_fHut3C4AOXxDGnAQ

这和expected JWT相符.

Javascript相关问答推荐

将音频记录从js发送到activx-web服务器以保存到磁盘

试图为每支球队生成类似于2024/25年欧洲足联冠军联赛瑞士系统格式的独特比赛配对

TypScript界面中的Infer React子props

if/else JavaScript中的条件行为

将状态向下传递给映射的子元素

我不知道为什么setwritten包装promise 不能像我预期的那样工作

在nextjs服务器端api调用中传递认证凭证

在服务器上放置了Create Reaction App Build之后的空白页面

为什么!逗号和空格不会作为输出返回,如果它在参数上?

使用GraphQL查询Uniswap的ETH价格

如何在每次单击按钮时重新加载HighChart/设置HighChart动画?

对网格项目进行垂直排序不起作用

如何利用CSS中的隐藏元素实现平滑扩展和防止网格行间隙

我想将Sitecore搜索面过滤器从多个转换为单个

MongoDB受困于太多的数据

如何使用<;Link>;执行与JS Reaction中的";window.Location=/GameOverDied;";类似的操作?

React Refs不与高阶组件(HOC)中的动态生成组件一起工作

rxjs在每次迭代后更新数组的可观察值

正则表达式以确定给定文本是否不只包含邮箱字符串

我们是否可以在reactjs中创建多个同名的路由