Current section

Files

Jump to
exth_crypto lib cipher.ex
Raw

lib/cipher.ex

defmodule ExthCrypto.Cipher do
@moduledoc """
Module for symmetric encryption.
"""
@type mode :: :cbc | :ctr | :ecb
@type cipher :: {atom(), integer(), mode}
@type plaintext :: iodata()
@type ciphertext :: binary()
@type init_vector :: binary()
@opaque stream :: :crypto.ctr_state
@doc """
Encrypts the given plaintext for the given block cipher.
## Examples
iex> ExthCrypto.Cipher.encrypt("execute order 66", ExthCrypto.Test.symmetric_key, ExthCrypto.Test.init_vector, {ExthCrypto.AES, ExthCrypto.AES.block_size, :cbc}) |> ExthCrypto.Math.bin_to_hex
"4f0150273733727f994754fee054df7e18ec169892db5ba973cf8580b898651b"
iex> ExthCrypto.Cipher.encrypt("execute order 66", ExthCrypto.Test.symmetric_key, ExthCrypto.Test.init_vector, {ExthCrypto.AES, ExthCrypto.AES.block_size, :ctr}) |> ExthCrypto.Math.bin_to_hex
"2a7935444247175ff635309b9274e948"
iex> ExthCrypto.Cipher.encrypt("execute order 66", ExthCrypto.Test.symmetric_key, {ExthCrypto.AES, ExthCrypto.AES.block_size, :ecb}) |> ExthCrypto.Math.bin_to_hex
"a73c5576667b7b43a23a9fd930b5465d637a44d08bf702881a8d4e6a5d4944b5"
"""
@spec encrypt(plaintext, ExthCrypto.Key.symmetric_key, init_vector, cipher) :: ciphertext
def encrypt(plaintext, symmetric_key, init_vector, {mod, _block_size, mode} = _cipher) do
mod.encrypt(plaintext, mode, symmetric_key, init_vector)
end
@spec encrypt(plaintext, ExthCrypto.Key.symmetric_key, cipher) :: ciphertext
def encrypt(plaintext, symmetric_key, {mod, _block_size, mode} = _cipher) do
mod.encrypt(plaintext, mode, symmetric_key)
end
@doc """
Decrypts the given ciphertext from the given block cipher.
## Examples
iex> "4f0150273733727f994754fee054df7e18ec169892db5ba973cf8580b898651b"
...> |> ExthCrypto.Math.hex_to_bin
...> |> ExthCrypto.Cipher.decrypt(ExthCrypto.Test.symmetric_key, ExthCrypto.Test.init_vector, {ExthCrypto.AES, ExthCrypto.AES.block_size, :cbc})
<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> <> "execute order 66"
iex> "2a7935444247175ff635309b9274e948"
...> |> ExthCrypto.Math.hex_to_bin
...> |> ExthCrypto.Cipher.decrypt(ExthCrypto.Test.symmetric_key, ExthCrypto.Test.init_vector, {ExthCrypto.AES, ExthCrypto.AES.block_size, :ctr})
"execute order 66"
iex> "a73c5576667b7b43a23a9fd930b5465d637a44d08bf702881a8d4e6a5d4944b5"
...> |> ExthCrypto.Math.hex_to_bin
...> |> ExthCrypto.Cipher.decrypt(ExthCrypto.Test.symmetric_key, {ExthCrypto.AES, ExthCrypto.AES.block_size, :ecb})
<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>> <> "execute order 66"
"""
@spec decrypt(ciphertext, ExthCrypto.Key.symmetric_key, init_vector, cipher) :: plaintext
def decrypt(ciphertext, symmetric_key, init_vector, {mod, _block_size, mode} = _cipher) do
mod.decrypt(ciphertext, mode, symmetric_key, init_vector)
end
@spec decrypt(ciphertext, ExthCrypto.Key.symmetric_key, cipher) :: plaintext
def decrypt(ciphertext, symmetric_key, {mod, _block_size, mode} = _cipher) do
mod.decrypt(ciphertext, mode, symmetric_key)
end
@doc """
Generate a random initialization vector for the given type of cipher.
## Examples
iex> ExthCrypto.Cipher.generate_init_vector(32) |> byte_size
32
iex> ExthCrypto.Cipher.generate_init_vector(32) == ExthCrypto.Cipher.generate_init_vector(32)
false
"""
@spec generate_init_vector(integer()) :: init_vector
def generate_init_vector(block_size) do
:crypto.strong_rand_bytes(block_size)
end
end