0

I am following along with a tutorial on encryption: https://php.watch/articles/modern-php-encryption-decryption-sodium. In working with the Sodium extension I'm just baffled by a few things. Googling is returning frustratingly little help. (Most of the results are just duplications of the php.net/manual.)

1. In various articles I'm reading, the result of sodium_crypto_*_encrypt() is something familiar:

// ex. DEx9ATXEg/eRq8GWD3NT5BatB3m31WED

Whenever I echo it out myself I get something like:

// ex. �2(*���3�CV��Wu��R~�u���H��

which I'm certain won't store correctly on a database. Nowhere in the articles or documentation does it mention anything about charset weirdness. I can throw a header('Content-Type: text/html; charset=ISO-8859-1') in there, but I still get weird characters I'm not certain are right since I'm not finding any threads talking about this:

// ex. ÑAÁ5eŠ…n@±'ýÞÃ1è9ÜÈ̳¬"CžãÚ0ÿÛ

2. I can't find any information about the best practice for storing keys or nonces.

I just figured this obvious-to-security-folks-but-not-to-others bit of information would be a regularly discussed part of articles on keygens and nonces and such. Seeing as both my keygen and nonce functions (at least in the Sodium library) seem to return non-UTF-8 gibberish, what do I do with it? fwrite it out to a file to be referenced later? Pass it directly to my database? Copy/pasting certainly doesn't work right with it being wingdings.

Other than these things, everything else in the encryption/decryption process makes complete sense to me. I'm far from new to PHP development, I just can't figure this out.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Phil Tune
  • 3,154
  • 3
  • 24
  • 46
  • guess the *encrypt functions return a byte stream. You can probably convert to text using e.g. `base64_encode`. – berend Dec 10 '21 at 20:42
  • @berend so trying that. It doesn't seem to clear that up. Dumping `base64_encode($secret)` returns `(string) "̷$>�q["`. I hadn't seen anywhere talking about it returning byte streams. Some of the functions work with streams, but not the keygens. Even `random_bytes($n)` is returning gibberish for me. Thinking i have some off settings in my MAMP possibly. – Phil Tune Dec 10 '21 at 20:53
  • Hold on. https://stackoverflow.com/a/44874239/1128978 suggests using `bin2hex()` for `random_bytes`. Checking to see if this works with sodium output also. – Phil Tune Dec 10 '21 at 21:01

1 Answers1

1

Came across https://stackoverflow.com/a/44874239/1128978 answering "PHP random_bytes returns unreadable characters"

random_bytes generates an arbitrary length string of cryptographic random bytes...

And suggests to use bin2hex to get readable characters. So amending my usages:

// Generate $ciphertext
$message = 'This is a secret message';
$key = sodium_crypto_*_keygen();
$nonce = random_bytes(SODIUM_CRYPTO_*BYTES);
$ciphertext = sodium_crypto_*_encrypt($message, '', $nonce, $key);

// Store hexadecimal versions of binary output
$nonce_hex = bin2hex($nonce);
$key_hex = bin2hex($key);
$ciphertext_hex = bin2hex($ciphertext);

// When ready to decrypt, convert hexadecimal values back to binary
$ciphertext_bin = hex2bin($ciphertext_hex);
$nonce_bin = hex2bin($nonce_hex);
$key_bin = hex2bin($key_hex);

$decrypted = sodium_crypto_*_decrypt($ciphertext_bin, '', $nonce_bin, $key_bin);
// "This is a secret message"

So making lots of use of bin2hex and hex2bin, but this now makes sense. Effectively solved, though not confident this is the proper way to work with it. I still have no idea why this isn't pointed out anywhere in php.net/manual nor in any of the articles/comments I've been perusing.

Phil Tune
  • 3,154
  • 3
  • 24
  • 46