Python加密RSA数据后Dart解密报OAEP解码错误的排查与解决
Dart与Python RSA跨语言加密解密错误排查与解决
我在Dart中生成RSA密钥对,将PEM编码的公钥通过Socket发送给Python;Python接收并加载该公钥,加密明文后将密文返回给Dart。但Dart使用匹配的私钥解密时出现以下错误:
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): decoding error #0 OAEPEncoding._decodeBlock (package:pointycastle/asymmetric/oaep.dart:452:7)
1. Dart端生成RSA密钥并发送PEM公钥
String produceKey(RSAPublicKey my_pub) { String public_pem = rsa_helper.CryptoUtils.encodeRSAPublicKeyToPem(my_pub); return "//encryptedKEY" + public_pem; // 基于Socket通信 }
2. Python端接收密钥并加密数据
public_key = serialization.load_pem_public_key(bytes(mykey,'utf8'), backend=default_backend()) message = "send 10 BTC to halit" message = base64.b64encode(bytes(message,'utf8')) encrypted_message = public_key.encrypt( message, padding.OAEP( mgf=padding.MGF1(algorithm=hashes.SHA1()), algorithm=hashes.SHA1(), label=None ) ) b = base64.b64encode(encrypted_message) base64_str = b.decode('utf8') # 发送密文至客户端
3. Dart端初始解密代码(出错版本)
String cipher_text = serverResponse.substring(9);// 截取Socket返回的密文(跳过前9位标识符) Uint8List plain_text = rsaDecrypt(my_private,cipher_text);// 使用私钥解密密文 print(plain_text);
备注
Socket通信已验证正常,发送的PEM公钥与生成的一致。
Dart解密工具方法
Uint8List rsaDecrypt(RSAPrivateKey myPrivate, Uint8List cipherText) { final decryptor = OAEPEncoding(RSAEngine()) ..init(false, PrivateKeyParameter<RSAPrivateKey>(myPrivate)); // false表示解密 return _processInBlocks(decryptor, cipherText); } // pointycastle包提供的解密方法
测试用例
给定密钥对:
-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCPGT5j+2qdxrKp trWW4hZcIwdacuduH16J7FO/0URzKoXdA5M5xVXwU/6HxREkKp+A+XUQN8HZCILP mQzXkmWCLWNQP92o6WUeZQW6bcXYt11mS9JmDhDPXwuiq33vEMJFlXi1L1Wrq2nR WVHKsJAuwswCfEjBfVdrJjut88JGXD/w5Et3t3A/zVX2eGAM1sn97kt57/PESObP RVLB+avTVAEAu4Qb3/uMvRlmDVgE6eE6pm5La+ObyVrfDdP41ly7zNf3VqgtM0dM OuurDmIGigXLvbrbIsx/TVxmwXvtreWhSyBISKMUMPB2NgcnvEXjXkt+PO00dGcN 8NI3erI9AgMBAAECggEAeHXWqJHfqVu30NgmuxItong2W3S4z2IG0nIn+iRuy8fz Eh9NU2eENaBvdtl02Y4r4YWdfv6A53ObsqhzQBFT9CbDIK3yqZt37QM7tDluQEXz kQao4hJbIkYvZEua4qGn+K2gBF4Jb08H8ByRlt/VMBf5Zuo60O7zpRZ1TLUTSOhi 7V0Teuu8djneHRtLzPgnfvGa1Ok6f4ObZGFgoZqTXK9HXxEc4+nICQoYc8BsMUlL iPFnBzU4MlvF5xUT4bYWqQjsQBoHM7zVrpAtZ3xKeSSdbkEWivYkt36h+RQLm3SM /1M5Ji92MjoFnLawh2XbZ+QD3W4owSvtd91n48lH/QKBgQDEbBI/7kfew6WO921D jaEEIRwDxOn0kYZhoGozU8zUWUQBfCfDR5MNJWELvioCfTWcyAJ/+ysalSezYIHU nuSGe8YrFTWI/xkGdUk1rfdSehbcnoPBwAM7wgW+twIdJpCAk6VbVMdh2hQNKDEN 0hAawk2PGr+2zm0qHuJhL0benwKBgQC6gKrbyv9XV6Th7blU0cnvY1fF3pdBKBFx U8oABAXi+8db2nUUxZ/zbOUUKFYd0yX5SukXArek8xrzPjf52CReL845k6M76fDy uSK4xQz900rueRaOANU4XxW+n+afti6CuoB5IINKRIne1S9ZEpmbtVWi0Y59+ANf 1GmXgictowKBgFcD7V3HCK3GDIz2TcBUeNVkeY2t6VsAMQEE2KdeY2pbFUZ3IwJe reVv/rr+BoxNvbdz36+krGa9VvYfNcTkkyaEpLinT60eHY7/3GvcYql2DrSzwHjP wF7zyCnB1zzkvbVIM0PvndhajPF7MagGvD2ugD96QR4R+shjIDSfhgzPAoGBAI5b 8o+NNzULYH9YP1RgQnzpXrFaBCinFhFkPNegOoIVYApcCWzOoRZls8KcO4fOibjt lliLKXTOYG71ujKK6s++O/M1H693FgWgjcFuIEmLxDGd2jqQpjC+W9HDKn4UyRHe nHxY9f51rKucHOUnznrNgs2imdrLun+mmuccYR1zAoGAHDkVep3Hy7cXVGwJzVeS lvAHadFlQ4TcvJqVv+uNB8hRsH7BZqsyWfnepWuy7MychkuWGHpiIpzBFxeMFvi1 aKa1yjNARIHQLpXvZntVVM7pb2hWFKTNyOwKMJrp8o2h0DJKOar7jlLyNs3ZIDFM n7w9iHpANOewTaT8svyFnxI= -----END PRIVATE KEY----- -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjxk+Y/tqncayqba1luIW XCMHWnLnbh9eiexTv9FEcyqF3QOTOcVV8FP+h8URJCqfgPl1EDfB2QiCz5kM15Jl gi1jUD/dqOllHmUFum3F2LddZkvSZg4Qz18Loqt97xDCRZV4tS9Vq6tp0VlRyrCQ LsLMAnxIwX1XayY7rfPCRlw/8ORLd7dwP81V9nhgDNbJ/e5Lee/zxEjmz0VSwfmr 01QBALuEG9/7jL0ZZg1YBOnhOqZuS2vjm8la3w3T+NZcu8zX91aoLTNHTDrrqw5i BooFy7262yLMf01cZsF77a3loUsgSEijFDDwdjYHJ7xF415LfjztNHRnDfDSN3qy PQIDAQAB -----END PUBLIC KEY----- plain_text = "Send To Halit 10BTC";
Python生成的密文:
jQO/VTb2lJut94GB5ABgV5gXsd2ee3x++EUz9FaMMEn8zxSisfUY7qiaAtwfV8bIOw+rcvfmyfIdxngSDS1B6qj5gp/OWDRhcExY7rfPTbY0Y1unuS4N8+C4dO1sFDANKSwl5tDfrs1ZN99J8H24jO9TjB0EPAAezxO8/DyjPRhe0wiBunObz0iiyVK73APoHJ1atCQ8cjKXUipCELpvog5k+XAdVwBeLb6N+Yw9LNUCMlIMXalj2koZ6IwbMY687qx2XlSgIH11pZC8ArRg82CCW/zi5gYckbeWVkC75ne/O3q3wd7h8/t8rdD/62hIyucV68udIFW7amCSN8/XFQ==
运行后出现上述解码错误。
解决方案
修改Dart端解密逻辑,正确处理密文的Base64解码以及明文的二次Base64解码:
String server_response = serverResponse.substring(9); print(server_response); final Uint8List cipherText = base64Decode(server_response); final decrypted = rsaDecrypt(my_private, cipherText); final decoded = utf8.decode(decrypted); final b64Decoded = base64Decode(decoded); print(decoded); print(utf8.decode(b64Decoded));
补充说明
问题根源在于Python端对明文进行了Base64编码后再加密,因此Dart端解密后需要先将结果转为字符串,再进行一次Base64解码才能得到原始明文。
内容的提问来源于stack exchange,提问作者Nakliyeci Sefer
相关产品推荐
相关产品推荐

