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

Dart(PointyCastle)与Go跨语言RSA加解密报错:crypto/rsa: decryption error

解决Dart(PointyCastle)与Go RSA-OAEP跨语言加解密不兼容问题

你遇到的crypto/rsa: decryption error问题,核心原因是Dart端PointyCastle的默认OAEP配置和Go标准库的OAEP参数不匹配。Go的rsa.DecryptOAEP默认使用SHA-256哈希算法、基于SHA-256的MGF1掩码生成函数,且空标签;而PointyCastle中直接使用AsymmetricBlockCipher('RSA/OAEP')时,默认采用的是SHA-1哈希和SHA-1的MGF1,两边参数不对等就会导致解密失败。

下面是具体的修复步骤:

1. 修改Dart端的OAEP加密配置

需要手动指定OAEP的哈希算法、MGF1函数和标签,确保和Go端完全一致:

首先导入PointyCastle的相关类:

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

然后调整加密器的初始化代码:

// 解析公钥(保持你原来的代码逻辑)
final publicKey = enc.RSAKeyParser().parse(serverRsaPublicKey) as RSAPublicKey;

// 配置与Go匹配的OAEP参数:SHA-256哈希、SHA-256的MGF1、空标签
final sha256Digest = SHA256Digest();
final mgf1 = MGF1Digest(sha256Digest);
final oaepParams = OAEPParameters(sha256Digest, mgf1, Uint8List(0));

// 初始化OAEP加密器,传入安全随机数生成器(OAEP必须依赖随机数)
final secureRandom = FortunaRandom();
secureRandom.seed(KeyParameter(Uint8List(32))); // 实际生产环境建议用更安全的种子源

final rsaEncrypter = OAEPEncoding(RSAEngine())
  ..init(
    true, // true表示加密模式
    ParametersWithRandom(
      PublicKeyParameter<RSAPublicKey>(publicKey),
      secureRandom,
    )..parameters = oaepParams,
  );

// 加密消息(保持你原来的分块处理逻辑)
final plaintext = Uint8List.fromList(utf8.encode('Some message'));
final ciphertext = rsaProcessInBlocks(rsaEncrypter, plaintext);

tcpSendMessage(ciphertext);

2. 确认分块处理函数的正确性

确保你的rsaProcessInBlocks函数(对应PointyCastle教程中的_processInBlocks)正确处理了OAEP的加密块大小:

  • OAEP的最大明文块大小 = 密钥长度(字节) - 2*哈希长度 - 2
  • 对于2048位RSA密钥+SHA-256哈希,块大小为 256 - 2*32 -2 = 190 字节
    如果分块逻辑错误,也会导致解密失败,建议直接使用教程中的标准分块实现。

3. 验证Go端的参数一致性

你的Go代码已经正确指定了SHA-256哈希、空标签,这部分不需要修改,但可以补充私钥格式兼容的判断,避免因私钥格式(PKCS1/PKCS8)导致的隐性问题:

block, _ := pem.Decode([]byte(RSA_PRIVATE_KEY))
if block == nil {
    println("failed to decode PEM block containing private key")
    return
}

var privateKey *rsa.PrivateKey
var err error
// 先尝试解析PKCS1格式私钥
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
    // 如果失败,尝试解析PKCS8格式
    privateKeyInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
    if err != nil {
        println(err.Error())
        return
    }
    var ok bool
    privateKey, ok = privateKeyInterface.(*rsa.PrivateKey)
    if !ok {
        println("not an RSA private key")
        return
    }
}

为什么单语言内正常但跨语言失败?

单语言内加解密使用的是相同的默认参数:Dart内用默认SHA-1加密解密没问题,Go内用SHA-256加密解密也没问题,但跨语言时参数不匹配就会触发失败——Go的OAEP实现出于安全考虑,不会泄露具体错误细节,只会返回模糊的decryption error。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 17:15:49