I have a 1MB test file and I want to decrypt it starting from its 500KB, not from the beginning. It doesn't need to start exactly from 500KB of the file, it can start at the beginning of any chunk as long as it's not the first, I just want to learn how to do it.
With this script I can decrypt the file as long as its starts from 0KB.
$file = file_get_contents("file.dat");
$aeskey = base64_decode("sVv2g7boc/pzCDepDfV1VA==");
$iv = base64_decode("A5chWWE3D4cAAAAAAAAAAA==");
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'ctr', '');
mcrypt_generic_init($td, $aeskey, $iv);
echo mdecrypt_generic($td, $file);
Could someone please explain me if it is at least possible?
In CTR mode, a counter (128 bit for AES) is encrypted to produce a key stream that is then XORed with the plaintext or ciphertext. Usually, it is assumed that the IV is either 64 bit or 96 bit and the remaining bits are actually set to 0. The initial 64 or 96 bit are called nonce.
The size of the nonce determines how much data can be encrypted in one go without creating a many-time pad: the larger the nonce, the smaller the safe message length, but also lower probability of collisions of two nonces when they are generated randomly. Since there is no specification how big the nonce is, many frameworks don't limit the size of a nonce to a specific size.
You can use the full block size for a nonce in mcrypt.
You can
Steps 2-4 are accomplished by the add
function in the following code.
Let's say you have a big file but want to decrypt from byte 512 (multiple of the block size for simplicity). You would add 512/16=32 to the IV.
Here is some example code:
<?php
$d = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
$k = "k0k1k2k3k4k5k6k7"; // 16 byte AES key
$bs = 16; // 16 byte block size
$iv = mcrypt_create_iv($bs);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'ctr', '');
mcrypt_generic_init($td, $k, $iv);
$ct = mcrypt_generic($td, $d);
$dec_offset = 32;
$ct_slice = substr($ct, $dec_offset);
$iv_slice = add($iv, $dec_offset / $bs);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', 'ctr', '');
mcrypt_generic_init($td, $k, $iv_slice);
$d_slice = mdecrypt_generic($td, $ct_slice);
var_dump($d_slice);
function add($big_num_str, $to_add){
$big_num = str_split(strrev($big_num_str));
for($i = 0; $i < count($big_num) ; $i++){
$tmp = ord($big_num[$i]) + $to_add;
$big_num[$i] = $tmp % 256;
$to_add = floor( $tmp / 256 );
}
while($to_add){
$big_num[$i++] = $to_add % 256;
$to_add = floor( $to_add / 256 );
}
for($i = 0; $i < count($big_num) ; $i++){
$big_num[$i] = chr($big_num[$i]);
}
return strrev(implode('', $big_num) );
}
Output:
string(32) "101112131415161718191a1b1c1d1e1f"
This also work in the exact same way for the OpenSSL extension in PHP. Here is the code.
Of course, this would be a little more complicated if you want to get a chunk that doesn't begin on a block boundary. You would have to start a block earlier and remove the excess bytes.