Cmsex.KeyWrap (cmsex v0.1.0)

Copy Markdown View Source

The AES key wrap of RFC 3394, and AES key wrap with padding of RFC 5649.

CMS uses them to encrypt a content-encryption key with another key: the key-encryption key of a KEKRecipientInfo, or the key that a KeyAgreeRecipientInfo derives. They are written in Elixir over the AES block cipher of :crypto.

The key-encryption key is 16, 24 or 32 bytes (AES-128, AES-192 or AES-256). wrap/2 takes key data of 16 bytes or more, in multiples of 8; wrap_with_padding/2 takes any length from 1 byte. Unwrapping checks the integrity value and returns :error when it does not match, which happens with a wrong key-encryption key as well as with a changed ciphertext; nothing tells the two apart.

iex> kek = Base.decode16!("000102030405060708090A0B0C0D0E0F")
iex> key = Base.decode16!("00112233445566778899AABBCCDDEEFF")
iex> wrapped = Cmsex.KeyWrap.wrap(kek, key)
iex> Base.encode16(wrapped)
"1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5"
iex> Cmsex.KeyWrap.unwrap(kek, wrapped)
{:ok, key}

Summary

Functions

Unwraps wrapped with kek (RFC 3394, 2.2.2). Returns :error when the integrity value does not match, or the ciphertext is not 24 bytes or more in multiples of 8.

Unwraps wrapped with kek (RFC 5649, 4.2). Returns :error when the integrity value or the padding does not check, or the ciphertext is not 16 bytes or more in multiples of 8.

Wraps key with kek (RFC 3394, 2.2.1, with the default initial value). Raises ArgumentError for a key-encryption key that is not an AES key, or key data that is shorter than 16 bytes or not a multiple of 8.

Wraps key, of any length from 1 byte, with kek (RFC 5649, 4.1). Raises ArgumentError for a key-encryption key that is not an AES key, or empty key data.

Functions

unwrap(kek, wrapped)

@spec unwrap(binary(), binary()) :: {:ok, binary()} | :error

Unwraps wrapped with kek (RFC 3394, 2.2.2). Returns :error when the integrity value does not match, or the ciphertext is not 24 bytes or more in multiples of 8.

unwrap_with_padding(kek, wrapped)

@spec unwrap_with_padding(binary(), binary()) :: {:ok, binary()} | :error

Unwraps wrapped with kek (RFC 5649, 4.2). Returns :error when the integrity value or the padding does not check, or the ciphertext is not 16 bytes or more in multiples of 8.

wrap(kek, key)

@spec wrap(binary(), binary()) :: binary()

Wraps key with kek (RFC 3394, 2.2.1, with the default initial value). Raises ArgumentError for a key-encryption key that is not an AES key, or key data that is shorter than 16 bytes or not a multiple of 8.

wrap_with_padding(kek, key)

@spec wrap_with_padding(binary(), binary()) :: binary()

Wraps key, of any length from 1 byte, with kek (RFC 5649, 4.1). Raises ArgumentError for a key-encryption key that is not an AES key, or empty key data.