For my particular PHP (8.2) Web Application I am storing keys and secrets in an .ini
file outside of root in a folder /private
.
I have been requested to encrypt the data in the ini file (reason stating that the php code is accessing the key details without any security measures).
$cfg = parse_ini_file('../../private/config.ini');
$my_secret_key_123 = $cfg['secret_key_123'];
$my_secret_key_345 = $cfg['secret_key_345'];
I was thinking I could just encrypt all of the data using sodium
:
$key = sodium_crypto_secretbox_keygen();
$nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
$encrypted_result = sodium_crypto_secretbox( 'secret_key_123', $nonce, $key );
$encoded_secret_key_123 = base64_encode( $nonce . $encrypted_result );
However, if I put that encoded secret key in my .ini
file and call it, I will need to have the $key
and $nonce
used to decrypt it:
$decoded = base64_decode($encoded_secret_key_123, false);
$nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
$encrypted_result = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
$plaintext = sodium_crypto_secretbox_open($encrypted_result, $nonce, $key);
So the question arises...where and how would I store the key sodium_crypto_secretbox_keygen()
without also encrypting that?
Perhaps this is simply overkill and I should just encode my .ini
secrets with simple base64
?
What I have ended up doing is storing the key produced from sodium_crypto_secretbox_keygen()
in a .env
file.
$sodium_key = sodium_crypto_secretbox_keygen();
var_dump( sodium_bin2hex($sodium_key)); // store as hex
Store the above output to the .env
file:
so_key = 1234567890abcdefghijklmnopqrstuvwxyz
One must use the PHP library dotenv
to easily load the .env
file which I put outside of root in a private folder.
require '../../private/vendor/autoload.php'; //autoloader for dotenv
$dotenv = Dotenv\Dotenv::createImmutable('../../private/'); //location of .env file
$dotenv->load(); //allows for $_ENV environment variable to be called
$so_key = sodium_hex2bin($_ENV['so_key']); //dont forget this is hex 2 bin
What I ended up doing was encoding all of my secret keys and stored the encoding of them in the same .env
file mentioned above.
Here are the functions I made to either encode or decode the data utilizing sodium
:
// Encode your string
function so_encode($encode, $so_key){
$nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
$encrypted_result = sodium_crypto_secretbox( $encode, $nonce, $so_key );
$encoded = base64_encode( $nonce . $encrypted_result );
return $encoded;
}
// Decode your string
function so_decode($so_encoded,$so_key){
$decoded = base64_decode($so_encoded, false);
$nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
$encrypted_result = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
$plaintext = sodium_crypto_secretbox_open($encrypted_result, $nonce, $so_key);
return $plaintext;
}