Field-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:

This document describes the internals in-depth. Understanding the Key Hierarchy document may help to understand this document.

Backend Components

  1. Header (string constant)
  2. 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

An informal security analysis is described in the Security page.

FIPSCrypto Encryption Protocol

  1. Generate a 256-bit HKDF salt via random_bytes().
  2. Generate a 128-bit CTR nonce via random_bytes().
    • (Steps 1 and 2 act as an extended nonce).
  3. Split the provided key into an encryption key and an authentication key, using HKDF and the randomly generated salt in step 1.
    1. For the encryption key, set the info to AES-256-CTR.
    2. For the authentication key, set the info to HMAC-SHA-384.
  4. Encrypt the message, using AES-256-CTR with the encryption key and CTR nonce.
  5. Authenticate a packed payload using HMAC-SHA-384, which consists of (in order):
    1. The header for FIPSCrypto (fips:).
    2. The HKDF salt (step 1).
    3. The CTR nonce (step 2).
    4. The ciphertext (step 4).
  6. Return the header followed by the base64url encoded payload, consisting of (in order):
    1. The HKDF salt.
    2. The CTR nonce.
    3. The HMAC authentication tag.
    4. The ciphertext.

FIPSCrypto Decryption Protocol

  1. 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.
  2. 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.
  3. Decode the remaining base64url-encoded bytes of the ciphertext message, then break it into its constituent parts:
    1. The first 32 bytes represent the HKDF salt.
    2. The next 16 bytes represent the CTR nonce.
    3. The next 48 bytes represent the HMAC authentication tag.
    4. The remaining bytes represent the AES-encrypted ciphertext.
  4. Split the provided key into an encryption key and an authentication key, using HKDF and the randomly generated salt in step 1.
    1. For the encryption key, set the info to AES-256-CTR.
    2. For the authentication key, set the info to HMAC-SHA-384.
  5. Recalculate the HMAC-SHA-384 tag of the packed payload consisting of (in order):
    1. The header for FIPSCrypto (fips:).
    2. The HKDF salt.
    3. The CTR nonce.
    4. The ciphertext.
  6. Compare the given authentication tag with the recalculated authentication tag, using hash_equals(). If it does not match, throw an exception.
  7. Decrypt the ciphertext, using AES-256-CTR with the encryption key and CTR nonce.
  8. Return the decrypted plaintext.

ModernCrypto

Header: nacl:

ModernCrypto provides a secure extended-nonce AEAD interface using libsodium.

ModernCrypto Algorithms

An informal security analysis is described in the Security page.

ModernCrypto Encryption Protocol

  1. Generate a 192-bit nonce via random_bytes().
  2. 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).
  3. Return the header followed by the base64url encoded payload, consisting of (in order):
    1. The nonce (step 1).
    2. The ciphertext (step 2).

ModernCrypto Decryption Protocol

  1. 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.
  2. 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.
  3. Decode the remaining base64url-encoded bytes of the ciphertext message, then break it into its constituent parts:
    1. The first 24 bytes represent the nonce.
    2. The remaining bytes represent the ciphertext.
  4. 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.
  5. Return the decrypted plaintext.