package cryptokit

  1. Overview
  2. Docs

The Cryptokit library provides a variety of cryptographic primitives that can be used to implement cryptographic protocols in security-sensitive applications.

The primitives provided include:

  • Symmetric-key ciphers: AES, Chacha20, DES, Triple-DES, Blowfish, ARCfour, in ECB, CBC, CFB, OFB and counter modes.
  • Authenticated encryption: AES-GCM, Chacha20-Poly1305
  • Public-key cryptography: RSA encryption, Diffie-Hellman key agreement.
  • Hash functions and MACs: SHA-3, SHA-2, BLAKE2, RIPEMD-160, and MACs based on AES, DES, and SipHash.
  • Random number generation.
  • Encodings and compression: base 64, hexadecimal, Zlib compression.

General-purpose abstract interfaces

class type transform = object ... end

A transform is an arbitrary mapping from sequences of characters to sequences of characters. Examples of transforms include ciphering, deciphering, compression, decompression, and encoding of binary data as text. Input data to a transform is provided by successive calls to the methods put_substring, put_string, put_char or put_byte. The result of transforming the input data is buffered internally, and can be obtained via the get_string, get_substring, get_char and get_byte methods.

val transform_string : transform -> string -> string

transform_string t s runs the string s through the transform t and returns the transformed string. The transform t is wiped before returning, hence can no longer be used for further transformations.

val transform_channel : transform -> ?len:int -> in_channel -> out_channel -> unit

transform_channel t ic oc reads characters from input channel ic, runs them through the transform t, and writes the transformed data to the output channel oc. If the optional len argument is provided, exactly len characters are read from ic and transformed; End_of_file is raised if ic does not contain at least len characters. If len is not provided, ic is read all the way to end of file. The transform t is wiped before returning, hence can no longer be used for further transformations.

val compose : transform -> transform -> transform

Compose two transforms, feeding the output of the first transform to the input of the second transform.

class type hash = object ... end

A hash is a function that maps arbitrarily-long character sequences to small, fixed-size strings.

val hash_string : hash -> string -> string

hash_string h s runs the string s through the hash function h and returns the hash value of s. The hash h is wiped before returning, hence can no longer be used for further hash computations.

val hash_channel : hash -> ?len:int -> in_channel -> string

hash_channel h ic reads characters from the input channel ic, computes their hash value and returns it. If the optional len argument is provided, exactly len characters are read from ic and hashed; End_of_file is raised if ic does not contain at least len characters. If len is not provided, ic is read all the way to end of file. The hash h is wiped before returning, hence can no longer be used for further hash computations.

An authenticated transform maps sequences of bytes to sequences of bytes, just like a transform, but also builds a message authentication tag for the transformed data. The tag is returned by the finish method. Authenticated transforms are used for authenticated encryption and decryption.

class type authenticated_transform = object ... end
val auth_transform_string : authenticated_transform -> string -> string

auth_transform_string t s runs the string s through the authenticated transform t and returns the concatenation of the transformed string and its authentication tag. The transform t is wiped before returning, hence can no longer be used for further transformations.

val auth_check_transform_string : authenticated_transform -> string -> string option

auth_check_transform_string t s splits the string s into an input string s1 and an expected authentication tag a. It runs s1 through the authenticated transform t and checks that the authentication tag is the expected tag a. If so, the transformed string is returned. If not, None is returned. The input string s must have length greater than or equal to t#tag_size. Otherwise, the Wrong_data_length exception is raised. The transform t is wiped before returning, hence can no longer be used for further transformations.

val auth_transform_string_detached : authenticated_transform -> string -> string * string

auth_transform_string_detached t s runs the string s through the authenticated transform t and returns a pair of the transformed string and its authentication tag. The transform t is wiped before returning, hence can no longer be used for further transformations.

val transform_then_hash : transform -> hash -> authenticated_transform

Build an authenticated transform from a transform t and a hash h. Input data is run through t, producing transformed data. The transformed data is hashed using h. The authentication tag is the final hash value.

