On this page:
cipher-spec?
cipher-impl?
get-cipher
cipher-block-size
cipher-default-key-size
cipher-key-sizes
cipher-iv-size
cipher-aead?
cipher-default-auth-size
generate-cipher-key
generate-cipher-iv
4.1 High-level Cipher Operations
encrypt
decrypt
encrypt/  auth
decrypt/  auth
4.2 Low-level Cipher Operations
make-encrypt-ctx
make-decrypt-ctx
cipher-ctx?
encrypt-ctx?
decrypt-ctx?
cipher-update
cipher-update-aad
cipher-final
cipher-get-auth-tag

4 Symmetric Encryption

A cipher (or symmetric-key encryption algorithm) is a reversable function from variable-length messages to messages. The input is called the “plaintext” and the output is called the “ciphertext.” For a good cipher, the ciphertext reveals no information about the contents of the plaintext (only its length or approximate length); in particular, it is infeasible to compute the plaintext corresponding to a given ciphertext without knowing the secret key.

Ciphers are organized into families that share common encryption and decryption algorithms but differ in parameters such as key length and block mode. For example, the AES family supports key lengths of 128, 192, and 256 bits, and it supports a wide range of modes, including ECB, CBC, and CTR.

This library provides both high-level, all-at-once encryption and decryption operations and low-level, incremental operations.

procedure

(cipher-spec? v)  boolean?

  v : any/c
Returns #t if v represents a cipher specifier, #f otherwise.

