0

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?

ToddN
  • 2,901
  • 14
  • 56
  • 96
  • You can store your secrets externally in a dedicated store like Hashicorp Vault, but your app still needs at least one plain secret to access the Vault, which makes it more of a question of how to inject secrets at app startup. For that most things tend to use environment variables or injected config files. All that said, base64 hides nothing from no one. Just leave it plain. – Sammitch Dec 13 '22 at 21:32
  • @Sammitch Thanks, I tended to opt for the environment variables storing the sodium key and other secrets sodium encrypted. – ToddN Dec 13 '22 at 21:41

1 Answers1

0

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;
}
ToddN
  • 2,901
  • 14
  • 56
  • 96