<?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)); } }