A cipher specifier is one of the following:
  • (list stream-cipher 'stream)where stream-cipher is one of the following symbols: 'chacha20, 'chacha20-poly1305, 'chacha20-poly1305/iv8, 'rc4, 'salsa20, 'salsa20r12, 'salsa20r8, 'xchacha20-poly1305.

  • (list block-cipher block-mode)where block-cipher is one of the following symbols: 'aes, 'blowfish, 'camellia, 'cast128, 'des, 'des-ede2, 'des-ede3, 'idea, 'serpent, 'twofish, and block-mode is one of the following symbols: 'ecb, 'cbc, 'ofb, 'cfb, 'ctr, 'gcm, 'ocb, 'eax.

Note that the key length is not considered part of the cipher specifier; it is determined implicitly from the key provided to encrypt, make-encrypt-ctx, etc.

The CCM block mode is not supported because of its burdensome requirements: it requires the message and AAD lengths to be known in advance.

Future versions of this library may add more ciphers to the lists above and other forms of cipher specifiers.

procedure

(cipher-impl? v)  boolean?

  v : any/c
Returns #t if v represents a cipher implementation, #f otherwise.

procedure

(get-cipher ci [factories])  (or/c cipher-impl? #f)

  ci : cipher-spec?
  factories : (or/c crypto-factory? (listof crypto-factory?))
   = (crypto-factories)
Returns an implementation of cipher ci from the given factories. If no factory in factories implements ci, returns #f.

Returns the size in bytes of the blocks manipulated by the cipher. If ci is a stream cipher (including block ciphers using a stream mode such as CTR), returns 1.

A cipher produces a ciphertext that is a multiple of its block size. If a cipher is used without padding, the plaintext must be a multiple of the block size.

Examples:
> (cipher-block-size '(aes cbc))

16

> (cipher-block-size '(aes ctr))

1

> (cipher-block-size '(salsa20 stream))

1

Returns a default size in bytes of the secret keys used by the cipher.

Examples:
> (cipher-default-key-size '(aes cbc))

16

> (cipher-default-key-size '(chacha20 stream))

32

Returns the possible sizes in bytes of the secret keys used by the cipher.

Examples:
> (cipher-key-sizes '(aes cbc))

'(16 24 32)

> (cipher-key-sizes '(chacha20 stream))

'(32)

Returns the size in bytes of the initialization vector (IV) used by the cipher. Returns 0 if the cipher does not use an IV.

This library uses a broad interpretation of the term “IV”. For example, if ci is a block cipher in CTR mode, this function returns the size of the counter.

Examples:
> (cipher-iv-size '(aes cbc))

16

> (cipher-iv-size '(aes ctr))

16

> (cipher-iv-size '(aes gcm))

12

> (cipher-iv-size '(aes ecb))

0

> (cipher-iv-size '(chacha20-poly1305 stream))

12

> (cipher-iv-size '(chacha20-poly1305/iv8 stream))

8

procedure

(cipher-aead? ci)  boolean?

  ci : (or/c cipher-spec? cipher-impl? cipher-ctx?)
Returns #t if ci is an authenticated encryption cipher, #f otherwise. See encrypt for more details.

An authenticated encryption cipher (with additionally authenticated data, AEAD) produces an authentication tag in addition to the ciphertext. An AEAD cipher provides both confidentiality and integrity, whereas a non-AEAD cipher only provides confidentiality.

Examples:
> (cipher-aead? '(aes ctr))

#f

> (cipher-aead? '(aes gcm))

#t

> (cipher-aead? '(chacha20-poly1305 stream))

#t

Returns the default size in bytes of the authentication tag produced by ci if it represents an authenticated encryption or decryption algorithm; 0 otherwise.

Examples:
> (cipher-default-auth-size '(aes gcm))

16

> (cipher-default-auth-size '(aes ctr))

0

procedure

(generate-cipher-key ci [#:size size])  bytes?

  ci : (or/c cipher-spec? cipher-impl?)
  size : exact-positive-integer? = (cipher-default-key-size ci)

procedure

(generate-cipher-iv ci [#:size size])  bytes?

  ci : (or/c cipher-spec? cipher-impl?)
  size : exact-positive-integer? = (cipher-iv-size ci)
Generates a random secret key or initialization vector, respectively, appropriate for use with the cipher ci. Some ciphers have a set of weak keys; generate-cipher-key currently does not detect or avoid weak keys. If ci does not use an IV, generate-cipher-iv returns #f.

The random bytes are generated with crypto-random-bytes.

4.1 High-level Cipher Operations

procedure

(encrypt ci    
  key    
  iv    
  input    
  [#:aad additional-authenticated-data    
  #:auth-size auth-size    
  #:pad pad-mode])  bytes?
  ci : (or/c cipher-spec? cipher-impl?)
  key : bytes?
  iv : (or/c bytes? #f)
  input : input/c
  additional-authenticated-data : input/c = #""
  auth-size : exact-nonnegative-integer?
   = (cipher-default-auth-size ci)
  pad-mode : boolean? = #t

procedure

(decrypt ci    
  key    
  iv    
  input    
  [#:aad additional-authenticated-data    
  #:auth-size auth-size    
  #:pad pad-mode])  bytes?
  ci : (or/c cipher-spec? cipher-impl?)
  key : bytes?
  iv : (or/c bytes? #f)
  input : (or/c bytes? input-port?)
  additional-authenticated-data : input/c = #""
  auth-size : exact-nonnegative-integer?
   = (cipher-default-auth-size ci)
  pad-mode : boolean? = #t
Encrypt or decrypt, respectively, using the secret key, initialization vector iv, and padding mode pad-mode. See input/c for accepted values of input and additional-authenticated-data and the rules of their conversion to bytes.

If ci is a block cipher and if pad-mode is #t, then the input is padded using PKCS#7 padding during decryption, and the padding is checked and removed during decryption; otherwise if pad-mode is #f, then the input is not padded, and its length must by divisible by ci’s block size. If ci is a stream cipher (including block ciphers using a stream mode), pad is ignored and no padding is added. Future versions of this library may support additional kinds of padding.

If ci is an authenticated encryption (AEAD) cipher, the authentication tag it produces is attached to the ciphertext. That is, encrypt appends the authentication tag to the end of the ciphertext, and decrypt extracts the authentication tag from the end of the ciphertext. The auth-size argument controls the length of the authentication tag. If authenticated decryption fails, an exception is raised.

Examples:
> (define key (generate-cipher-key '(aes ctr)))
> (define iv (generate-cipher-iv '(aes ctr)))
> (define ciphertext (encrypt '(aes ctr) key iv "Hello world!"))
> ciphertext

#"\331 >\303\0\370\240Mf\177\345\204"

> (decrypt '(aes ctr) key iv ciphertext)

#"Hello world!"

procedure

(encrypt/auth ci 
  key 
  iv 
  input 
  [#:aad additional-authenticated-data 
  #:auth-size auth-size 
  #:pad pad-mode]) 
  
bytes? bytes?
  ci : (or/c cipher-spec? cipher-impl?)
  key : bytes?
  iv : (or/c bytes? #f)
  input : input/c
  additional-authenticated-data : input/c = #""
  auth-size : exact-nonnegative-integer?
   = (cipher-default-auth-size ci)
  pad-mode : boolean? = #t

procedure

(decrypt/auth ci    
  key    
  iv    
  input    
  [#:aad additional-authenticated-data    
  #:auth-tag auth-tag    
  #:pad pad-mode])  bytes?
  ci : (or/c cipher-spec? cipher-impl?)
  key : bytes?
  iv : (or/c bytes? #f)
  input : (or/c bytes? input-port?)
  additional-authenticated-data : input/c = #""
  auth-tag : bytes? = #""
  pad-mode : boolean? = #t
Like encrypt and decrypt, respectively, but the authentication tag is detached from the ciphertext. That is, encrypt/auth produces two values consisting of the ciphertext and authentication tag, and decrypt/auth takes the ciphertext and authentication tag as distinct arguments.

If ci is not an AEAD cipher, the authentication tag is always #"".

Examples:
> (define key (generate-cipher-key '(aes gcm)))
> (define iv (generate-cipher-iv '(aes gcm)))
> (define-values (ciphertext auth-tag)
    (encrypt/auth '(aes gcm) key iv "Hello world!" #:aad #"greeting"))
> (decrypt/auth '(aes gcm) key iv ciphertext #:aad #"greeting" #:auth-tag auth-tag)

#"Hello world!"

> (decrypt/auth '(aes gcm) key iv ciphertext #:aad #"INVALID" #:auth-tag auth-tag)

decrypt: authenticated decryption failed

4.2 Low-level Cipher Operations

procedure

(make-encrypt-ctx ci 
  key 
  iv 
  [#:auth-size auth-size 
  #:auth-attached? auth-attached? 
  #:pad pad-mode]) 
  encrypt-ctx?
  ci : (or/c cipher-spec? cipher-impl?)
  key : bytes?
  iv : (or/c bytes? #f)
  auth-size : exact-nonnegative-integer?
   = (cipher-default-auth-size ci)
  auth-attached? : boolean? = #t
  pad-mode : boolean? = #t

procedure

(make-decrypt-ctx ci 
  key 
  iv 
  [#:auth-size auth-size 
  #:auth-attached? auth-attached? 
  #:pad pad-mode]) 
  decrypt-ctx?
  ci : (or/c cipher-spec? cipher-impl?)
  key : bytes?
  iv : (or/c bytes? #f)
  auth-size : exact-nonnegative-integer?
   = (cipher-default-auth-size ci)
  auth-attached? : boolean? = #t
  pad-mode : boolean? = #t
Returns a new cipher context for encryption or decryption, respectively, using the given secret key, initialization vector iv, and padding mode pad-mode.

procedure

(cipher-ctx? v)  boolean?

  v : any/c
Returns #t if v is a cipher context, #f otherwise.

Equivalent to (or (encrypt-ctx? v) (decrypt-ctx? v)).

procedure

(encrypt-ctx? v)  boolean?

  v : any/c

procedure

(decrypt-ctx? v)  boolean?

  v : any/c
Returns #t if v is a cipher context for encryption or decryption, respectively; otherwise, returns #f.

procedure

(cipher-update cctx input)  bytes?

  cctx : cipher-ctx?
  input : input/c
Processes input with the cipher context cctx, returning the newly available encrypted or decrypted output. The output may be larger or smaller than the input, because incomplete blocks are internally buffered by cctx.

procedure

(cipher-update-aad cctx input)  void?

  cctx : cipher-ctx?
  input : input/c
Processes input as additional authenticated data to the cipher context cctx. Must be called before any calls to cipher-update.

If cctx is not a context for authenticated encryption or decryption, an exception is raised.

procedure

(cipher-final cctx [auth-tag])  bytes?

  cctx : cipher-ctx?
  auth-tag : (or/c bytes? #f) = #f
Processes any remaining input buffered by cctx, applies or checks and removes padding if appropriate, and returns the newly available output.

If cctx is an authenticated decryption context in detached mode (that is, created with #:auth-attached? #f), then auth-tag is checked against the decryption’s final authentication tag and an exception is raised if they do not match.

Otherwise—if the cctx is an encryption context, or a decryption context for a non-AEAD cipher, or a decryption context for an AEAD cipher in attached mode—auth-tag must be #f or else an exception is raised.

procedure

(cipher-get-auth-tag cctx)  bytes?

  cctx : cipher-ctx?
If cctx is an encryption context, retrieves the authentication code. For a non-AEAD cipher, the authentication code is always #"". If called before cipher-final, an exception is raised.