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

Flutter中RSAES-OAEP/SHA-256/MGF1-SHA-1加密数据不匹配问题排查

RSA-OAEP加密跨端兼容问题排查

问题背景

我之前用JS的forge库实现了RSAES-OAEP/SHA-256/MGF1-SHA-1算法的公钥加密,该实现与Java的RSA/ECB/OAEPWithSHA-256AndMGF1Padding兼容。现在用Flutter的encrypt库编写对应加密逻辑后,加密结果发送到服务器验证不通过,需要排查配置差异。

JS端实现代码

textPayPass = document.getElementById('tpassword').value;
$('tpassword').val('');
s_cert = "-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5xdSrXnpj8pUFBWvEWuEPmzL/iuCfoHwGsMou4PE5Y/wNmnM1E8niUww8yjLHgdOBOtPtLaBua/dkL+EKVXLylt0xpKtCC6KWBr07bvNK/CNXFUhd/9MMyV90UWJP5XHSzrxYz//ZJYn0XUicsKPDox7TJZFtMnw+euAwPDA7VhRupc4x8QHTkdTORUaeKSI3jLr6LdQC19BjeC5M4uZ45/U+6Hd9PPgKqp90dXrIyOcMXb65HrQoba6FsZnrN6qr7Z/4v4r6Xxdxo9Qwl6YBZJ3+1RlT/uSxjcxJTYgIropjI3O3r90+e7/DxE1ITHxxEjZhUkySTUBOkzeQdpRmHyL+ctSDvip7IO3Fd+axVvhSZq5w9x5DDWJcMhTiJpkjF3LHXaB1+T+oet36ClyMGmnnsnyOZ2s/kWiAaGFmqBebtk6iDkbq0y6hKtpNmPrx5hoUiQomo/cfoDpfnIUeJd4Kf+QRvTqGXP2yXbu8861LjWuaJ+kyTDUAoGV/Haw28P/Kwnr7oZTtP0mWU7bKqrPwoWAc9CHv2SKy4qjZCuS036VaAe2vd5gmGBni4hjA8YdWrLcPF5LwSDWoaXpPm9Ve8KB+5XpxLjyCjve/8y+9yGDtoYpTltOTsm9Au7BcZSFy5XyEAs6CQHaOZ6NGp8pIEhskUj7fv7/E6owkEMCAwEAAQ==-----END PUBLIC KEY-----";

var s_certForge = forge.pki.publicKeyFromPem(s_cert);
// encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1
// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Padding
var encData = s_certForge.encrypt(textPayPass, 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
    md: forge.md.sha1.create()
}
});
var s_encData = forge.util.encode64(encData);

Flutter端当前实现代码

static String publicKeyTE ='''-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgsOgXZqI0joBljDjJ/9lOIHP1kGZJg8JsulkxK3CWOis/BO0N7Lqj70qGb8T3dgd/MOb/mmBkwxZ/U/PAIUS9YynPPPOd4ROXpEnkWYj5ntMKr7KWY/VKHSm+RzLWX8yi+8NmmK3NJosWzOXAwMIKY8ZSB+BBw//uI+aaRQlE4bAICufff9KcoJd8EEldQgLa74F+TgLg5VtV+2Ik9xgV2h2NaM6wvldp69OicjEgGPnX2uEwYJbo2HYiGjm5HnFtT70c5w8vO88O5/OvYafNfLmXZsszR/JYdPpOdKOf45NX2v50V43VnBgVlskki70kZAdi5roLjEpSC2vxjbh9I3dJrApp7UgnTE6+iaJg7onsXuXe1VPgp0evKM/BpVo2Jb95uD24oBop1OghQX6UyKYr7MAaPT3yT40vBOe5BxiAjbHDob/K8tzWt6fh1qKkLNry5jWOD/pQC7yrEBLIezB/Hzai+cIfBLqgWBEc1uA0D4/81SBu7MXTko1ne9HNF2zQwPtQOk0l/F8YOdCpyv4X0vxejc4pIwE+Iuk+KGqXvzRp2RnQZ6U08Bc4kkxXoEYSJ9ICyxSQCVxzJ9AMW8mlAOon71ZVr4ZWj9dicoQDUt+kXZV2E3itoy0guIabyk12ONvEekgzoRyRnrIv+mHWw6sV2Luo8bUh159sIsCAwEAAQ==-----END PUBLIC KEY-----''';

