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

如何用RSA公钥验证文件?我的Node.js验证代码返回false

RSA签名验证失败的问题分析与修复

嘿,我一眼就看到你代码里的两个关键问题,这就是为什么验证一直返回false的原因:


1. 对verify()方法的返回值理解错误

你在验证代码里写了:

const testSignature = verifier.verify(publicKey, fileSignature, 'base64');
// ...
if (testSignature === fileHash) console.log("ok");

这里完全搞反了逻辑!verifier.verify()的返回值是一个布尔值,它直接告诉你签名是否有效(公钥能否验证签名和内容的匹配性),而不是返回文件的哈希值。你拿这个布尔值和fileHash字符串比较,肯定永远不相等,而且这也不是验证签名的正确方式。

2. 签名生成与验证的内容不匹配

看你的签名生成代码:

signer.update(fileHash); // 你是对文件的hex哈希字符串进行签名
fileSignature = signer.sign(privateKey, 'base64');

但在验证代码里,你创建了verifier对象后,根本没有调用verifier.update()来传入要验证的内容!这就相当于你让验证器去验证一个空内容的签名,自然会返回false。

而且更规范的做法是:签名时直接对原始文件内容进行签名(而不是先算哈希再签名),因为crypto.createSign('RSA-SHA256')本身就会先计算SHA256哈希再用RSA签名,你额外再算一次哈希属于画蛇添足,还容易出错。


修正后的完整代码

首先是签名生成代码(优化版,直接处理文件流)

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

const signer = crypto.createSign('RSA-SHA256');
const fd = fs.createReadStream("path/to/file");

fd.on('end', () => {
  signer.end();
  const privateKey = fs.readFileSync('keys/private_key.pem');
  const fileSignature = signer.sign(privateKey, 'base64');
  console.log('生成的签名:', fileSignature);
  // 这里可以把签名保存到文件或者其他地方
});

fd.pipe(signer); // 直接把文件流导入signer,自动处理内容

然后是验证代码(对应优化后的签名流程)

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

const verifier = crypto.createVerify('RSA-SHA256');
const fd = fs.createReadStream("path/to/my/file");

fd.on('end', () => {
  verifier.end();
  const publicKey = fs.readFileSync('keys/public_key.pem');
  // 假设fileSignature是你拿到的正确签名字符串
  const isSignatureValid = verifier.verify(publicKey, fileSignature, 'base64');
  
  console.log("签名是否有效:", isSignatureValid);
  if (isSignatureValid) {
    console.log("验证通过:文件未被篡改,签名合法");
  } else {
    console.log("验证失败:文件被篡改或签名无效");
  }
});

fd.pipe(verifier); // 同样直接把文件流导入verifier

如果你坚持要保留原有的“先算哈希再签名”的方式(不推荐)

那验证代码也必须对应地先计算出相同的hex哈希,然后对这个哈希字符串做update:

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

var hash = crypto.createHash("sha256");
hash.setEncoding("hex");
var fd = fs.createReadStream("path/to/my/file");

fd.on("end", function() {
  hash.end();
  var fileHash = hash.read();
  const publicKey = fs.readFileSync('keys/public_key.pem');
  const verifier = crypto.createVerify('RSA-SHA256');
  
  // 关键:必须update和签名时相同的内容——也就是fileHash这个hex字符串
  verifier.update(fileHash);
  const isSignatureValid = verifier.verify(publicKey, fileSignature, 'base64');
  
  console.log("签名是否有效:", isSignatureValid);
  if (isSignatureValid) {
    console.log("验证通过");
  } else {
    console.log("验证失败");
  }
});
fd.pipe(hash);

但还是推荐直接用文件流处理的方式,更简洁也不容易出错,因为createSign和createVerify已经内置了哈希计算的逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:20:24