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
相关产品推荐
相关产品推荐

