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

Flutter实现与PHP一致的AES-256-CBC加解密功能报错求助

问题:Flutter实现PHP AES-256-CBC加解密时出现IV长度错误

问题背景

现有PHP的AES-256-CBC加解密函数,在Flutter中实现对应逻辑时触发错误:

E/flutter ( 9703): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument(s): Initialization vector must be the same length as block size

PHP原函数

public static function encrypt_decrypt($action, $string) {
    $output = false;

    $encrypt_method = "AES-256-CBC";
    $secret_key = 'R4haSIA';
    $secret_iv = 'r$h4sia';

    $key = hash('sha256', $secret_key);

    $iv = substr(hash('sha256', $secret_iv), 0, 16);

    if ($action == 'encrypt') {
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
    } else if ($action == 'decrypt') {
        $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
    }

    return $output;
}

原Flutter代码(报错版本)

String encryptPassword(String password) {
  final key = encrypt.Key.fromUtf8('R4haSIA');
  final iv = encrypt.IV.fromUtf8('r\$h4sia12345678'); // Panjang IV 16 byte
  final encrypter =
      encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
  final encrypted = encrypter.encrypt(password, iv: iv);

  return encrypted.base64;
}

Future<void> _login() async {
  var url = Uri.parse("http://10.0.2.2/config/db/login.php");
  var pass_enkripsi = encryptPassword(passwordController.text);
  var response = await http.post(url, body: {
    "username": usernameController.text,
    "password": pass_enkripsi,
  });
  var datauser = jsonDecode(response.body);

  if (datauser != '') {
    print('Login Success');

    Navigator.pushReplacement(
      context,
      MaterialPageRoute(builder: (context) => const homepage()),
    );
  } else {
    print('Login failed');
  }
}

问题根源

Flutter代码和PHP逻辑存在两处关键不一致:

  1. 密钥生成错误:PHP对secret_key做SHA256哈希后作为AES-256密钥(SHA256输出32字节,刚好符合AES-256要求),但Flutter直接用原始7字节字符串作为密钥,长度不足且逻辑不符。
  2. IV生成错误:PHP对secret_iv做SHA256哈希后取前16字节作为IV,而Flutter手动拼接字符串凑16字节,生成逻辑完全不同,且这种方式不符合PHP的处理逻辑。

修正后的Flutter代码

需要先在pubspec.yaml中添加依赖:

dependencies:
  crypto: ^3.0.3
  encrypt: ^5.0.1

然后使用以下修正后的代码,确保和PHP逻辑完全对齐:

import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:encrypt/encrypt.dart';

// 加密函数,和PHP逻辑完全一致
String encryptPassword(String password) {
  final secretKey = 'R4haSIA';
  final secretIv = 'r\$h4sia';

  // 生成密钥:对secretKey做SHA256哈希,取32字节(SHA256输出刚好32字节)
  final keyBytes = sha256.convert(utf8.encode(secretKey)).bytes;
  final key = encrypt.Key(keyBytes);

  // 生成IV:对secretIv做SHA256哈希,取前16字节
  final ivHash = sha256.convert(utf8.encode(secretIv)).toString();
  final ivBytes = utf8.encode(ivHash.substring(0, 16));
  final iv = encrypt.IV(ivBytes);

  final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
  // PHP中openssl_encrypt默认使用PKCS7填充,和encrypt包默认一致
  final encrypted = encrypter.encrypt(password, iv: iv);
  
  return encrypted.base64;
}

// 可选:对应的解密函数,和PHP decrypt逻辑一致
String decryptPassword(String encryptedPassword) {
  final secretKey = 'R4haSIA';
  final secretIv = 'r\$h4sia';

  final keyBytes = sha256.convert(utf8.encode(secretKey)).bytes;
  final key = encrypt.Key(keyBytes);

  final ivHash = sha256.convert(utf8.encode(secretIv)).toString();
  final ivBytes = utf8.encode(ivHash.substring(0, 16));
  final iv = encrypt.IV(ivBytes);

  final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
  final decrypted = encrypter.decrypt64(encryptedPassword, iv: iv);
  
  return decrypted;
}

Future<void> _login() async {
  var url = Uri.parse("http://10.0.2.2/config/db/login.php");
  var pass_enkripsi = encryptPassword(passwordController.text);
  var response = await http.post(url, body: {
    "username": usernameController.text,
    "password": pass_enkripsi,
  });
  var datauser = jsonDecode(response.body);

  if (datauser != '') {
    print('Login Success');
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(builder: (context) => const homepage()),
    );
  } else {
    print('Login failed');
  }
}

关键说明

  • 使用crypto包处理SHA256哈希,确保和PHP的hash('sha256', ...)逻辑完全一致。
  • AES-256要求32字节密钥,SHA256哈希刚好输出32字节,直接使用即可。
  • AES-CBC的IV必须是16字节,严格按照PHP逻辑对secret_iv哈希后取前16字节生成。
  • encrypt包默认使用PKCS7填充,和PHP的openssl_encrypt默认填充方式一致,无需额外配置。

内容的提问来源于stack exchange,提问作者M. Ibnu Wildan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:26:05