ChaCha20 is high speed stream cipher, a vairant of Salsa20, usually combine with Poly1305 as AEAD construction.


ChaCha20-Poly13051 requires very similar inputs to AES:

  • a 32 bytes (256-bit) key, can derive key from password with a secure KDF
  • a 12 bytes (96-bit) nonce aka IV

There are more steps to encrypt a message due to it is stream cipher aka state cipher, which is different from block cipher such as AES, block cipher generate fixed length key to encrypt fixed length message, while stream cipher can produce state to generate keystream for next chunk of data.

  • AEAD need to add and finalize before encrypt, and cannot modify later on
  • encrypt can call multiple times based on current state
  • finalise a state will generate auth tag
ghci> import Crypto.Error
ghci> import Crypto.Cipher.ChaChaPoly1305
ghci| do
ghci| key <- getRandomBytes 32 :: IO ByteString
ghci| nonce <- getRandomBytes 12 :: IO ByteString
ghci| throwCryptoErrorIO $ do
ghci| st1 <- nonce12 nonce >>= initialize key
ghci| let
ghci|   st2 = finalizeAAD $ appendAAD ("context":: ByteString) st1
ghci|   (out, st3) = encrypt ("message":: ByteString) st2
ghci|   auth = finalize st3
ghci| return $ (convertToBase Base16 out :: ByteString, convertToBase Base16 auth :: ByteString)