PHP与Dart/Flutter间AES256二进制数据加解密问题求助
PHP与Flutter(Dart) AES256-CBC二进制数据加解密不一致问题解决
问题根源
- 二进制转String的字节损坏:Dart代码中通过
String.fromCharCodes(tab)将二进制字节数组转为String时,若字节值不符合UTF-8编码规则,会被替换为默认替代字符(如�),导致加密的原始数据与PHP端完全不一致。 - 数据长度不匹配: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
相关产品推荐
相关产品推荐

