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

Dart中RSA加密转Base64后跨场景解密失败问题

Dart RSA加密后Base64存储解密失败问题解决

问题核心

在Dart中执行RSA加密,将密文转为Base64字符串存储后,取出解密时触发Invalid argument(s): decoding error错误。同一函数内连续执行加密→Base64编码→解码→解密流程完全正常,但使用数据库取出的Base64串或复制打印输出的Base64串解密时,即便解码后的字节数组与原密文字节数组一致,仍解密失败。

复现代码与错误信息

示例代码

import 'dart:convert';
import 'package:pointycastle/asymmetric/rsa.dart';
import 'package:pointycastle/key_generators/rsa_key_generator.dart';
import 'package:pointycastle/api.dart';

void main() async {
  // 生成RSA密钥对
  final keyGenerator = RSAKeyGenerator();
  final params = RSAKeyGeneratorParameters(BigInt.from(65537), 2048, 12);
  keyGenerator.init(ParametersWithRandom(params, SecureRandom()));
  final keyPair = keyGenerator.generateKeyPair();
  final publicKey = keyPair.publicKey as RSAPublicKey;
  final privateKey = keyPair.privateKey as RSAPrivateKey;

  // 测试1:同函数内加密解码解密(正常)
  final plainText = 'test data';
  final encryptor = RSAEngine()..init(true, PublicKeyParameter<RSAPublicKey>(publicKey));
  final encrypted = encryptor.process(utf8.encode(plainText));
  final base64Str = base64.encode(encrypted);
  print('Base64密文:$base64Str');
  
  final decodedBytes = base64.decode(base64Str);
  final decryptor = RSAEngine()..init(false, PrivateKeyParameter<RSAPrivateKey>(privateKey));
  final decrypted1 = utf8.decode(decryptor.process(decodedBytes));
  print('同函数解密结果:$decrypted1'); // 输出test data

  // 测试2:使用打印的Base64串解密(失败)
  final copiedBase64 = '这里替换成打印的base64Str内容';
  final copiedDecoded = base64.decode(copiedBase64);
  print('解码字节数组是否一致:${encrypted.toString() == copiedDecoded.toString()}'); // 输出true
  try {
    final decrypted2 = utf8.decode(decryptor.process(copiedDecoded));
    print('复制串解密结果:$decrypted2');
  } catch (e) {
    print('解密错误:$e'); // 输出Invalid argument(s): decoding error
  }
}

错误栈

Invalid argument(s): decoding error
#0      _RSAImpl.decrypt (package:pointycastle/impl/asymmetric/rsa.dart:254:7)
#1      RSAEngine.process (package:pointycastle/asymmetric/rsa.dart:107:25)
#2      main (file:///path/to/your/file.dart:28:46)

可能原因与解决方案

1. Base64字符串存在隐藏字符或格式问题

从数据库取出或复制打印的Base64串可能包含不可见字符(如换行符、制表符、前后空格)或多余符号(如打印时的引号)。即使肉眼看起来一致,这些字符会导致解码后的字节数组看似匹配,但实际解密时因格式不符报错。

解决方法:

  • 对取出的Base64串进行清理:
    final cleanedBase64 = copiedBase64.trim().replaceAll(RegExp(r'\s'), '').replaceAll('"', '');
    
  • 对比原Base64串与取出串的字符长度,确保无截断或额外字符。

2. Base64编码/解码标准不匹配

Dart中dart:convert提供了base64和base64Url两种编码标准,若加密时用base64.encode,解密时误用base64Url.decode(或反之),会导致解码后的字节数组异常。

解决方法:

  • 统一使用同一套Base64工具方法:加密用base64.encode(encryptedBytes),解密用base64.decode(base64Str)。

3. RSA填充模式不一致

RSA加密和解密必须使用相同的填充模式(如PKCS1、OAEP)。若加密时默认使用了某填充模式,解密时未指定或指定错误,会导致解密失败。

解决方法:

  • 显式指定填充模式,确保加密解密一致:
    // 加密时指定PKCS1填充
    final encryptor = PKCS1Encoding(RSAEngine())
      ..init(true, PublicKeyParameter<RSAPublicKey>(publicKey));
    final encrypted = encryptor.process(utf8.encode(plainText));
    
    // 解密时使用相同填充
    final decryptor = PKCS1Encoding(RSAEngine())
      ..init(false, PrivateKeyParameter<RSAPrivateKey>(privateKey));
    final decrypted = decryptor.process(decodedBytes);
    

4. 数据库存储时的编码转换问题

部分数据库会自动对字符串进行编码转换(如将UTF-8转成其他编码),导致Base64串的字节结构被修改。

解决方法:

  • 确保数据库存储Base64串时使用UTF-8编码,且以纯文本形式存储,避免自动转码。

验证步骤

  1. 打印原Base64串和取出串的字符长度,确认一致。
  2. 将两个字符串转为字节数组后逐字节对比,确认完全匹配。
  3. 对取出的Base64串执行清理操作后再尝试解密。

内容的提问来源于stack exchange,提问作者Niek van Dommelen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:12:11