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

Flutter与Node.js双向加密方案问询(偏好AES256)

Flutter 与 Node.js 双向加密方案

一、RSA 双向加密实现

RSA 为非对称加密机制,前端用公钥加密数据,后端用私钥解密;后端用私钥签名数据,前端用公钥验签。该方案完全避开浏览器端依赖库,可彻底解决你遇到的window is undefined问题。

Flutter 端实现(依赖encrypt库)

  1. 在pubspec.yaml添加依赖:
dependencies:
  encrypt: ^5.0.1
  1. 加密/验签代码示例:
import 'package:encrypt/encrypt.dart';

// 后端生成的PEM格式公钥
final publicKey = RSAKeyParser().parse('''-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...(完整公钥内容)
-----END PUBLIC KEY-----''') as RSAPublicKey;

// 公钥加密数据
String rsaEncrypt(String plainText) {
  final encrypter = Encrypter(RSA(publicKey: publicKey));
  return encrypter.encrypt(plainText).base64;
}

// 公钥验签(验证后端私钥签名的内容)
bool rsaVerify(String plainText, String signature) {
  final signer = Signer(RSASigner(RSASignDigest.SHA256, publicKey: publicKey));
  return signer.verify(plainText, Signature(base64.decode(signature)));
}

Node.js 端实现(原生crypto模块)

  1. 生成RSA密钥对(一次性操作,妥善保存私钥):
openssl genrsa -out private.key 2048
openssl rsa -in private.key -pubout -out public.key
  1. 解密/签名代码示例:
const crypto = require('crypto');
const fs = require('fs');

// 读取本地密钥文件
const privateKey = fs.readFileSync('./private.key', 'utf8');
const publicKey = fs.readFileSync('./public.key', 'utf8');

// 私钥解密前端加密数据
function rsaDecrypt(encryptedText) {
  const buffer = Buffer.from(encryptedText, 'base64');
  return crypto.privateDecrypt(
    {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
      oaepHash: 'sha256'
    },
    buffer
  ).toString();
}

// 私钥签名数据,供前端验签
function rsaSign(plainText) {
  const sign = crypto.createSign('SHA256');
  sign.write(plainText);
  sign.end();
  return sign.sign(privateKey, 'base64');
}

二、AES-256 双向加密实现

AES为对称加密,前后端共用32字节(256位)密钥,每次加密随机生成16字节IV,推荐使用CBC模式+PKCS7填充。

Flutter 端实现(依赖encrypt库)

import 'package:encrypt/encrypt.dart';
import 'dart:math';

// 32字节密钥(前后端必须完全一致,注意保密)
final key = Key.fromUtf8('your-32-byte-secret-key-here-12345678');

// 生成随机16字节IV
IV generateIV() => IV.fromBytes(List<int>.generate(16, (i) => Random.secure().nextInt(256)));

// AES加密,返回加密数据和IV
Map<String, String> aesEncrypt(String plainText) {
  final iv = generateIV();
  final encrypter = Encrypter(AES(key, mode: AESMode.cbc));
  final encrypted = encrypter.encrypt(plainText, iv: iv);
  return {
    'data': encrypted.base64,
    'iv': iv.base64 // IV需随加密数据一同传给后端
  };
}

// AES解密,接收加密数据和IV
String aesDecrypt(String encryptedText, String ivBase64) {
  final iv = IV.fromBase64(ivBase64);
  final encrypter = Encrypter(AES(key, mode: AESMode.cbc));
  return encrypter.decrypt(Encrypted.fromBase64(encryptedText), iv: iv);
}

Node.js 端实现(原生crypto模块)

const crypto = require('crypto');

// 和Flutter端一致的32字节密钥
const key = Buffer.from('your-32-byte-secret-key-here-12345678', 'utf8');

// AES解密前端数据
function aesDecrypt(encryptedData) {
  const { data, iv } = encryptedData;
  const decipher = crypto.createDecipheriv('aes-256-cbc', key, Buffer.from(iv, 'base64'));
  let decrypted = decipher.update(data, 'base64', 'utf8');
  decrypted += decipher.final('utf8');
  return decrypted;
}

// AES加密返回给前端
function aesEncrypt(plainText) {
  const iv = crypto.randomBytes(16); // 生成随机IV
  const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
  let encrypted = cipher.update(plainText, 'utf8', 'base64');
  encrypted += cipher.final('base64');
  return {
    data: encrypted,
    iv: iv.toString('base64')
  };
}

关键注意事项

  • RSA仅适合加密小数据(如AES密钥),AES适合加密大体积业务数据,实际项目可结合使用:用RSA加密AES密钥,再用AES加密核心数据。
  • 密钥、私钥绝不能硬编码到代码中,建议通过环境变量或加密配置文件加载。
  • IV必须每次加密随机生成,禁止固定使用同一IV,否则会大幅降低加密安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:13:28