Flutter解密PHP加密数据时报错Invalid argument(s): Input data length must be a multiple of cipher's block size的解决方法
Flutter解密PHP加密数据时报错Invalid argument(s): Input data length must be a multiple of cipher's block size的解决方法
嘿,我懂你碰到这个错误有多闹心!咱们来拆解一下问题出在哪——其实是PHP和Dart两边对加密后数据的处理流程没对齐,导致Dart拿到的加密数据格式不对,才触发了块大小不匹配的错误。
先理清楚你的PHP代码逻辑:
openssl_encrypt在第四个参数传0的时候,默认会把加密后的原始字节做一次base64编码再返回- 然后你把
IV + base64编码后的加密字符串拼接起来,又做了一次base64编码才返回
而你的Dart代码现在只做了一次base64解码,把拼接后的内容拆成IV和“加密数据”,但这个“加密数据”其实还是PHP里第一次base64编码后的字符串,不是真正的加密原始字节,自然长度不符合AES块大小要求。
修正后的Dart代码
import 'dart:convert'; import 'package:crypto/crypto.dart'; import 'package:encrypt/encrypt.dart'; String decryptDomainWithToken(String encrypted, String token) { final method = AESMode.cbc; // Derive key from token using SHA-256(这部分逻辑和PHP一致,是正确的) final key = sha256.convert(utf8.encode(token)).bytes; final encrypter = Encrypter(AES(Key(Uint8List.fromList(key)), mode: method)); // 第一步:解码整个返回的base64字符串 final decodedData = base64.decode(encrypted); // 取出IV(AES-256-CBC的IV长度确实是16字节) final ivLength = 16; final iv = IV(Uint8List.fromList(decodedData.sublist(0, ivLength))); // 关键修正:剩下的部分是PHP里openssl_encrypt返回的base64字符串,需要先转成字符串再解码 final encryptedBase64Str = utf8.decode(decodedData.sublist(ivLength)); final encryptedData = Encrypted(base64.decode(encryptedBase64Str)); // 现在解密就正常了 return encrypter.decrypt(encryptedData, iv: iv); }
关键修改点说明
- 原来的Dart代码直接把
decodedData.sublist(ivLength)当成加密原始字节,但这部分其实是PHP端第一次base64编码后的字符串,所以需要先转成UTF-8字符串,再做一次base64解码,才能得到真正的加密原始字节。 - 密钥生成和IV处理的逻辑是正确的,和PHP端完全对齐:PHP用
hash('sha256', $token, true)返回原始字节,Dart用sha256.convert(...).bytes也是对应的原始字节数组;AES-256-CBC的IV长度确实是16字节,这部分没问题。
你可以试试这个修正后的代码,应该就能正常解密啦!
备注:内容来源于stack exchange,提问作者ilham
相关产品推荐
相关产品推荐