val transform_and_hash : transform -> hash -> authenticated_transform

Build an authenticated transform from a transform t and a hash h. Input data is run through t, producing transformed data. In parallel, the input data is hashed using h. The authentication tag is the final hash value.

Utilities: random numbers and padding schemes

module Random : sig ... end

The Random module provides random and pseudo-random number generators suitable for generating cryptographic keys, nonces, or challenges.

module Padding : sig ... end

The Padding module defines a generic interface for padding input data to an integral number of blocks, as well as two popular padding schemes.

Cryptographic primitives (simplified interface)

module Cipher : sig ... end

The Cipher module implements the AES, DES, Triple-DES, ARCfour and Blowfish symmetric ciphers. Symmetric ciphers are presented as transforms parameterized by a secret key and a "direction" indicating whether encryption or decryption is to be performed. The same secret key is used for encryption and for decryption.

module AEAD : sig ... end

The AEAD module implements authenticated encryption with associated data. This provides the same confidentiality guarantees as plain encryption, but also provides integrity guarantees. This module implements the AES-GCM and Chacha20-Poly1305 algorithms.

module Hash : sig ... end

The Hash module implements unkeyed cryptographic hashes (SHA-1, SHA-256, SHA-512, SHA-3, RIPEMD-160 and MD5), also known as message digest functions. Hash functions used in cryptography are characterized as being one-way (given a hash value, it is computationally infeasible to find a text that hashes to this value) and collision-resistant (it is computationally infeasible to find two different texts that hash to the same value). Thus, the hash of a text can be used as a compact replacement for this text for the purposes of ensuring integrity of the text.

module MAC : sig ... end

The MAC module implements message authentication codes, also known as keyed hash functions. These are hash functions parameterized by a secret key. In addition to being one-way and collision-resistant, a MAC has the property that without knowing the secret key, it is computationally infeasible to find the hash for a known text, even if many pairs of (text, MAC) are known to the attacker. Thus, MAC can be used to authenticate the sender of a text: the receiver of a (text, MAC) pair can recompute the MAC from the text, and if it matches the transmitted MAC, be reasonably certain that the text was authentified by someone who possesses the secret key.

module RSA : sig ... end

The RSA module implements RSA public-key cryptography. Public-key cryptography is asymmetric: two distinct keys are used for encrypting a message, then decrypting it. Moreover, while one of the keys must remain secret, the other can be made public, since it is computationally very hard to reconstruct the private key from the public key. This feature supports both public-key encryption (anyone can encode with the public key, but only the owner of the private key can decrypt) and digital signature (only the owner of the private key can sign, but anyone can check the signature with the public key).

module DH : sig ... end

The DH module implements Diffie-Hellman key agreement. Key agreement is a protocol by which two parties can establish a shared secret (typically a key for a symmetric cipher or MAC) by exchanging messages, with the guarantee that even if an attacker eavesdrop on the messages, he cannot recover the shared secret. Diffie-Hellman is one such key agreement protocol, relying on the difficulty of computing discrete logarithms. Notice that the Diffie-Hellman protocol is vulnerable to active attacks (man-in-the-middle attacks).

Advanced, compositional interface to block ciphers and stream ciphers

module Block : sig ... end

The Block module provides classes that implements popular block ciphers, chaining modes, and wrapping of a block cipher as a general transform or as a hash function. The classes can be composed in a Lego-like fashion, facilitating the integration of new block ciphers, modes, etc.

module Stream : sig ... end

The Stream module provides classes that implement the ARCfour stream cipher, and the wrapping of a stream cipher as a general transform. The classes can be composed in a Lego-like fashion, facilitating the integration of new stream ciphers.

Encoding and compression of data

module Base64 : sig ... end

The Base64 module supports the encoding and decoding of binary data in base 64 format, using only alphanumeric characters that can safely be transmitted over e-mail or in URLs.

module Hexa : sig ... end

