Overview
Cryptography is a fascinating subject, that I hope we’ll explore further in the future. This post will cover a practical use-case for encryption within a PHP based project. WIthin this guide you will learn the ins and outs of encypting with native PHP.
Intro to Sodium
So what is Sodium?
Here’s a direct quote from the creators and maintainers of the library:
Sodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more.
LibSodium intro page: https://libsodium.gitbook.io/doc/
It is a portable, cross-compilable, installable, packageable fork of NaCl, with a compatible API, and an extended API to improve usability even further.
Its goal is to provide all of the core operations needed to build higher-level cryptographic tools.
Sodium includes a metric ton of useful functions, some of which tend to be on the high-end use-case scenarios for encryption. For the purposes of keeping this guide readable, I’ll just share the vast amount of functions here, and we’ll go in depth into each one, and what it does, at a later date
Functions listing:
sodium_add — Add large numbers
sodium_base642bin — Description
sodium_bin2base64 — Description
sodium_bin2hex — Encode to hexadecimal
sodium_compare — Compare large numbers
sodium_crypto_aead_aes256gcm_decrypt — Decrypt in combined mode with precalculation
sodium_crypto_aead_aes256gcm_encrypt — Encrypt in combined mode with precalculation
sodium_crypto_aead_aes256gcm_is_available — Check if hardware supports AES256-GCM
sodium_crypto_aead_aes256gcm_keygen — Get random bytes for key
sodium_crypto_aead_chacha20poly1305_decrypt — Verify that the ciphertext includes a valid tag
sodium_crypto_aead_chacha20poly1305_encrypt — Encrypt a message
sodium_crypto_aead_chacha20poly1305_ietf_decrypt — Verify that the ciphertext includes a valid tag
sodium_crypto_aead_chacha20poly1305_ietf_encrypt — Encrypt a message
sodium_crypto_aead_chacha20poly1305_ietf_keygen — Get random bytes for key
sodium_crypto_aead_chacha20poly1305_keygen — Get random bytes for key
sodium_crypto_aead_xchacha20poly1305_ietf_decrypt — Description
sodium_crypto_aead_xchacha20poly1305_ietf_encrypt — Description
sodium_crypto_aead_xchacha20poly1305_ietf_keygen — Description
sodium_crypto_auth_keygen — Get random bytes for key
sodium_crypto_auth_verify — Verifies that the tag is valid for the message
sodium_crypto_auth — Compute a tag for the message
sodium_crypto_box_keypair_from_secretkey_and_publickey — Description
sodium_crypto_box_keypair — Randomly generate a secret key and a corresponding public key
sodium_crypto_box_open — Verify and decrypt a ciphertext
sodium_crypto_box_publickey_from_secretkey — Description
sodium_crypto_box_publickey — Description
sodium_crypto_box_seal_open — Decrypt the ciphertext
sodium_crypto_box_seal — Encrypt a message
sodium_crypto_box_secretkey — Description
sodium_crypto_box_seed_keypair — Deterministically derive the key pair from a single key
sodium_crypto_box — Encrypt a message
sodium_crypto_generichash_final — Complete the hash
sodium_crypto_generichash_init — Initialize a hash
sodium_crypto_generichash_keygen — Get random bytes for key
sodium_crypto_generichash_update — Add message to a hash
sodium_crypto_generichash — Get a hash of the message
sodium_crypto_kdf_derive_from_key — Derive a subkey
sodium_crypto_kdf_keygen — Get random bytes for key
sodium_crypto_kx_client_session_keys — Description
sodium_crypto_kx_keypair — Creates a new sodium keypair
sodium_crypto_kx_publickey — Description
sodium_crypto_kx_secretkey — Description
sodium_crypto_kx_seed_keypair — Description
sodium_crypto_kx_server_session_keys — Description
sodium_crypto_pwhash_scryptsalsa208sha256_str_verify — Verify that the password is a valid password verification string
sodium_crypto_pwhash_scryptsalsa208sha256_str — Get an ASCII encoded hash
sodium_crypto_pwhash_scryptsalsa208sha256 — Derives a key from a password
sodium_crypto_pwhash_str_needs_rehash — Description
sodium_crypto_pwhash_str_verify — Verifies that a password matches a hash
sodium_crypto_pwhash_str — Get an ASCII-encoded hash
sodium_crypto_pwhash — Derive a key from a password
sodium_crypto_scalarmult_base — Alias of sodium_crypto_box_publickey_from_secretkey
sodium_crypto_scalarmult — Compute a shared secret given a user's secret key and another user's public key
sodium_crypto_secretbox_keygen — Get random bytes for key
sodium_crypto_secretbox_open — Verify and decrypt a ciphertext
sodium_crypto_secretbox — Encrypt a message
sodium_crypto_secretstream_xchacha20poly1305_init_pull — Description
sodium_crypto_secretstream_xchacha20poly1305_init_push — Description
sodium_crypto_secretstream_xchacha20poly1305_keygen — Description
sodium_crypto_secretstream_xchacha20poly1305_pull — Description
sodium_crypto_secretstream_xchacha20poly1305_push — Description
sodium_crypto_secretstream_xchacha20poly1305_rekey — Description
sodium_crypto_shorthash_keygen — Get random bytes for key
sodium_crypto_shorthash — Compute a fixed-size fingerprint for the message
sodium_crypto_sign_detached — Sign the message
sodium_crypto_sign_ed25519_pk_to_curve25519 — Convert an Ed25519 public key to a Curve25519 public key
sodium_crypto_sign_ed25519_sk_to_curve25519 — Convert an Ed25519 secret key to a Curve25519 secret key
sodium_crypto_sign_keypair_from_secretkey_and_publickey — Description
sodium_crypto_sign_keypair — Randomly generate a secret key and a corresponding public key
sodium_crypto_sign_open — Check that the signed message has a valid signature
sodium_crypto_sign_publickey_from_secretkey — Extract the public key from the secret key
sodium_crypto_sign_publickey — Description
sodium_crypto_sign_secretkey — Description
sodium_crypto_sign_seed_keypair — Deterministically derive the key pair from a single key
sodium_crypto_sign_verify_detached — Verify signature for the message
sodium_crypto_sign — Sign a message
sodium_crypto_stream_keygen — Get random bytes for key
sodium_crypto_stream_xor — Encrypt a message
sodium_crypto_stream — Generate a deterministic sequence of bytes from a seed
sodium_hex2bin — Decodes a hexadecimally encoded binary string
sodium_increment — Increment large number
sodium_memcmp — Test for equality in constant-time
sodium_memzero — Overwrite buf with zeros
sodium_pad — Add padding data
sodium_unpad — Remove padding data
Ready to start tinkering? Cool, let’s get to work.
Installation
Here’s a simple guide on how to install the library on the major OS vendors:
Debian 8+, Ubuntu 15.04+
apt-get install libsodium-dev
Linux – older builds
sudo add-apt-repository ppa:chris-lea/libsodium
sudo apt-get update && sudo apt-get install libsodium-dev
Or
sudo echo "deb http://ppa.launchpad.net/chris-lea/libsodium/ubuntu precise main" >> /etc/apt/sources.list
sudo echo "deb-src http://ppa.launchpad.net/chris-lea/libsodium/ubuntu precise main" >> /etc/apt/sources.list
Fedora
dnf install libsodium-devel
CentOS
yum install libsodium-devel
OSX
brew install --build-from-source libsodium
Windows
- Grab a .zip that matches your requirements from here: Sodium-repo
- Copy the .dll file
libsodium.dll
to either%SYSTEM32%
or to the source directory, containing your PHP installation - Copy the other .dll file
php_libsodium.dll
to your extensions folder. It’s default path isext/
, but it could be modified via thephp.ini
file, so make sure to double-check. - Include the
extension=php_libsodium.dll
line to yourphp.ini
file, so that PHP can load the extension
Now double-check that the minor and major version of the extension match your requirements. You can simply run a var_dump()
on the following, to see the versions:
SODIUM_LIBRARY_MAJOR_VERSION
SODIUM_LIBRARY_MINOR_VERSION
Encrypting a message
This is the easiest way to get your foot through the door of encryption. Let’s generate a “nonce” message, rather than sending it in a clear-text format. The snippets below are hyper-simplified, but you can easily build up on them.
We’ll be using the sodium_crypto_box
command, which is a one-stop-shop for key-pair generation. If you’re not familiar with this concept, here’s an amazing explanation: Link
Scenario
Say John wants to send an encrypted message to Sasha, well he has to generate a key-pair for himself before he can proceed. (Yes I know I’m using names for personification of code blocks, but believe me, this can get confusing quite rapidly otherwise)
Let’s give John a set of keys:
$johns_key_pair = sodium_crypto_box_keypair();
$johns_public_key = sodium_crypto_box_publickey($johns_key_pair);
$johns_private_key = sodium_crypto_box_secretkey($johns_key_pair);
Cool, let’s do the same with Sasha:
$sashas_key_pair = sodium_crypto_box_keypair();
$sashas_public_key = sodium_crypto_box_publickey($sashas_key_pair);
$sashas_private_key = sodium_crypto_box_secretkey($sashas_key_pair);
Awesome, so John wants to send a message to Sasha, containing his most valued possession: Intel i7-7700HQ CPU
. We can write this out as follows:
$priced_possession = 'Intel i7-7700HQ CPU';
$throw_off_bytes = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
$encryption_key = sodium_crypto_box_keypair_from_secretkey_and_publickey($johns_private_key, $sashas_public_key);
$encrypted = sodium_crypto_box($priced_possession, $throw_off_bytes, $encryption_key);
If we run the following command: echo base64_encode($encrypted);
we can see this:
EBQEZAsKp4pWULJApRrVIQvmImOZ6alFY3+T/UoESHKtKxM=
The reason we encode it with Base64 is because the raw output look like this:
ǵ�3��XI-gkO6g���gG�`�
Awesome, so let’s see how Sasha would decrypt this message:
$decryption_key = sodium_crypto_box_keypair_from_secretkey_and_publickey($sashas_private_key, $johns_public_key);
$decrypted = sodium_crypto_box_open($encrypted, $throw_off_bytes, $decryption_key);
And running the echo shows us:
Intel i7-7700HQ CPU
Yay, you’ve enabled secure communication between John and Sasha.
The only clear-text values passed around are the public keys, which are always traded freely (by design), and the throw_off_bytes
, which look like so:
xYfK8vypDQXDycbhyp74U++8//32Gxnc
And now you’re all set to explore the magical world of cryptography.
Happy coding!