key = hash('sha256', $passphrase, true); $this->search_key = hash('sha256', $passphrase_s, true); } // Enkripsi plaintext → base64(iv[12] + tag[16] + ciphertext) public function encrypt($plaintext) { if ($plaintext === null || $plaintext === '') return null; $iv = random_bytes(12); $tag = ''; $ct = openssl_encrypt((string)$plaintext, $this->cipher, $this->key, OPENSSL_RAW_DATA, $iv, $tag, '', $this->tag_length); if ($ct === false) return null; return base64_encode($iv . $tag . $ct); } // Dekripsi base64(iv + tag + ciphertext) → plaintext public function decrypt($ciphertext) { if ($ciphertext === null || $ciphertext === '') return null; $raw = base64_decode($ciphertext); if (strlen($raw) < 12 + $this->tag_length) return null; $iv = substr($raw, 0, 12); $tag = substr($raw, 12, $this->tag_length); $ct = substr($raw, 12 + $this->tag_length); $pt = openssl_decrypt($ct, $this->cipher, $this->key, OPENSSL_RAW_DATA, $iv, $tag); return $pt === false ? null : $pt; } // Hasilkan JSON array trigram token untuk kolom _bidx (partial search) public function search_bidx($value) { if ($value === null || $value === '') return null; $norm = mb_strtolower(trim((string)$value), 'UTF-8'); $len = mb_strlen($norm, 'UTF-8'); $tokens = []; if ($len <= 3) { $tokens[] = $this->_token($norm); } else { for ($i = 0; $i <= $len - 3; $i++) { $tokens[] = $this->_token(mb_substr($norm, $i, 3, 'UTF-8')); } } return json_encode(array_values(array_unique($tokens))); } // Hasilkan array trigram token dari query string (untuk WHERE JSON_CONTAINS) public function query_tokens($value) { if ($value === null || $value === '') return []; $norm = mb_strtolower(trim((string)$value), 'UTF-8'); $len = mb_strlen($norm, 'UTF-8'); $tokens = []; if ($len <= 3) { $tokens[] = $this->_token($norm); } else { for ($i = 0; $i <= $len - 3; $i++) { $tokens[] = $this->_token(mb_substr($norm, $i, 3, 'UTF-8')); } } return array_values(array_unique($tokens)); } private function _token($str) { return hash_hmac('sha256', $str, $this->search_key); } }