key = sodium_crypto_generichash( (string) $material, '', SODIUM_CRYPTO_SECRETBOX_KEYBYTES ); } /** * The box keyed by this site's salts. * * wp_salt() rather than the raw constants: it also answers on installs whose salts are kept * in the database. * * @return self */ public static function from_salts() { return new self( wp_salt( 'auth' ) . wp_salt( 'secure_auth' ) ); } /** * Seal a string. * * @param string $plain Plain text. * @return string Empty for empty input, otherwise PREFIX + base64( nonce . ciphertext ). */ public function encrypt( $plain ) { $plain = (string) $plain; if ( '' === $plain ) { return ''; } $nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- Binary ciphertext made storable, not obfuscation. return self::PREFIX . base64_encode( $nonce . sodium_crypto_secretbox( $plain, $nonce, $this->key ) ); } /** * Open a sealed string. * * @param string $stored Value produced by encrypt(). * @return string|false The plain text, or false when it cannot be opened (wrong key, * tampering, or a value this class did not make). */ public function decrypt( $stored ) { $stored = (string) $stored; if ( '' === $stored ) { return ''; } if ( 0 !== strpos( $stored, self::PREFIX ) ) { return false; } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode -- Reverses encrypt(). $raw = base64_decode( substr( $stored, strlen( self::PREFIX ) ), true ); if ( false === $raw || strlen( $raw ) <= SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ) { return false; } $nonce = substr( $raw, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ); $plain = sodium_crypto_secretbox_open( substr( $raw, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES ), $nonce, $this->key ); return false === $plain ? false : $plain; } }