key = $key; // IV القديم للتوافقية أثناء مرحلة المايغريشن $this->cbcIv = $cbcIv ?: getenv('initializationVector') ?: str_repeat('0', 16); } // ─── تشفير نص باستخدام AES-256-GCM ── public function encryptData(string $plainText): string { $plainText = mb_convert_encoding($plainText, 'UTF-8'); $iv = random_bytes(self::IV_LEN_GCM); $tag = ''; $encrypted = openssl_encrypt($plainText, self::ALGO_GCM, $this->key, OPENSSL_RAW_DATA, $iv, $tag, "", self::TAG_LEN); return self::PREFIX_GCM . base64_encode($iv . $tag . $encrypted); } // ─── فك تشفير نص (يدعم CBC والـ GCM المستقبلي) ─────────── public function decryptData(string $cipherText): string|false { // تحقق إن كان مشفر بالنظام الجديد if (str_starts_with($cipherText, self::PREFIX_GCM)) { $raw = base64_decode(substr($cipherText, strlen(self::PREFIX_GCM)), true); if ($raw === false || strlen($raw) < self::IV_LEN_GCM + self::TAG_LEN) return false; $iv = substr($raw, 0, self::IV_LEN_GCM); $tag = substr($raw, self::IV_LEN_GCM, self::TAG_LEN); $cipher = substr($raw, self::IV_LEN_GCM + self::TAG_LEN); $plain = openssl_decrypt($cipher, self::ALGO_GCM, $this->key, OPENSSL_RAW_DATA, $iv, $tag); return $plain !== false ? $plain : false; } // وإلا استخدم CBC القديم $decoded = base64_decode($cipherText, true); if ($decoded === false) return false; $decrypted = openssl_decrypt($decoded, self::ALGO_CBC, $this->key, OPENSSL_RAW_DATA, $this->cbcIv); if ($decrypted === false) return false; $pad = ord($decrypted[strlen($decrypted) - 1]); if ($pad < 1 || $pad > 16) return false; return substr($decrypted, 0, -$pad); } // ─── تشفير/فك تشفير Binary (صور، ملفات) ─────────────── // تُستخدم الـ GCM مع IV عشوائي (كما في encryptData) public function encryptBinary(string $data): string { $iv = random_bytes(self::IV_LEN_GCM); $tag = ''; $encrypted = openssl_encrypt($data, self::ALGO_GCM, $this->key, OPENSSL_RAW_DATA, $iv, $tag, "", self::TAG_LEN); return base64_encode($iv . $tag . $encrypted); } public function decryptBinary(string $data): string|false { $raw = base64_decode($data, true); if ($raw === false || strlen($raw) < self::IV_LEN_GCM + self::TAG_LEN) return false; $iv = substr($raw, 0, self::IV_LEN_GCM); $tag = substr($raw, self::IV_LEN_GCM, self::TAG_LEN); $cipher = substr($raw, self::IV_LEN_GCM + self::TAG_LEN); return openssl_decrypt($cipher, self::ALGO_GCM, $this->key, OPENSSL_RAW_DATA, $iv, $tag); } // --------- دوال الـ Padding للـ CBC ---------- private function addPadding($data, $blockSize = 16) { $pad = $blockSize - (strlen($data) % $blockSize); return $data . str_repeat(chr($pad), $pad); } private function removePadding($data) { $pad = ord($data[strlen($data) - 1]); return substr($data, 0, -$pad); } }