clrghouz/app/Classes/Crypt.php

97 lines
1.8 KiB
PHP

<?php
namespace App\Classes;
use App\Interfaces\CRC as CRCInterface;
class Crypt implements CRCInterface
{
private array $keys= [
305419896,
591751049,
878082192,
];
public function __construct(string $password)
{
$this->extend_key($password);
}
/**
* Update crc.
*/
private function crc32_cr(int $oldCrc, int $charAt): int
{
return (($oldCrc >> 8) & 0xFFFFFF) ^ self::crc32_tab[($oldCrc ^ $charAt) & 0xFF];
}
public function decrypt(string $content): string
{
$result = '';
foreach (unpack('C*', $content) as $byte) {
$byte = ($byte ^ $this->decrypt_byte()) & 0xFF;
$this->update_keys($byte);
$result .= chr($byte);
}
return $result;
}
/**
* Decrypt byte.
*/
private function decrypt_byte(): int
{
$temp = $this->keys[2] | 2;
return (($temp * ($temp ^ 1)) >> 8) & 0xFFFFFF;
}
public function encrypt(string $content): string
{
$result = '';
foreach (unpack('C*', $content) as $val)
$result .= pack('c', $this->encrypt_byte($val));
return $result;
}
private function encrypt_byte(int $byte): int
{
$result = $byte ^ $this->decrypt_byte() & 0xFF;
$this->update_keys($byte);
return $result;
}
public function extend_key(string $password): void
{
foreach (unpack('C*', $password) as $byte)
$this->update_keys($byte);
}
public static function toSignedInt32(int $int): int
{
if (\PHP_INT_SIZE === 8) {
$int &= 0xFFFFFFFF;
if ($int & 0x80000000)
return $int - 0x100000000;
}
return $int;
}
/**
* Update keys.
*/
private function update_keys(int $byte): void
{
$this->keys[0] = $this->crc32_cr($this->keys[0],$byte);
$this->keys[1] += ($this->keys[0] & 0xFF);
$this->keys[1] = $this->toSignedInt32($this->keys[1]*134775813+1);
$this->keys[2] = $this->toSignedInt32($this->crc32_cr($this->keys[2],($this->keys[1] >> 24) & 0xFF));
}
}