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

NodeJS服务器RSA加密,Flutter客户端解密方案求助

NodeJS RSA加密 + Flutter 解密可行方案

核心问题原因

加密解密失败通常是密钥格式不兼容、填充/哈希算法不匹配导致的,以下是统一配置后的可运行方案。


第一步:标准化NodeJS端加密代码

确保node-rsa的加密参数与Flutter端兼容,显式指定填充方式、哈希算法和密钥格式:

const NodeRSA = require('node-rsa');

// 生成2048位密钥对,指定PKCS1_OAEP填充、SHA-256哈希(Flutter端易支持)
const key = new NodeRSA({b: 2048}, {
  encryptionScheme: 'pkcs1_oaep',
  hash: 'sha256'
});

// 导出标准PKCS8格式的公钥/私钥
const publicKeyPem = key.exportKey('pkcs8-public-pem');
const privateKeyPem = key.exportKey('pkcs8-private-pem');
console.log('公钥(用于加密):\n', publicKeyPem);
console.log('私钥(用于Flutter解密):\n', privateKeyPem);

// 加密文本,输出base64格式
const text = 'Hello RSA!';
const encrypted = key.encrypt(text, 'base64');
console.log('加密结果:', encrypted);

第二步:Flutter端解密实现

使用pointycastle(最可靠的加密底层库)实现对应解密逻辑:

1. 添加依赖

在pubspec.yaml中加入:

dependencies:
  pointycastle: ^3.7.3
  convert: ^3.1.1

2. 解密代码实现

import 'dart:convert';
import 'package:pointycastle/asymmetric/api.dart';
import 'package:pointycastle/asymmetric/oaep.dart';
import 'package:pointycastle/asymmetric/rsa.dart';
import 'package:pointycastle/digests/sha256.dart';
import 'package:pointycastle/random/fortuna_random.dart';
import 'package:pointycastle/asymmetric/asn1.dart';

// 解析PKCS8格式PEM私钥为RSAPrivateKey
RSAPrivateKey parsePrivateKeyFromPem(String pem) {
  // 去除PEM头、尾和换行
  final cleanPem = pem.split('\n')
      .where((line) => !line.startsWith('-----BEGIN') && !line.startsWith('-----END') && line.isNotEmpty)
      .join('');
  final keyBytes = base64Decode(cleanPem);
  final asn1Parser = ASN1Parser(keyBytes);
  final seq = asn1Parser.nextObject() as ASN1Sequence;
  
  return RSAPrivateKey(
    (seq.elements[1] as ASN1Integer).valueAsBigInteger,
    (seq.elements[2] as ASN1Integer).valueAsBigInteger,
    (seq.elements[3] as ASN1Integer).valueAsBigInteger,
    (seq.elements[4] as ASN1Integer).valueAsBigInteger,
    (seq.elements[5] as ASN1Integer).valueAsBigInteger,
    (seq.elements[6] as ASN1Integer).valueAsBigInteger,
    (seq.elements[7] as ASN1Integer).valueAsBigInteger,
    (seq.elements[8] as ASN1Integer).valueAsBigInteger,
  );
}

// RSA解密函数
String rsaDecrypt(String encryptedBase64, String privateKeyPem) {
  final privateKey = parsePrivateKeyFromPem(privateKeyPem);
  // 对应NodeJS端的PKCS1_OAEP + SHA-256配置
  final cipher = OAEPEncoding(RSAEngine())
    ..init(
      false, // false代表解密模式
      ParametersWithRandom(
        PrivateKeyParameter<RSAPrivateKey>(privateKey),
        FortunaRandom(),
      ),
      OAEPParameters(SHA256Digest(), SHA256Digest(), null),
    );

  final encryptedBytes = base64Decode(encryptedBase64);
  final decryptedBytes = cipher.process(encryptedBytes);
  return utf8.decode(decryptedBytes);
}

// 使用示例
void main() {
  const encryptedStr = "替换为NodeJS输出的加密字符串";
  const privateKey = "替换为NodeJS导出的PKCS8私钥";
  final result = rsaDecrypt(encryptedStr, privateKey);
  print("解密结果:$result"); // 输出 Hello RSA!
}

关键兼容注意事项

  • 填充/哈希必须完全匹配:如果NodeJS端改用pkcs1填充,Flutter端需替换为PKCS1Encoding(RSAEngine()),哈希算法也要对应一致
  • 密钥格式统一:必须用PKCS8格式,避免node-rsa默认的其他格式导致Flutter解析失败
  • 密钥长度一致:两端都使用2048位(或4096位)密钥,不要混用不同长度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:15:38