Skip to content.

Scott Arciszewski

Software, Privacy, Security, Innovation

Sodium in PHP: Asymmetric Crypto, Hold the Blood Pressure

Are you frustrated by the lack of a simple, fast, and secure asymmetric cryptography when developing PHP applications? Fear not, libsodium is coming to PECL.

Introduction

libsodium logo

What is Sodium?

Sodium is an upcoming (not released yet) PECL extension for the PHP programming language that exposes bindings for libsodium by Frank Denis — which is in turn a cross-platform derivative from NaCl, a library written by Daniel Bernstein and Tanja Lange, two of the world's foremost experts on elliptic curve cryptography, et al.

What is Elliptic Curve Cryptography?

If you want to truly understand what ECC is and how it works, ask a cryptographer.

As a developer, this is all you need to know right now:

  • It's lightweight. Elliptic Curve Cryptography fills the shoes of traditional implementations (DSA, Diffie-Hellman, etc.) with much smaller key sizes for the same level of security. For many cryptographic operations, this results in a performance gain.
  • It's time-tested. Elliptic Curve Cryptography is not "new"; it's been in academic literature since 1985.
  • It's still cryptography. All of the usual disclaimers (don't roll your own crypto-system, you are doomed to failure) still apply.

Why Would I Want Asymmetric Cryptography?

There are a number of use cases for asymmetric cryptography that cannot be solved by symmetric cryptography alone. Some examples include:

  1. Digital Signatures — digital signatures allow you to sign a document with a private key, and allow all of your customers verify the authenticity of the document using your public key.
  2. Symmetric Key Agreement — this allows you to share a secret (e.g. one-time AES key) over an untrusted network (i.e. the Internet) without an eavesdropper being able to intercept it. (Useful in peer-to-peer software.)
  3. Secure Cryptographic Storage — if you encrypt a message with a public key, only the private key can decrypt it. This is incredibly useful for storing your customers' credit card data, assuming you can safely transport it onto an airgapped computer for decrypting it for the purpose of recurring charges.

Why Choose Libsodium To Fill This Role?

  • Security. Libsodium is compatible with NaCl for all of its elliptic curve cryptographic operations (Curve25519, etc.). For more on why this is a security advantage over, e.g. NIST's P256, check out this page on the security of elliptic curve cryptography.
  • Platform Agnosticism. The Sodium PECL extension interacts with a library called libsodium, which is also available in most popular programming languages.
  • Ease of use. As I will demonstrate, Sodium takes care of most of the security considerations and then gets out of your way.

Setup Instructions

Once Sodium is available in PECL, installing it will be a breeze:

  1. Install PECL
  2. Install Sodium
  3. Enable Sodium
  4. Restart Apache/PHP-FPM

1. Installing PECL

The exact instructions you need to follow for this step will vary depending on your operating system, but if you're using a Debian-based flavor of GNU/Linux, then the command you want is as follows:

sudo apt-get install php5-dev

2. Installing Sodium

Once you can build PHP extensions from PECL onto your local machine, the next step is to build Sodium and install it as a PHP extension.

Warning: Sodium is still in the Beta channel. Soon it should be ready for general purpose.

sudo pecl install libsodium

3. Enabling the Sodium PHP Extension

Now that Sodium in installed, you just have to enable it. This should be done for you already (since the PECL installer asks if you want to enable support), but just in case it isn't, these two commands will take care of that.

sudo echo "extension=libsodium.so" >> /etc/php5/mods-available/libsodium.ini
sudo php5enmod libsodium

4. Restart PHP

Depending on your development stack, this may mean restarting Apache, restarting PHP-FPM, etc.

sudo service apache2 restart
# OR 
sudo service php5-fpm restart

How to Use Sodium

Digital Signatures

The first step is to generate a key pair, like so:

$my_keypair = Sodium::crypto_sign_keypair();

// Keep this private!
$signing_key = Sodium::crypto_sign_secretkey($my_keypair);

// This should be given out to everyone.
$publickey = Sodium::crypto_sign_publickey($my_keypair);

Next, we'll use $signing_key to sign a message.

$msg = "This is something important that must not be tampered with!";

