Created
March 19, 2025 09:55
-
-
Save kasparsd/dd772542ecec7cc8e40a7d6e6339711c to your computer and use it in GitHub Desktop.
Initial draft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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