Skip to content

Instantly share code, notes, and snippets.

@kasparsd
Created March 19, 2025 09:55
Show Gist options
  • Save kasparsd/dd772542ecec7cc8e40a7d6e6339711c to your computer and use it in GitHub Desktop.
Save kasparsd/dd772542ecec7cc8e40a7d6e6339711c to your computer and use it in GitHub Desktop.
Initial draft
<?php
abstract class WP_Encrypted_Secret_Method {
protected WP_Encrypted_Secret_Storage $storage;
public function __construct( WP_Encrypted_Secret_Storage $storage ) {
$this->storage = $storage;
}
abstract public function is_supported(): bool;
abstract public function encrypt( string $value ): string;
abstract public function decrypt( string $value ): string;
}
abstract class WP_Encrypted_Secret_Storage {
abstract public function is_supported(): bool;
abstract public function set( string $secret_key ): bool;
abstract public function get(): ?string;
}
class WP_Encrypted_Secret_Storage_File extends WP_Encrypted_Secret_Storage {
protected string $file;
public function __construct( string $file_path ) {
$this->file = $file_path;
}
public function is_supported(): bool {
return is_writable( dirname( $this->file ) );
}
public function set( string $secret_key ): bool {
$secret = [
'key' => base64_encode( $secret_key ),
'created' => time(),
];
$secret_stored = sprintf( '<?php return %s;', var_export( $secret, true ) );
if ( $this->is_supported() ) {
return (bool) file_put_contents( $this->file, $secret_stored );
}
return false;
}
public function get(): ?string {
if ( is_readable( $this->file ) ) {
$secret = include $this->file;
if ( is_array( $secret ) && ! empty( $secret['key'] ) ) {
return base64_decode( $secret['key'] ) ?? null;
}
}
return null;
}
}
class WP_Encrypted_Method_Sodium_Secretbox extends WP_Encrypted_Secret_Method {
public function is_supported(): bool {
return function_exists( 'sodium_crypto_secretbox_keygen' ) && function_exists( 'sodium_crypto_secretbox' );
}
public function is_configured(): bool {
return ! empty( $this->storage->get() );
}
public function configure(): bool {
if ( $this->is_supported() ) {
return $this->storage->set( sodium_crypto_secretbox_keygen() );
}
return false;
}
public function encrypt( string $value ): string {
$secret_key = $this->storage->get();
if ( ! empty( $secret_key ) ) {
$nonce = sodium_crypto_generichash( $value, '', SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
$encrypted = sodium_crypto_secretbox( $value, $nonce, $secret_key );
return base64_encode( $nonce . $encrypted );
}
return $value;
}
public function decrypt( string $value ): string {
$encrypted = base64_decode( $value );
$secret_key = $this->storage->get();
if ( $encrypted && ! empty( $secret_key ) ) {
$nonce = substr( $encrypted, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
$encrypted = substr( $encrypted, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
if ( ! empty( $secret_key ) && ! empty( $nonce ) && ! empty( $encrypted ) ) {
return sodium_crypto_secretbox_open( $encrypted, $nonce, $secret_key );
}
}
return $value;
}
}
$storage = new WP_Encrypted_Secret_Storage_File( __DIR__ . '/secret.php' );
$method = new WP_Encrypted_Method_Sodium_Secretbox( $storage );
if ( $method->is_supported() && $storage->is_supported() ) {
if ( ! $method->is_configured() ) {
$method->configure();
}
$encrypted = $method->encrypt( 'Hello, World!' );
var_dump( $encrypted, $method->decrypt( $encrypted ) );
//add_filter( 'option_' . $option_name, [ $option, 'decrypt' ] );
//add_filter( 'pre_update_option_' . $option_name, [ $option, 'encrypt' ] );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment