Using Libsodium in PHP Projects

A guide to using the libsodium PHP extension for modern, secure, and fast cryptography. Open Source.

Basic Public-key Cryptography

Unlike secret-key cryptography, where both participants possess the same exact secret key, public-key cryptography allows you to generate a key-pair (one secret key and a related public key). You can freely share your public key, but your secret key must never be shared.

Before you decide whether or not to use a feature, check the quick reference page, which explains what each function does and where each should be used.

To view the old API documentation, click here.

In order to communicate with another entity, you must have their public key and your own secret key.

Thus, before you can begin working with public key cryptography, each participant must generate a keypair.

// On Alice's computer:

$alice_box_kp = sodium_crypto_box_keypair();
$alice_sign_kp = sodium_crypto_sign_keypair();

    // Split the key for the crypto_box API for ease of use
    $alice_box_secretkey = sodium_crypto_box_secretkey($alice_box_kp);
    $alice_box_publickey = sodium_crypto_box_publickey($alice_box_kp);
    
    // Split the key for the crypto_sign API for ease of use
    $alice_sign_secretkey = sodium_crypto_sign_secretkey($alice_sign_kp);
    $alice_sign_publickey = sodium_crypto_sign_publickey($alice_sign_kp);

// On Bob's computer:

$bob_box_kp = sodium_crypto_box_keypair();
$bob_sign_kp = sodium_crypto_sign_keypair();

    // Split the key for the crypto_box API for ease of use
    $bob_box_secretkey = sodium_crypto_box_secretkey($bob_box_kp);
    $bob_box_publickey = sodium_crypto_box_publickey($bob_box_kp);
    
    // Split the key for the crypto_sign API for ease of use
    $bob_sign_secretkey = sodium_crypto_sign_secretkey($bob_sign_kp);
    $bob_sign_publickey = sodium_crypto_sign_publickey($bob_sign_kp);

// Optionally, you can reassemble a keypair string from a secret key and 
// public key pair:

$keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey(
    $alice_box_secretkey,
    $alice_box_publickey
);

In the examples below, you are Alice and you are trying to talk to Bob.

Public-key Authenticated Encryption

If you have your own secret key and possess your recipient's public key, and they have your public key, you can easily facilitate authenticated encryption by taking advantage of the Box API. This consists of two functions:

  • sodium_crypto_box
  • sodium_crypto_box_open

Each message sent requires a nonce (a unique large number represented as a binary string that should only be used once).

Sending a boxed message (crypto_box)

string crypto_box(string $message, string $nonce, string $message_keypair);

// On Alice's computer:
$message = 'Hi, this is Alice';
$alice_to_bob_kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
    $alice_box_secretkey,
    $bob_box_publickey
);
$message_nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES);
$ciphertext = sodium_crypto_box(
    $message,
    $nonce,
    $alice_to_bob_kp
);

Opening a boxed message (crypto_box_open)

string|bool crypto_box_open(string $message, string $nonce, string $message_keypair);

// On Bob's computer:
$bob_to_alice_kp = sodium_crypto_box_keypair_from_secretkey_and_publickey(
    $bob_box_secretkey,
    $alice_box_publickey
);
$plaintext = sodium_crypto_box_open(
    $ciphertext,
    $nonce,
    $bob_to_alice_kp
);
if ($plaintext === false) {
    throw new Exception("Malformed message or invalid MAC");
}

Generating a crypto_box Key-pair from a Seed

string sodium_crypto_box_seed_keypair(string $seed);

To deterministically generate a keypair from a random string (or from the output of a key-derivation function), you can use crypto_box_seed_keypair.

$bob_seed = random_bytes(SODIUM_CRYPTO_BOX_SEEDBYTES);
$bob_encrypt_kp = sodium_crypto_box_seed_keypair($bob_seed);

Public-key Signatures

Public-key signatures are incredibly useful. If you can verify that you have the correct public key, you can verify the authenticity of a message (e.g. a software update) with near-absolute certainty.

Note that the crypto_sign API does not encrypt messages, it merely authenticates their contents such that anyone with your public key can verify that it came from you (or someone in possession of the correct secret key).

You can use the crypto_sign API in two modes: combined (default) or detached.

Signing a message

string sodium_crypto_sign(string $message, string $secretkey)

This returns the message and the signature all in one string.

// On Alice's computer:
$message = 'This comes from Alice.';
$signed_msg = sodium_crypto_sign(
    $message,
    $alice_sign_secretkey
);

Verifying a message

string|bool sodium_crypto_sign_open(string $message, string $publickey)

Given a signed message, this will either return FALSE or the contents of the message.

// On Bob's computer:
$original_msg = sodium_crypto_sign_open(
    $signed_msg,
    $alice_sign_publickey
);
if ($original_msg === false) {
    throw new Exception("Invalid signature");
} else {
    echo $original_msg; // Displays "This comes from Alice."
}

Detached message signing

string sodium_crypto_sign_detached(string $message, string $secretkey)

Instead of returning a signed message, this function only returns the signature.

// On Alice's computer:
$signature = sodium_crypto_sign_detached(
    $message,
    $alice_sign_secretkey
);

Detached signature verification

bool sodium_crypto_sign_verify_detached(string $signature, string $message, string $publickey)

// On Bob's computer:
if (sodium_crypto_sign_verify_detached(
        $signature,
        $message,
        $alice_sign_publickey
    )
) {
    // We've verified the authenticity of message and already had its contents
    // stored in $message
} else {
    throw new Exception("Invalid signature");
}

Generating a crypto_sign Key-pair from a Seed

string sodium_crypto_sign_seed_keypair(string $seed);

To deterministically generate a keypair from a random string (or from the output of a key-derivation function), you can use crypto_sign_seed_keypair.

$bob_seed = random_bytes(SODIUM_CRYPTO_SIGN_SEEDBYTES);
$bob_sign_kp = sodium_crypto_sign_seed_keypair($bob_seed);

Extra Information