CipherSweet
Cross-platform, searchable field-level database encryptionField-Level Encryption
CipherSweet uses authenticated symmetric-key encryption with random initialization vectors (IVs, also called a nonce: a number to be used once).
Encryption is abstracted into something we call a backend, which defines a rigid ciphersuite of known-secure primitives. As of this release, CipherSweet provides two backends:
-
FIPSCrypto
uses the OpenSSL and Hash extensions built into PHP. -
ModernCrypto
uses libsodium, a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more.
This document describes the internals in-depth. Understanding the Key Hierarchy document may help to understand this document.
Backend Components
- Header (string constant)
- Payload (Authenticated encryption, base64url encoded)
FIPSCrypto
Header: fips:
FIPSCrypto provides a secure extended-nonce AEAD interface using only the cryptographic algorithms recommended by FIPS 140-2 (and other FIPS supplementary documents).
You'll want to use FIPSCrypto if you're aspiring to use CipherSweet in a FIPS certified web application, or if you cannot install libsodium.
FIPSCrypto Algorithms
- Encryption is facilitated by AES-256 in Counter mode (CTR).
- Ciphertexts are authenticated with HMAC-SHA384 (Encrypt-then-MAC).
- IVs/nonces are generated by
random_bytes()
(the kernel's CSPRNG). - Key separation uses HKDF-HMAC-SHA384.
An informal security analysis is described in the Security page.
FIPSCrypto Encryption Protocol
- Generate a 256-bit HKDF salt via
random_bytes()
. - Generate a 128-bit CTR nonce via
random_bytes()
.- (Steps 1 and 2 act as an extended nonce).
- Split the provided key into an encryption key and an authentication
key, using HKDF and the randomly generated salt in step 1.
- For the encryption key, set the
info
toAES-256-CTR
. - For the authentication key, set the
info
toHMAC-SHA-384
.
- For the encryption key, set the
- Encrypt the message, using AES-256-CTR with the encryption key and CTR nonce.
- Authenticate a packed payload using HMAC-SHA-384,
which consists of (in order):
- The header for FIPSCrypto (
fips:
). - The HKDF salt (step 1).
- The CTR nonce (step 2).
- The ciphertext (step 4).
- The header for FIPSCrypto (
- Return the header followed by the base64url encoded payload,
consisting of (in order):
- The HKDF salt.
- The CTR nonce.
- The HMAC authentication tag.
- The ciphertext.
FIPSCrypto Decryption Protocol
- Verify that the first 5 bytes of the ciphertext message matches the
header for the FIPSCrypto backend (i.e.
fips:
), in constant-time; otherwise throw an exception. - If the decoded message (step 1) is too short, throw an exception.
- Too short: Less than 96 bytes, which is the sum of the HKDF salt size, CTR nonce size, and HMAC-SHA-384 output length.
- Decode the remaining base64url-encoded bytes of the ciphertext
message, then break it into its constituent parts:
- The first 32 bytes represent the HKDF salt.
- The next 16 bytes represent the CTR nonce.
- The next 48 bytes represent the HMAC authentication tag.
- The remaining bytes represent the AES-encrypted ciphertext.
- Split the provided key into an encryption key and an authentication
key, using HKDF and the randomly generated salt in step 1.
- For the encryption key, set the
info
toAES-256-CTR
. - For the authentication key, set the
info
toHMAC-SHA-384
.
- For the encryption key, set the
- Recalculate the HMAC-SHA-384 tag of the packed
payload consisting of (in order):
- The header for FIPSCrypto (
fips:
). - The HKDF salt.
- The CTR nonce.
- The ciphertext.
- The header for FIPSCrypto (
- Compare the given authentication tag with the recalculated
authentication tag, using
hash_equals()
. If it does not match, throw an exception. - Decrypt the ciphertext, using AES-256-CTR with the encryption key and CTR nonce.
- Return the decrypted plaintext.
ModernCrypto
Header: nacl:
ModernCrypto provides a secure extended-nonce AEAD interface using libsodium.
ModernCrypto Algorithms
- AEAD (Authenticated Encryption with Associated Data) is facilitated by XChaCha20 (eXtended-nonce ChaCha20 with a Poly1305 authentication tag).
- IVs/nonces are generated by
random_bytes()
(the kernel's CSPRNG).
An informal security analysis is described in the Security page.
ModernCrypto Encryption Protocol
- Generate a 192-bit nonce via
random_bytes()
. - Use
crypto_aead_xchacha20poly1305_ietf_encrypt()
from libsodium to encrypt the message with both the nonce AND additional data set to the randomly generated nonce (step 1). - Return the header followed by the base64url encoded payload,
consisting of (in order):
- The nonce (step 1).
- The ciphertext (step 2).
ModernCrypto Decryption Protocol
- Verify that the first 5 bytes of the ciphertext message matches the
header for the ModernCrypto backend (i.e.
nacl:
), in constant-time; otherwise throw an exception. - If the decoded message (step 1) is too short, throw an exception.
- Too short: Less than 40 bytes, which is the sum of the nonce size and Poly1305 authentication tag length.
- Decode the remaining base64url-encoded bytes of the ciphertext
message, then break it into its constituent parts:
- The first 24 bytes represent the nonce.
- The remaining bytes represent the ciphertext.
- Use
crypto_aead_xchacha20poly1305_ietf_decrypt()
from libsodium to encrypt the message with both the nonce AND additional data set to the nonce. If unsuccessful, throw an exception. - Return the decrypted plaintext.