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

Flutter PointyCastle实现RSA/OAEP-SHA256加密遇在线解密填充错误

RSA/ECB/OAEPWithSHA-256AndMGF1Padding解密填充错误排查

问题背景

我用PointyCastle和encrypt库严格按文档实现了RSA/ECB/OAEPWithSHA-256AndMGF1Padding加密,本地运行正常,但在devgland.com这类在线网站测试解密时,出现Padding error in decryption(解密填充错误)。

加密代码

String rsaEncrypt(String dataToEncrypt) {
  final publicKey = RSAKeyParser().parse(publicKeyStr) as RSAPublicKey;

  final engine = OAEPEncoding.withSHA256(RSAEngine());

  engine.init(
    true,
    PublicKeyParameter<RSAPublicKey>(publicKey),
  ); // true=encrypt

  return base64Encode(
    _processInBlocks(
      engine,
      Uint8List.fromList(dataToEncrypt.codeUnits),
    ),
  );
}

Uint8List _processInBlocks(AsymmetricBlockCipher engine, Uint8List input) {
  final numBlocks = input.length ~/ engine.inputBlockSize +
      ((input.length % engine.inputBlockSize != 0) ? 1 : 0);

  final output = Uint8List(numBlocks * engine.outputBlockSize);

  var inputOffset = 0;
  var outputOffset = 0;
  while (inputOffset < input.length) {
    final chunkSize = (inputOffset + engine.inputBlockSize <= input.length)
        ? engine.inputBlockSize
        : input.length - inputOffset;

    outputOffset += engine.processBlock(
        input, inputOffset, chunkSize, output, outputOffset);

    inputOffset += chunkSize;
  }

  return (output.length == outputOffset)
      ? output
      : output.sublist(0, outputOffset);
}

核心问题及解决办法

1. 错误的分块处理逻辑

RSA-OAEP是单块加密算法,不支持分块加密。你的_processInBlocks方法会破坏OAEP的填充结构,导致解密时无法验证填充。

修正方案:移除分块逻辑,直接处理整个明文(注意明文长度不能超过engine.inputBlockSize)。如果明文过长,必须使用混合加密:先用AES等对称算法加密明文,再用RSA加密对称密钥。

修正后的加密代码:

String rsaEncrypt(String dataToEncrypt) {
  final publicKey = RSAKeyParser().parse(publicKeyStr) as RSAPublicKey;
  
  // 显式指定OAEP和MGF1都使用SHA256
  final engine = OAEPEncoding(
    RSAEngine(),
    SHA256Digest(),
    SHA256Digest(),
    Uint8List(0), // 空标签参数,和大多数在线工具保持一致
  );

  engine.init(true, PublicKeyParameter<RSAPublicKey>(publicKey));
  
  final inputBytes = Uint8List.fromList(dataToEncrypt.codeUnits);
  
  // 检查输入长度是否符合OAEP限制
  if (inputBytes.length > engine.inputBlockSize) {
    throw Exception('明文长度超过RSA-OAEP最大限制,请使用混合加密');
  }
  
  final encryptedBytes = engine.processBlock(inputBytes, 0, inputBytes.length);
  return base64Encode(encryptedBytes);
}

2. MGF1哈希算法不匹配

OAEPEncoding.withSHA256仅指定了OAEP的哈希算法为SHA256,但PointyCastle默认给MGF1用的是SHA-1。而多数在线解密工具默认会用SHA256作为MGF1的哈希算法,导致算法参数不匹配,触发填充错误。

修正方案:初始化OAEPEncoding时显式指定MGF1的哈希算法为SHA256,如上修正代码所示。

3. 密钥格式不兼容

确保在线工具使用的私钥和你的公钥是配对密钥,且密钥格式一致:

  • 检查公钥是否为PKCS#8格式(PointyCastle的RSAKeyParser默认支持),如果在线工具要求PKCS#1格式,需要转换密钥格式;
  • 确认私钥没有额外的密码保护,多数在线工具不支持解密带密码的私钥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:09:51