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

PHP与Dart/Flutter间AES256二进制数据加解密问题求助

PHP与Flutter(Dart) AES256-CBC二进制数据加解密不一致问题解决

问题根源

  1. 二进制转String的字节损坏:Dart代码中通过String.fromCharCodes(tab)将二进制字节数组转为String时,若字节值不符合UTF-8编码规则,会被替换为默认替代字符(如�),导致加密的原始数据与PHP端完全不一致。
  2. 数据长度不匹配:Dart中创建了长度为13的Uint8List,但仅填充前4字节,剩余9字节为0;而PHP端通过pack("N", $l_group_id)生成的是严格4字节的二进制数据,双方加密的原始数据长度和内容本就不同,密文自然无法一致。

修正方案

核心思路:直接处理二进制字节数据,避免String转换,同时确保两端的原始数据长度、编码方式、加解密参数完全对齐。

修正后的PHP代码

<?php
$_key = 'MySecretKeyForEncryptionAndDecry'; // 32字节AES-256密钥
$_iv = 'helloworldhelloW'; // 16字节CBC向量
$_method = 'aes-256-cbc';

$l_group_id = 1540980342;
$binary_data = pack("N", $l_group_id); // 生成4字节大端二进制数据

// 加密:获取原始二进制密文后手动Base64编码,与Dart端对齐
$raw_cipher = openssl_encrypt($binary_data, $_method, $_key, OPENSSL_RAW_DATA, $_iv);
$cipher_base64 = base64_encode($raw_cipher);

// 解密:Base64解码后还原原始密文,再解密
$decrypted_binary = openssl_decrypt(base64_decode($cipher_base64), $_method, $_key, OPENSSL_RAW_DATA, $_iv);
$decrypted_group_id = unpack("N", $decrypted_binary)[1]; // 还原为整数

echo "原始二进制字节: " . implode(" ", array_map('ord', str_split($binary_data))) . "<br>";
echo "密文(Base64): {$cipher_base64}<br>";
echo "解密后整数: {$decrypted_group_id}<br>";
?>

修正后的Dart代码

import 'package:encrypt/encrypt.dart';
import 'dart:typed_data';

void main() {
  final key = Key.fromUtf8('MySecretKeyForEncryptionAndDecry'); // 32字节密钥
  final iv = IV.fromUtf8('helloworldhelloW'); // 16字节向量

  const int lGroupId = 1540980342;
  // 生成4字节大端二进制数据,与PHP pack("N")完全一致
  final Uint8List binaryData = Uint8List(4)
    ..[0] = ((lGroupId >> 24) & 0xFF)
    ..[1] = ((lGroupId >> 16) & 0xFF)
    ..[2] = ((lGroupId >> 8) & 0xFF)
    ..[3] = (lGroupId & 0xFF);

  // 直接加密二进制字节
  final encrypter = Encrypter(AES(key, mode: AESMode.cbc));
  final encrypted = encrypter.encryptBytes(binaryData, iv: iv);
  final cipherBase64 = encrypted.base64;

  // 解密二进制字节
  final decryptedBytes = encrypter.decryptBytes(Encrypted.fromBase64(cipherBase64), iv: iv);
  // 从4字节大端数据还原整数
  final decryptedGroupId = (decryptedBytes[0] << 24) |
                           (decryptedBytes[1] << 16) |
                           (decryptedBytes[2] << 8) |
                           decryptedBytes[3];

  print("原始二进制字节: ${binaryData.join(' ')}");
  print("密文(Base64): $cipherBase64");
  print("解密后整数: $decryptedGroupId");
}

关键修改说明

  • Dart端:使用encryptBytes/decryptBytes方法直接处理Uint8List,彻底规避String转换带来的字节损坏;将二进制数组长度改为4,与PHP端数据长度完全匹配。
  • PHP端:使用OPENSSL_RAW_DATA选项获取原始密文,再手动Base64编码,确保与Dart端的密文编码逻辑一致;解密后通过unpack("N")还原整数,保证数据格式对齐。

内容的提问来源于stack exchange,提问作者ZeDvD

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:58:13