PHP Classes

File: docs/internals/03-encryption.md

Recommend this page to a friend!
  Classes of Scott Arciszewski   Cipher Sweet   docs/internals/03-encryption.md   Download  
File: docs/internals/03-encryption.md
Role: Auxiliary data
Content type: text/markdown
Description: Auxiliary data
Class: Cipher Sweet
Encrypt data in away that can be searched
Author: By
Last change:
Date: 6 years ago
Size: 5,821 bytes
 

Contents

Class file image Download

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:

  • `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

  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

  • 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.

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

  • 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).

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. 4. 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.