Block cipher modes are really simple, you can just implement them yourself if two implementations aren't compatible.
Here is a CTR implementation for your particular case:
function ctr_crypt($str, $key, $iv) {
$numOfBlocks = ceil(strlen($str) / 16);
$ctrStr = '';
for ($i = 0; $i < $numOfBlocks; ++$i) {
$ctrStr .= $iv;
// increment IV
for ($j = 0; $j < 16; ++$j) {
$n = ord($iv[$j]);
if (++$n == 0x100) {
// overflow, set this one to 0, increment next
$iv[$j] = "\0";
} else {
// no overflow, just write incremented number back and abort
$iv[$j] = chr($n);
break;
}
}
}
return $str ^ mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $ctrStr, MCRYPT_MODE_ECB);
}
The algorithm is very simple: You always append and increment the IV until you have a string that is longer (or of equal length) as the input string. Then you encrypt this string using ECB mode and XOR it with the input string.
The incrementation is the complicated part here, because we are dealing with a number in binary. Little Endian means we increment from left to right (j = 0, j < 16, j++). Big Endian would mean that we increment from right to left (j = 15, j >= 0, j--).
Try it out:
$encrypted = base64_decode('MlNFlnXE1sqIsmKZRtjChBvUMgiJlXgdjHVxQJ6JK24Id4uaN9NK/nBtY+cgrMJR/PRJRCmIUx0boQO5XqJYZ8VJ0w==');
$key = base64_decode('HB+dD1Irj2rXQ/nO+IuqSiK9xVE3PD9cZGIGzrMtwtA=');
$iv = base64_decode('2gxxKYU/G4lj7174e5wj+g==');
var_dump(ctr_crypt($encrypted, $key, $iv));
// string(67) "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do..."
Note: ctr_crypt
works both as an encryption and as a decryption function.