error( 'Encryption failed: ' . openssl_error_string(), 'encryption' ); return ''; } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode return self::PREFIX . base64_encode( $iv . $ciphertext ); } /** * Decrypt a previously encrypted string. * * Handles both prefixed ("enc:...") and legacy non-prefixed values for * backward compatibility during the transition. * * @param string $encrypted Prefixed base64-encoded ciphertext. * * @return string The original plaintext, or empty string on failure. */ public static function decrypt( string $encrypted ): string { if ( '' === $encrypted ) { return ''; } // Strip the prefix if present. $payload = $encrypted; if ( self::is_encrypted( $encrypted ) ) { $payload = substr( $encrypted, strlen( self::PREFIX ) ); } $key = self::get_key(); $iv_len = (int) openssl_cipher_iv_length( self::METHOD ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode $raw = base64_decode( $payload, true ); if ( false === $raw || strlen( $raw ) <= $iv_len ) { PRAutoBlogger_Logger::instance()->error( 'Decryption failed: invalid ciphertext format.', 'encryption' ); return ''; } $iv = substr( $raw, 0, $iv_len ); $ciphertext = substr( $raw, $iv_len ); $plaintext = openssl_decrypt( $ciphertext, self::METHOD, $key, OPENSSL_RAW_DATA, $iv ); if ( false === $plaintext ) { PRAutoBlogger_Logger::instance()->error( 'Decryption failed: ' . openssl_error_string(), 'encryption' ); return ''; } return $plaintext; } /** * Derive the encryption key from WordPress salts. * * @return string 32-byte key suitable for AES-256. */ private static function get_key(): string { return hash( 'sha256', wp_salt( 'auth' ), true ); } }