The Hexa module supports the encoding and decoding of binary data as hexadecimal strings. This is a popular format for transmitting keys in textual form.

module Zlib : sig ... end

The Zlib module supports the compression and decompression of data, using the zlib library. The algorithm used is Lempel-Ziv compression as in the gzip and zip compressors. While compression itself is not encryption, it is often used prior to encryption to reduce the size of the ciphertext.

Error reporting

type error =
  1. | Wrong_key_size
    (*

    The key is too long or too short for the given cipher.

    *)
  2. | Wrong_IV_size
    (*

    The initialization vector does not have the same size as the block size.

    *)
  3. | Wrong_data_length
    (*

    The total length of the input data for a transform is not an integral multiple of the input block size.

    *)
  4. | Bad_padding
    (*

    Incorrect padding bytes were found after decryption.

    *)
  5. | Output_buffer_overflow
    (*

    The output buffer for a transform exceeds the maximal length of a Caml string.

    *)
  6. | Incompatible_block_size
    (*

    A combination of two block ciphers was attempted whereby the ciphers have different block sizes, while they must have the same.

    *)
  7. | Number_too_long
    (*

    Denotes an internal error in RSA key generation or encryption.

    *)
  8. | Seed_too_short
    (*

    The seed given to a pseudo random number generator is too short.

    *)
  9. | Message_too_long
    (*

    For symmetric ciphers in counter mode (CTR): the message exceeds the maximal length supported, causing the counter to wrap around. For RSA encryption or decryption: the message is greater than the modulus of the RSA key.

    *)
  10. | Bad_encoding
    (*

    Illegal characters were found in an encoding of binary data such as base 64 or hexadecimal.

    *)
  11. | Compression_error of string * string
    (*

    Error during compression or decompression.

    *)
  12. | No_entropy_source
    (*

    No entropy source (OS, hardware, or /dev/random) was found for Cryptokit.Random.secure_rng.

    *)
  13. | Entropy_source_closed
    (*

    End of file on a device or EGD entropy source.

    *)
  14. | Compression_not_supported
    (*

    The data compression functions are not available.

    *)

Error codes for this library.

exception Error of error

Exception raised by functions in this library to report error conditions.

Miscellaneous utilities

val wipe_bytes : bytes -> unit

wipe_bytes b overwrites b with zeroes. Can be used to reduce the memory lifetime of sensitive data.

val wipe_string : string -> unit

wipe_string s overwrites s with zeroes. Can be used to reduce the memory lifetime of sensitive data. Note that strings are normally immutable and this operation violates this immutability property. Therefore, this is an unsafe operation, and it should be used only by code that is the only owner of the string s. See Stdlib.Bytes.unsafe_of_string for more details on the ownership policy.

val string_equal : string -> string -> bool

Constant-time comparison between strings. string_equal s1 s2 returns true if the strings s1 and s2 have the same length and contain the same characters. The execution time of this function is determined by the lengths of s1 and s2, but is independent of their contents.

val bytes_equal : bytes -> bytes -> bool

Constant-time comparison between byte sequences. Like Cryptokit.string_equal, but for byte sequences.

val xor_bytes : bytes -> int -> bytes -> int -> int -> unit

xor_bytes src spos dst dpos len performs the xor (exclusive or) of characters spos, ..., spos + len - 1 of src with characters dpos, ..., dpos + len - 1 of dst, storing the result in dst starting at position dpos.

val xor_string : string -> int -> bytes -> int -> int -> unit

Same as xor_bytes, but the source is a string instead of a byte array.

val mod_power : string -> string -> string -> string

mod_power a b c computes a^b mod c, where the strings a, b, c and the result are viewed as arbitrary-precision integers in big-endian format. Requires a < c.

val mod_mult : string -> string -> string -> string

mod_mult a b c computes a*b mod c, where the strings a, b, c and the result are viewed as arbitrary-precision integers in big-endian format.

OCaml

Innovation. Community. Security.