String encryptPassword(String password) {
RSAPublicKey publicKey=RsaKeyHelper().parsePublicKeyFromPem(publicKeyTE);
    final encrypter = Encrypter(
    RSA(
      publicKey: publicKey,
      encoding: RSAEncoding.OAEP,
      digest: RSADigest.SHA256,
    )
);
final encrypted = encrypter.encrypt(password);
return encrypted.base64;
}

问题原因

核心差异在于MGF1掩码生成函数的摘要算法配置不一致:

  • JS端明确指定MGF1使用SHA-1:mgf1: { md: forge.md.sha1.create() }
  • Flutter端当前仅配置了OAEP主摘要为SHA256,encrypt库默认会让MGF1使用和主摘要相同的算法(即SHA256),这与JS端的SHA-1不匹配,导致加密结果无法兼容。

修正后的Flutter代码

static String publicKeyTE ='''-----BEGIN PUBLIC KEY-----MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgsOgXZqI0joBljDjJ/9lOIHP1kGZJg8JsulkxK3CWOis/BO0N7Lqj70qGb8T3dgd/MOb/mmBkwxZ/U/PAIUS9YynPPPOd4ROXpEnkWYj5ntMKr7KWY/VKHSm+RzLWX8yi+8NmmK3NJosWzOXAwMIKY8ZSB+BBw//uI+aaRQlE4bAICufff9KcoJd8EEldQgLa74F+TgLg5VtV+2Ik9xgV2h2NaM6wvldp69OicjEgGPnX2uEwYJbo2HYiGjm5HnFtT70c5w8vO88O5/OvYafNfLmXZsszR/JYdPpOdKOf45NX2v50V43VnBgVlskki70kZAdi5roLjEpSC2vxjbh9I3dJrApp7UgnTE6+iaJg7onsXuXe1VPgp0evKM/BpVo2Jb95uD24oBop1OghQX6UyKYr7MAaPT3yT40vBOe5BxiAjbHDob/K8tzWt6fh1qKkLNry5jWOD/pQC7yrEBLIezB/Hzai+cIfBLqgWBEc1uA0D4/81SBu7MXTko1ne9HNF2zQwPtQOk0l/F8YOdCpyv4X0vxejc4pIwE+Iuk+KGqXvzRp2RnQZ6U08Bc4kkxXoEYSJ9ICyxSQCVxzJ9AMW8mlAOon71ZVr4ZWj9dicoQDUt+kXZV2E3itoy0guIabyk12ONvEekgzoRyRnrIv+mHWw6sV2Luo8bUh159sIsCAwEAAQ==-----END PUBLIC KEY-----''';

String encryptPassword(String password) {
  RSAPublicKey publicKey = RsaKeyHelper().parsePublicKeyFromPem(publicKeyTE);
  final encrypter = Encrypter(
    RSA(
      publicKey: publicKey,
      encoding: RSAEncoding.OAEP,
      digest: RSADigest.SHA256,
      mgf1Digest: RSADigest.SHA1, // 关键配置:与JS端MGF1算法对齐
    )
  );
  final encrypted = encrypter.encrypt(password);
  return encrypted.base64;
}

额外注意事项

  • 测试时需确保Flutter端使用的公钥与JS端完全一致(当前代码中两端公钥不同,需替换为相同公钥验证)
  • 字符串编码无需额外处理:JS的forge和Flutter的encrypt库默认均使用UTF-8编码明文,这部分保持一致。

内容的提问来源于stack exchange,提问作者Ernesto Enrique Sanchez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 08:14:57