php 47 lines · 7 steps

Authenticated field encryption with libsodium

A small PHP class that encrypts and decrypts strings with libsodium's secretbox, prepending a fresh nonce to each ciphertext.

Explained by highlit
1final class FieldEncryptor
2{
3 private string $key;
4 
5 public function __construct(string $base64Key)
6 {
7 $key = base64_decode($base64Key, true);
8 
9 if ($key === false || strlen($key) !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
10 throw new InvalidArgumentException('Encryption key must be 32 raw bytes, base64-encoded.');
11 }
12 
13 $this->key = $key;
14 }
15 
16 public function encrypt(string $plaintext): string
17 {
18 $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
19 $cipher = sodium_crypto_secretbox($plaintext, $nonce, $this->key);
20 
21 $payload = base64_encode($nonce . $cipher);
22 
23 sodium_memzero($plaintext);
24 
25 return $payload;
26 }
27 
28 public function decrypt(string $payload): string
29 {
30 $decoded = base64_decode($payload, true);
31 
32 if ($decoded === false || strlen($decoded) < SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + SODIUM_CRYPTO_SECRETBOX_MACBYTES) {
33 throw new RuntimeException('Malformed ciphertext payload.');
34 }
35 
36 $nonce = substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
37 $cipher = substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
38 
39 $plaintext = sodium_crypto_secretbox_open($cipher, $nonce, $this->key);
40 
41 if ($plaintext === false) {
42 throw new RuntimeException('Decryption failed: data was tampered with or the wrong key was used.');
43 }
44 
45 return $plaintext;
46 }
47}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Symmetric authenticated encryption needs a fresh random nonce per message, stored alongside the ciphertext.
  2. 2Validating key and payload length up front turns silent crypto failures into clear, early errors.
  3. 3A false return from secretbox_open means tampering or a wrong key — never treat decryption as infallible.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Authenticated field encryption with libsodium — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code