$signed_msg = Sodium::crypto_sign($msg, $signing_key);

The recipient, whom should have $publickey on hand, can then verify the message as follows:

$msg_orig = Sodium::crypto_sign_open($signed_msg, $publickey);
if ($msg_orig === false) {
    die("Invalid signature.");
} else {
    // We can trust $msg_orig came from someone who possesses $signing_key
}

Take note of the nomenclature: To sign a message, you use Sodium::crypto_sign(), and to verify a message, you use Sodium::crypto_sign_open(). This convention is consistent throughout Sodium.

Public Key Authenticated Encryption (Made Easy!)

Most PHP developers don't understand the difference between encryption and authentication.

While it's possible to achieve a relatively solid authenticated encryption system with an Encrypt-Then-MAC construct using AES-CBC or AES-CTR with an unpredictably random IV, most developers (including framework designers) get it wrong. Extrapolating such a system to work with public key cryptography is a tall order for most developers.

Fortunately, Sodium makes all the difficult decisions for you. Just use Sodium::crypto_box() and Sodium::crypto_box_open().

Example time! First, we need to generate keys:

$alice_kp = Sodium::crypto_box_keypair(); // Do not share
$alice_secretkey = Sodium::crypto_box_secretkey($alice_kp); // Do not share
$alice_publickey = Sodium::crypto_box_publickey($alice_kp); // SHARE THIS ONE

$bob_kp = Sodium::crypto_box_keypair(); // Do not share
$bob_secretkey = Sodium::crypto_box_secretkey($bob_kp); // Do not share
$bob_publickey = Sodium::crypto_box_publickey($bob_kp); // SHARE THIS ONE

Now let's send a message from Alice to Bob. On Alice's machine, the following code will be run:

// Derive a shared secret from my private key and the other person's public key:
$alice_to_bob_kp = Sodium::crypto_box_keypair_from_secretkey_and_publickey
  ($alice_secretkey, $bob_publickey);

// Let's generate a random nonce for this message:
$alice_to_bob_message_nonce = Sodium::randombytes_buf(Sodium::CRYPTO_BOX_NONCEBYTES);

// This is the message we actually send:
$alice_to_bob_ciphertext = Sodium::crypto_box(
    'Hi, this is Alice',
    $alice_to_bob_message_nonce,
    $alice_to_bob_kp
);

The code necessary for Bob to read Alice's message is as follows:

// Derive a shared secret from my private key and the other person's public key:
$bob_to_alice_kp = Sodium::crypto_box_keypair_from_secretkey_and_publickey
  ($bob_secretkey, $alice_publickey);
// Notice that the keys are switched? That's the magic of Diffie Hellman and its Curve25519 descendant.

$alice_message_decrypted_by_bob = Sodium::crypto_box_open(
    $alice_to_bob_ciphertext,
    $alice_to_bob_message_nonce,
    $bob_to_alice_kp
);

Since Bob already has the shared secret derived, the code to generate his response is more succinct.

$bob_to_alice_message_nonce = Sodium::randombytes_buf(Sodium::CRYPTO_BOX_NONCEBYTES);

$bob_to_alice_ciphertext = Sodium::crypto_box(
    'Hi Alice! This is Bob',
    $bob_to_alice_message_nonce,
    $bob_to_alice_kp
);

And thus, for Alice to decrypt Bob's response, the code is merely:

$bob_message_decrypted_by_alice = Sodium::crypto_box_open(
    $bob_to_alice_ciphertext,
    $bob_to_alice_message_nonce,
    $alice_to_bob_kp
);

IMPORATANT: Take care to generate a new nonce for each message.

Secure Cryptographic Storage

This entire section has been obsoleted by crypto_box_seal() and crypto_box_seal_open().

But Wait, There's More!

Sodium also comes with a lot of cool utilities. Sodium::sodium_memzero() was demonstrated previously, but it also contains an interface for password hashing, key derivation, constant-time string comparison, and much more.

The documentation covers all of the features not mentioned on this page.

In closing, Sodium is a swiss army knife of security features with a much smaller learning curve.

Update (2015-01-18) - build script to quickly jump into beta-testing the PECL extension.

Blog Archives Categories Latest Comments