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

