我正在尝试使用功能openssl_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}
答案 0 :(得分:1)
CBC模式需要IV。加密的IV必须用于解密。在发布的示例中,openssl_decrypt
调用中没有传递任何IV(对应于具有0值的IV),因此第一个块(1块= 16字节)被错误地解密。
原则上,如果密钥,明文和密文是已知的,则可以重建IV:密文的第一个块被解密(没有IV),并且结果与明文的第一个块进行异或。这将为发布的示例中的数据(以十六进制字符串)产生以下IV:3B297D2864244336363339332B2D2826
。使用此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:在CBC-模式的描述中,可以看出,在加密开始时,对明文和IV进行XOR运算,然后对结果进行加密。因此,可以通过首先解密此第一个加密块,然后将结果与纯文本进行异或运算来确定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");
答案 1 :(得分:0)
@Topaco
非常感谢!
我想我需要开始学习密码学...:-)