botan-low-0.0.1.0: Low-level Botan bindings
Copyright(c) Leo D 2023
LicenseBSD-3-Clause
Maintainerleo@apotheca.io
Stabilityexperimental
PortabilityPOSIX
Safe HaskellSafe-Inferred
LanguageHaskell2010

Botan.Low.Cipher

Description

A block cipher by itself, is only able to securely encrypt a single data block. To be able to securely encrypt data of arbitrary length, a mode of operation applies the block cipher’s single block operation repeatedly to encrypt an entire message.

Synopsis

Cipher

A cipher mode is a cryptographic algorithm suitable for encrypting and decrypting large quantities of arbitrarily-sized data. An aead is a cipher mode that also used to provide authentication of the ciphertext, potentially with plaintext `associated data`.

Usage

Unless you need a specific cipher or aead, it is strongly recommended that you use the `cbcMode AES256 PKCS7` and `gcmMode AES256` (or ChaCha20Poly1305) algorithms respectively.

import Botan.Low.Cipher
encrypter <- cipherInit ChaCha20Poly1305 Encrypt

To use a cipher, we first need to generate (if we haven't already) a secret key.

import Botan.Low.RNG
rng <- rngInit "user"
-- We will use the maximum key size; ChaCha20Poly1305 keys are always 32 bytes
(_,keySize,_) <- cipherGetKeyspec encrypter
-- Block cipher keys are randomly generated
key <- rngGet rng keySize

After the key is generated, we must set it as the cipher key:

cipherSetKey encrypter key

If the cipher is an aead, we may also set the `associated data`:

cipherSetAssociatedData encrypter "Fee fi fo fum!"

To ensure that the key is not leaked, we should generate a new nonce for every encryption. The range of allowed nonce sizes depends on the specific algorithm.

import Botan.Low.RNG
-- The default ChaCha20Poly1305 nonce is always 12 bytes.
nonceSize <- cipherGetDefaultNonceLength encrypter
nonce <- rngGet rng nonceSize

To encrypt a message, it must be a multiple of the block size. If the cipher was an aead, the authentication tag will automatically be included in the ciphertext

-- Rarely, some cipher modes require that the message size be aligned to the block size
-- Consult algorithm-specific documentation if this occurs. 
message = "I smell the blood of an Englishman!"
cipherStart encrypter nonce
ciphertext <- cipherEncrypt encrypter message

To decrypt a message, we run the same process with a decrypter, using the same key and nonce to decode the ciphertext:

decrypter <- cipherInit ChaCha20Poly1305 Decrypt
cipherSetKey decrypter key
cipherSetAssociatedData decrypter "Fee fi fo fum!"
cipherStart decrypter nonce
plaintext <- cipherDecrypt decrypter ciphertext
message == plaintext -- True

You can completely clear a cipher's state, leaving it ready for reuse:

cipherClear encrypter
-- You'll have to set the key, nonce, (and ad, if aead) again.
cipherSetKey encrypter anotherKey
cipherStart encrypter anotherNonce
cipherSetAssociatedData encrypter anotherAD
-- Process another message
anotherCiphertext <- cipherEncrypt encrypter anotherMessage

If you are encrypting or decrypting multiple messages with the same key, you can reset the cipher instead of clearing it, leaving the key set:

cipherClear encrypter
-- This is equivalent to calling cipherClear followed by cipherSetKey with the original key.
-- You'll have to set the nonce  (and ad, if aead) again, but not the key.
cipherStart encrypter anotherNonce
cipherSetAssociatedData encrypter anotherAD
-- Process another message with the same key
anotherCiphertext <- cipherEncrypt encrypter anotherMessage

newtype Cipher Source #

Constructors

MkCipher 

Fields

withCipher :: Cipher -> (BotanCipher -> IO a) -> IO a Source #

cipherInit Source #

Arguments

:: CipherName

name

-> CipherInitFlags

flags

-> IO Cipher

cipher

Initialize a cipher object

cipherDestroy :: Cipher -> IO () Source #

Destroy the cipher object immediately

cipherName Source #

Arguments

:: Cipher

cipher

-> IO CipherName

name

Return the name of the cipher object

cipherOutputLength Source #

Arguments

:: Cipher

cipher

-> Int

in_len

-> IO Int

out_len

Return the output length of this cipher, for a particular input length.

WARNING: This function is of limited use. From the C++ docs: /** * Returns the size of the output if this transform is used to process a * message with input_length bytes. In most cases the answer is precise. * If it is not possible to precise (namely for CBC decryption) instead an * upper bound is returned. */ We need to explicitly calculate padding + tag length

cipherValidNonceLength Source #

Arguments

:: Cipher

cipher

-> Int

nl

-> IO Bool 

Return if the specified nonce length is valid for this cipher NOTE: This just always seems to return True, even for -1 and maxBound

cipherGetTagLength Source #

Arguments

:: Cipher

cipher

-> IO Int

tag_size

Get the tag length of the cipher (0 for non-AEAD modes)

cipherGetDefaultNonceLength Source #

Arguments

:: Cipher

cipher

-> IO Int

nl

Get the default nonce length of this cipher

cipherGetUpdateGranularity Source #

Arguments

:: Cipher

cipher

-> IO Int

ug

Return the update granularity of the cipher; botan_cipher_update must be called with blocks of this size, except for the final.

cipherGetIdealUpdateGranularity Source #

Arguments

:: Cipher

cipher

-> IO Int

ug

Return the ideal update granularity of the cipher. This is some multiple of the update granularity, reflecting possibilities for optimization.

Some ciphers (ChaChaPoly, EAX) may consume less input than the reported ideal granularity

cipherQueryKeylen Source #

Arguments

:: Cipher

cipher

-> IO (Int, Int)

(min,max)

Deprecated: Prefer cipherGetKeyspec.

Get information about the key lengths.

cipherGetKeyspec Source #

Arguments

:: Cipher

cipher

-> IO (Int, Int, Int)

(min,max,mod)

Get information about the supported key lengths.

cipherSetKey Source #

Arguments

:: Cipher

cipher

-> ByteString

key

-> IO () 

Set the key for this cipher object

cipherReset Source #

Arguments

:: Cipher

cipher

-> IO () 

Reset the message specific state for this cipher. Without resetting the keys, this resets the nonce, and any state associated with any message bits that have been processed so far.

It is conceptually equivalent to calling botan_cipher_clear followed by botan_cipher_set_key with the original key.

cipherSetAssociatedData Source #

Arguments

:: Cipher

cipher

-> ByteString

ad

-> IO () 

Set the associated data. Will fail if cipher is not an AEAD

cipherStart Source #

Arguments

:: Cipher

cipher

-> ByteString

nonce

-> IO () 

Begin processing a new message using the provided nonce

cipherUpdate Source #

Arguments

:: Cipher

cipher

-> CipherUpdateFlags

flags

-> Int

output_size

-> ByteString

input_bytes[]

-> IO (Int, ByteString)

(input_consumed,output[])

"Encrypt some data"

This function is ill-documented.

See the source for authoritative details: https://github.com/randombit/botan/blob/72dc18bbf598f2c3bef81a4fb2915e9c3c524ac4/src/lib/ffi/ffi_cipher.cpp#L133

Some ciphers (ChaChaPoly, EAX) may consume less input than the reported ideal granularity

cipherEncrypt :: Cipher -> ByteString -> IO ByteString Source #

Encrypt and finalize a complete piece of data.

This is not a canonical Botan C/C++ function.

cipherDecrypt :: Cipher -> ByteString -> IO ByteString Source #

Encrypt and finalize a complete piece of data.

This is not a canonical Botan C/C++ function.

cipherClear :: Cipher -> IO () Source #

Reset the key, nonce, AD and all other state on this cipher object

Cipher modes

CBC padding

AEAD

AEAD modes

Convenience

cipherEncryptOnline :: Cipher -> ByteString -> IO ByteString Source #

Deprecated: Moving from botan-low to botan

cipherDecryptOnline :: Cipher -> ByteString -> IO ByteString Source #

Deprecated: Moving from botan-low to botan