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

NodeJS自定义RSA实现解密结果异常问题排查

RSA解密结果不符的问题排查与修复

我来帮你搞定这个问题——你的解密环节出错的核心原因是JavaScript的Math.pow()处理大整数幂运算时会丢失精度,下面详细拆解问题并给出可行的修复方案:

问题根源:大数幂运算的精度限制

JavaScript里的Number类型是64位双精度浮点数,它只能精确表示小于2^53的整数。当你用Math.pow(char, d)计算加密后数值的高次幂时(比如8^29,这个数远大于2^53),Math.pow()返回的是一个近似值,而非精确的整数,后续取模%n自然会得到错误的结果,导致解密出的字符和原消息不符。

举个例子:8^29的精确值是154742504910672534362390528,但Math.pow(8,29)返回的是近似值,丢失了末尾的精确数位,这就直接导致解密取模出错。

修复方案:使用快速幂取模算法

解决这个问题的关键是避免直接计算完整的大幂值,改用快速幂取模(模幂运算)——在计算过程中不断对结果取模,让数值始终保持在较小的范围内,从而避免精度丢失。

修改后的完整代码

const p = 7; // 选择的质数
const q = 13; // 选择的质数
const n = p * q;
const e = 5; // 公钥指数
const publicKey = [e, n]; // 公钥(注:你原代码里的密钥注释写反了)
const d = 29; // 私钥指数
const privateKey = [d, n]; // 私钥

// 快速幂取模函数:安全计算 (base^exponent) % mod
function modPow(base, exponent, mod) {
  let result = 1;
  base = base % mod; // 确保基数先落在mod范围内
  while (exponent > 0) {
    // 如果指数是奇数,将当前基数乘入结果并取模
    if (exponent % 2 === 1) {
      result = (result * base) % mod;
    }
    // 指数折半,基数平方后取模
    exponent = Math.floor(exponent / 2);
    base = (base * base) % mod;
  }
  return result;
}

let message = 'hello';
let encrypted = [];
message = message.toUpperCase();

// 加密流程
for (let i = 0; i < message.length; i++) {
  const charCode = message.charCodeAt(i) - 64; // 转换为A=1, B=2...Z=26的数值
  const cipher = modPow(charCode, e, n); // 用快速幂取模计算加密值
  encrypted.push(cipher);
}

// 解密流程
console.log('解密结果:');
encrypted.forEach(cipher => {
  const originalCharCode = modPow(cipher, d, n); // 用快速幂取模计算明文数值
  console.log(String.fromCharCode(originalCharCode + 64));
});

额外注意事项

  1. 密钥注释修正:你原代码里把公钥和私钥的注释写反了——[e, n]是公钥(用于加密),[d, n]是私钥(用于解密),别搞混哦。
  2. 密钥合法性验证:你的密钥是符合RSA要求的:φ(n)=(p-1)(q-1)=612=72,e*d=5*29=145,145%72=1,满足(e*d) % φ(n) = 1的核心条件,所以密钥本身是没问题的。

运行修改后的代码,解密结果就会正确输出HELLO啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:27:54