Php AES 256 ECB有效密钥解密返回奇怪/字符

Php AES 256 ECB有效密钥解密返回奇怪/字符,php,aes,cbc-mode,ecb,Php,Aes,Cbc Mode,Ecb,我正在尝试使用函数openssl\u decrypt在PHP中解密 问题是返回的字符串的一部分是正确的,而另一部分是胡言乱语 `@ M{-Y f{5678","token":null}` 任何形式的帮助都将不胜感激 首先,我认为这是一个编码问题,所以我尝试使用此函数更改编码,但没有成功 mb_convert_encoding($data,'UTF-8'); 下面是我正在使用的简单函数 $secret="#oc*Zd'&'&%rez`&;957.u1c:(|'%c8

我正在尝试使用函数openssl\u decrypt在PHP中解密

问题是返回的字符串的一部分是正确的,而另一部分是胡言乱语

`@M{-Y  f{5678","token":null}`
任何形式的帮助都将不胜感激

首先,我认为这是一个编码问题,所以我尝试使用此函数更改编码,但没有成功

mb_convert_encoding($data,'UTF-8');
下面是我正在使用的简单函数

$secret="#oc*Zd'&'&%rez`&;957.u1c:(|'%c81";


$data="SsxrFLoAWTPP7t8AR1/QFXSkZF6Xl2DXGV8Ay90rXk1sgwN46CmSmWsBqTvhbeUT";

$decrypted=openssl_decrypt($data,'aes-256-cbc',$secret);

var_dump($decrypted);
这应该是预期的输出

`{"reg_no":"UP2345678","token":null}
该模式需要IV。必须使用加密的IV进行解密。在发布的示例中,
openssl\u decrypt
-调用中没有传递IV(对应于具有0值的IV),因此第一个块(1块=16字节)被错误解密

原则上,如果已知密钥、明文和密文,则可以重构IV:解密密文的第一个块(没有IV),并将结果与明文的第一个块异或。对于发布的示例中的数据(作为十六进制字符串),这将导致以下IV:
3B297D28642443363339332B2D2826
。使用该IV,输出

$secret = "#oc*Zd'&'&%rez`&;957.u1c:(|'%c81";
$iv = hex2bin('3B297D2864244336363339332B2D2826');
$data = "SsxrFLoAWTPP7t8AR1/QFXSkZF6Xl2DXGV8Ay90rXk1sgwN46CmSmWsBqTvhbeUT";
$decrypted = openssl_decrypt($data, 'aes-256-cbc',$secret, 0, $iv);
print('Decrypted data: '.$decrypted);
与预期结果相对应:

{"reg_no":"UP2345678","token":null}

编辑:

虽然我认为这很清楚,但我想指出,下面描述的方法当然不是确定IV解密的常规方法(这根本不起作用,因为明文是未知的)。通常用于加密的IV与密文一起发送给收件人。这是可能的,因为静脉注射不必保密。也就是说,在发布的示例中,IV由于某种原因缺失,尽管它实际上应该存在

无论如何,也可以使用明文、密文和密钥通过以下方式确定IV:在-模式的描述中可以看到,在加密开始时,明文和IV的第一个块是异或的,然后对结果进行加密。因此,可以通过首先解密该第一个加密块,然后用明文对结果进行异或运算来确定IV。相应的PHP代码是:

// Step 1: Decrypt the first block of the ciphertext (no IV is used which is equivalent to a 0-IV)  
$ciphertext = base64_decode('SsxrFLoAWTPP7t8AR1/QFXSkZF6Xl2DXGV8Ay90rXk1sgwN46CmSmWsBqTvhbeUT');
$ciphertextFirstBlock = substr($ciphertext, 0, 16);                                                                               // First block / 16 Byte of encrypted data
$decryptedFirstBlock = openssl_decrypt($ciphertextFirstBlock, 'aes-256-cbc', $secret,  OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);  // First block / 16 Byte of decrypted data
print('Decrypted first block: '.bin2hex($decryptedFirstBlock)."\n");

// Step 2: XOR the result with the first block of the plaintext
$plaintext = '{"reg_no":"UP2345678","token":null}';
$plaintextFirstBlock = substr($plaintext, 0 , 16);                                                                                // First block / 16 Byte of plaintext
$ivReconstructed = $decryptedFirstBlock ^ $plaintextFirstBlock;
print('Reconstructed IV: '.bin2hex($ivReconstructed)."\n");

预期输出未加密到给定的
$data
。字符串
oiaeybksadbljihutbpl9k6ahtxt3v4g2dlysvrsjzqw3ep6if4lkjpzkrhow+J
解密到您的预期输出
{“regu no”:“UP2345678”,“token”:null}
。请将您的问题包括源代码,说明您如何加密原始消息/内容。Quote**“如果已知密钥、明文和密文,则可以重建IV”**你能解释一下你是如何得到这个3B297D28642443363339332B2D2826的吗?实际上,我已经描述过它(“密文的第一块被解密(没有IV),结果与明文的第一块异或。”)。我现在已经更详细地解释了这两个步骤,请参阅我答案中的编辑部分。