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

Node.js实现SHA256WithRSA签名遇DECODER routines错误求助

问题

我开发的Node.js(TypeScript)应用需要向Web服务发送签名,要求如下:

  • 基于SHA256WithRSA算法
  • 使用客户端私钥对客户端数据签名并输出签名结果
  • 将签名编码为Base64

我最初尝试用HMAC实现,但发现不符合算法要求:

import { createHmac } from 'crypto';
const signature = createHmac('sha256', config.secret).update(data).digest('hex');
const signature1 = Buffer.from(signature, 'hex').toString('base64')

改用createSign后抛出错误:

import { createSign  } from 'crypto';
const sign = createSign('RSA-SHA256');
sign.update(data);
const signature = sign.sign(config.secret, 'base64');

错误信息:

Error: error:1E08010C:DECODER routines::unsupported
at Object.signOneShot (node:internal/crypto/sig:163:15)

我的私钥是RSA2算法生成的2048位密钥,格式为无PEM标签的纯Base64字符串:

MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcZdmCvpg8tiiKMGs1GkYqNPZtW....

尝试添加PEM标签后仍报错:

const pemKey = `
    -----BEGIN RSA PRIVATE KEY-----
    ${secretkey}
    -----END RSA PRIVATE KEY-----
    `;

也试过crypto.sign的写法,依旧报相同错误:

import * as crypto from 'node:crypto'
const signature =  crypto.sign(
  "sha256",
  Buffer.from(encodedParams),
  {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
  }
).toString('base64')

测试环境:Ubuntu 22.04(Node 18.20)、Mac 11.7.10(Node 20.11),已将OpenSSL从1.1.1升级到3.0,问题未解决。

解决方法

1. 错误根源:私钥解析失败

error:1E08010C:DECODER routines::unsupported本质是OpenSSL无法正确解析你的私钥,核心原因有两个:

  • 纯Base64字符串未按PEM规范分段(要求每64个字符换行)
  • 私钥格式与PEM标签不匹配(比如用了PKCS#1标签但实际是PKCS#8格式)

2. 正确格式化私钥

方式一:修复PKCS#1格式PEM

如果私钥是PKCS#1格式,给纯Base64字符串按64字符分段,再添加对应标签:

// 给纯Base64私钥添加换行,符合PEM规范
const formattedKey = secretKey.match(/.{1,64}/g)?.join('\n') || secretKey;
const pemKey = `-----BEGIN RSA PRIVATE KEY-----\n${formattedKey}\n-----END RSA PRIVATE KEY-----`;

方式二:尝试PKCS#8格式标签

如果私钥是PKCS#8格式(多数工具默认生成),改用对应标签:

const formattedKey = secretKey.match(/.{1,64}/g)?.join('\n') || secretKey;
const pemKey = `-----BEGIN PRIVATE KEY-----\n${formattedKey}\n-----END PRIVATE KEY-----`;

3. 最终签名实现代码

私钥格式修复后,用crypto.sign实现标准SHA256WithRSA(默认使用PKCS#1 v1.5填充,这是该算法的标准要求):

import * as crypto from 'node:crypto';

// 要签名的原始数据
const data = 'your_data_to_sign';
// 你的纯Base64私钥
const secretKey = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCcZdmCvpg8tiiKMGs1GkYqNPZtW....';

// 格式化私钥为标准PEM格式
const formattedKey = secretKey.match(/.{1,64}/g)?.join('\n') || secretKey;
// 先试PKCS#1标签,不行换PKCS#8
const pemKey = `-----BEGIN RSA PRIVATE KEY-----\n${formattedKey}\n-----END RSA PRIVATE KEY-----`;

try {
  const signature = crypto.sign(
    'sha256',
    Buffer.from(data),
    {
      key: pemKey,
      // SHA256WithRSA默认用PKCS1_PADDING,不要用PSS_PADDING(除非服务端明确要求)
      padding: crypto.constants.RSA_PKCS1_PADDING
    }
  ).toString('base64');
  
  console.log('生成的签名:', signature);
} catch (err) {
  console.error('签名失败:', err);
}

4. 关键注意事项

  • 不要随意指定RSA_PKCS1_PSS_PADDING,SHA256WithRSA通常指SHA256哈希+RSA PKCS#1 v1.5填充
  • 确保私钥没有多余空格、换行或特殊字符
  • 如果私钥是加密的(带密码),需要在配置中添加passphrase字段:{ key: pemKey, passphrase: 'your_password' }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 23:13:27