DownloadField-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.
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.
1. For the encryption key, set the `info` to `AES-256-CTR`.
2. For the authentication key, set the `info` to `HMAC-SHA-384`.
-
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):
1. The header for FIPSCrypto (`fips:`).
2. The HKDF salt (step 1).
3. The CTR nonce (step 2).
4. The ciphertext (step 4).
-
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
-
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:
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.
-
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`.
-
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.
-
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).
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):
1. The nonce (step 1).
2. 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:
1. The first 24 bytes represent the nonce.
4. 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.
|