SIV-like deterministic nonce-misuse resistant authenticated encryption construction with BLAKE2s and ChaCha20
- key - 32-byte secret key
- nonce - 8-byte nonce (all-zero by default)
- plaintext - data to encrypt and authenticate
-
Calculate mac:
mac = BLAKE2s { personalization: "SB2C-mac" key: key salt: nonce digestLength: 32 data: plaintext }
-
Derive encryption key from mac and key:
encKey = BLAKE2s { personalization: "SB2C-enc" key: key digestLength: 32 data: mac }
-
Encrypt plaintext with encKey:
ciphertext = ChaCha20-XOR { key: encKey nonce: nonce data: plaintext }
-
Output mac concatenated with ciphertext:
sealed = mac || ciphertext
- key - 32-byte secret key
- nonce - 8-byte nonce
- sealed - sealed data to decrypt and authenticate
-
Extract first 32 bytes as mac and the rest as ciphertext:
mac || ciphertext = sealed
-
Derive encryption key from mac and key:
encKey = BLAKE2s { personalization: "SB2C-enc" key: key digestLength: 32 data: mac }
-
Decrypt plaintext with encKey:
plaintext = ChaCha20-XOR { key: encKey nonce: nonce data: ciphertext }
-
Calculate correctMac:
correctMac = BLAKE2s { personalization: "SB2C-mac" key: key salt: nonce digestLength: 32 data: plaintext }
-
Compare mac and correctMac using a constant-time comparison function, and return error if they are not equal.
-
Return plaintext.
TBD (basically, encode properly padded [e.g. also encoding length] AD along with plaintext in mac, use different personalization strings for everything.)
The original SIV uses CMAC to generate synthetic IV — which is a MAC of plaintext — and CTR for encryption. CMAC and CTR use two different keys, or rather, double key size, one half of which is used for CMAC, another half for CTR. If the CMAC half of key repeats, but the CTR half not, for the same message, it will result in the same MAC tag/synthetic IV, but different ciphertexts.
Unlike the original SIV, this algorithm uses a single 32-byte key. Because different personalization strings are used for BLAKE2s to derive synthetic IV/MAC and encryption key, initial keyed BLAKE2s states differ, so it is pretty much equivalent to having two different keys derived from one 32-byte key using HKDF or similar construction.
The original SIV uses synthetic IV (with two bits cleared) as IV/nonce (initial full counter) for CTR mode. This algorithm instead derives a new encryption key from synthetic IV and secret key. This is similar to how XSalsa20 construction works.
In the original SIV, nonce is added the same way any associated data is added — it is fed to CMAC. This algorithm uses nonce both in synthetic IV calculation (as BLAKE2s salt) and ChaCha20 encryption. The nonce length is thus limited to 8 bytes, however, like in the original SIV, any nonce-like input (counter, difference in messages, randomness, etc.) in plaintext and associated data (in TBD variant with associated data) also serves as a kind of a nonce. As with SIV, repeating nonce is fine: only message equivalence will be revealed if the same nonce is used for the same message.