key() ) ); } /** * Decrypts a value produced by encrypt(). * * @param mixed $payload Encrypted value; invalid types are rejected. * @return string Plain text, or an empty string when the value can't be decrypted. */ public function decrypt( $payload ) { if ( ! is_string( $payload ) || 0 !== strpos( $payload, self::PREFIX ) ) { return ''; } $hex = substr( $payload, strlen( self::PREFIX ) ); if ( strlen( $hex ) < 2 * ( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + SODIUM_CRYPTO_SECRETBOX_MACBYTES ) || 0 !== strlen( $hex ) % 2 || ! preg_match( '/\A[0-9a-fA-F]+\z/', $hex ) ) { return ''; } $raw = hex2bin( $hex ); if ( false === $raw ) { return ''; } $nonce = substr( $raw, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $box = substr( $raw, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); try { $plain = sodium_crypto_secretbox_open( $box, $nonce, $this->key() ); } catch ( \Throwable $e ) { return ''; } return false === $plain ? '' : $plain; } /** * Derives the 32-byte encryption key. * * @return string */ private function key() { if ( defined( 'TURTLEREPORT_ENCRYPTION_KEY' ) && TURTLEREPORT_ENCRYPTION_KEY ) { $material = (string) TURTLEREPORT_ENCRYPTION_KEY; } else { $material = wp_salt( 'auth' ); } return sodium_crypto_generichash( 'turtlereport|' . $material, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES ); } }