2021-11-11 14:25:26 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Objects;
|
|
|
|
|
|
|
|
class AesStream {
|
|
|
|
|
|
|
|
private string $key;
|
|
|
|
private string $iv;
|
|
|
|
private $callback;
|
|
|
|
private ?string $outputFile;
|
|
|
|
private ?string $inputFile;
|
|
|
|
|
|
|
|
public function __construct(string $key, string $iv) {
|
|
|
|
$this->key = $key;
|
|
|
|
$this->iv = $iv;
|
|
|
|
$this->inputFile = null;
|
|
|
|
$this->outputFile = null;
|
|
|
|
$this->callback = null;
|
|
|
|
|
|
|
|
if (!in_array(strlen($key), [16, 24, 32])) {
|
|
|
|
throw new \Exception("Invalid Key Size");
|
|
|
|
} else if (strlen($iv) !== 16) {
|
|
|
|
throw new \Exception("Invalid IV Size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 16:53:43 +01:00
|
|
|
public function setInputFile(string $file) {
|
2021-11-11 14:25:26 +01:00
|
|
|
$this->inputFile = $file;
|
|
|
|
}
|
|
|
|
|
2021-12-08 16:53:43 +01:00
|
|
|
public function setOutput(callable $callback) {
|
2021-11-11 14:25:26 +01:00
|
|
|
$this->callback = $callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setOutputFile(string $file) {
|
|
|
|
$this->outputFile = $file;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function start(): bool {
|
|
|
|
if (!$this->inputFile) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$blockSize = 16;
|
2021-12-08 16:53:43 +01:00
|
|
|
$aesMode = $this->getCipherMode();
|
2021-11-11 14:25:26 +01:00
|
|
|
|
|
|
|
$outputHandle = null;
|
|
|
|
$inputHandle = fopen($this->inputFile, "rb");
|
|
|
|
if (!$inputHandle) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->outputFile !== null) {
|
|
|
|
$outputHandle = fopen($this->outputFile, "wb");
|
|
|
|
if (!$outputHandle) {
|
2021-12-08 16:53:43 +01:00
|
|
|
fclose($inputHandle);
|
2021-11-11 14:25:26 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 16:53:43 +01:00
|
|
|
set_time_limit(0);
|
|
|
|
|
|
|
|
$ivCounter = $this->iv;
|
|
|
|
$modulo = \gmp_init("0x1" . str_repeat("00", $blockSize), 16);
|
|
|
|
|
2021-11-11 14:25:26 +01:00
|
|
|
while (!feof($inputHandle)) {
|
2021-12-08 16:53:43 +01:00
|
|
|
$chunk = fread($inputHandle, 65536);
|
2021-11-11 14:25:26 +01:00
|
|
|
$chunkSize = strlen($chunk);
|
2021-12-08 16:53:43 +01:00
|
|
|
if ($chunkSize > 0) {
|
|
|
|
$blockCount = intval(ceil($chunkSize / $blockSize));
|
|
|
|
$encrypted = openssl_encrypt($chunk, $aesMode, $this->key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $ivCounter);
|
2021-11-11 14:25:26 +01:00
|
|
|
|
2021-12-08 16:53:43 +01:00
|
|
|
$ivNumber = \gmp_init(bin2hex($ivCounter), 16);
|
|
|
|
$ivNumber = \gmp_add($ivNumber, $blockCount);
|
|
|
|
$ivNumber = \gmp_mod($ivNumber, $modulo);
|
|
|
|
$ivNumber = str_pad(\gmp_strval($ivNumber, 16), $blockSize * 2, "0", STR_PAD_LEFT);
|
|
|
|
$ivCounter = hex2bin($ivNumber);
|
|
|
|
|
|
|
|
if ($this->callback !== null) {
|
2021-11-11 14:25:26 +01:00
|
|
|
call_user_func($this->callback, $encrypted);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($outputHandle !== null) {
|
|
|
|
fwrite($outputHandle, $encrypted);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose($inputHandle);
|
|
|
|
if ($outputHandle) fclose($outputHandle);
|
|
|
|
return true;
|
|
|
|
}
|
2021-12-08 16:53:43 +01:00
|
|
|
|
|
|
|
public function getCipherMode(): string {
|
|
|
|
$bitStrength = strlen($this->key) * 8;
|
|
|
|
return "aes-$bitStrength-ctr";
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getKey(): string {
|
|
|
|
return $this->key;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIV(): string {
|
|
|
|
return $this->iv;
|
|
|
|
}
|
2021-11-11 14:25:26 +01:00
|
|
|
}
|