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

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代码逻辑:

  1. openssl_encrypt在第四个参数传0的时候,默认会把加密后的原始字节做一次base64编码再返回
  2. 然后你把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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:09:37