Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specs and formatting #14

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 23 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,29 @@ jobs:
- run: mix local.hex --force
- run: mix local.rebar --force
- run: mix deps.get
- run: mix test
- run: mix dialyzer
- run: mix format --check-formatted
- run:
command: mix compile
environment:
MIX_ENV: test

- restore_cache:
keys:
- v2-plt-cache-{{ arch }}-{{ checksum "mix.lock" }}
- v2-plt-cache-{{ arch }}
- v2-plt-cache

- run: mix dialyzer --plt

- save_cache:
key: _build
key: v2-plt-cache-{{ arch }}-{{ checksum "mix.lock" }}
paths:
- _build
- ~/.mix

- run: mix dialyzer --halt-exit-status

- save_cache:
key: _build
paths:
- _build
3 changes: 3 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
erlang 21.1
elixir 1.7-otp-21
56 changes: 42 additions & 14 deletions lib/aes/aes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule ExthCrypto.AES do
iex> ExthCrypto.AES.block_size
32
"""
@spec block_size :: integer()
@spec block_size :: 32
def block_size, do: @block_size

@doc """
Expand Down Expand Up @@ -58,11 +58,21 @@ defmodule ExthCrypto.AES do
iex> ExthCrypto.AES.encrypt("jedi knight", :ecb, ExthCrypto.Test.symmetric_key)
<<98, 60, 215, 107, 189, 132, 176, 63, 62, 225, 92, 13, 70, 53, 187, 240>>
"""
@spec encrypt(ExthCrypto.Cipher.plaintext, ExthCrypto.Cipher.mode, ExthCrypto.symmetric_key, ExthCrypto.Cipher.init_vector) :: ExthCrypto.Cipher.ciphertext
@spec encrypt(
ExthCrypto.Cipher.plaintext(),
ExthCrypto.Cipher.mode(),
ExthCrypto.Key.symmetric_key(),
ExthCrypto.Cipher.init_vector()
) :: ExthCrypto.Cipher.ciphertext()
def encrypt(plaintext, :cbc, symmetric_key, init_vector) do
padding_bits = ( 16 - rem(byte_size(plaintext), 16) ) * 8

:crypto.block_encrypt(:aes_cbc, symmetric_key, init_vector, <<0::size(padding_bits)>> <> plaintext)
padding_bits = (16 - rem(byte_size(plaintext), 16)) * 8

:crypto.block_encrypt(
:aes_cbc,
symmetric_key,
init_vector,
<<0::size(padding_bits)>> <> plaintext
)
end

def encrypt(plaintext, :ctr, symmetric_key, init_vector) do
Expand All @@ -73,9 +83,13 @@ defmodule ExthCrypto.AES do
ciphertext
end

@spec encrypt(ExthCrypto.Cipher.plaintext, ExthCrypto.Cipher.mode, ExthCrypto.symmetric_key) :: ExthCrypto.Cipher.ciphertext
@spec encrypt(
ExthCrypto.Cipher.plaintext(),
ExthCrypto.Cipher.mode(),
ExthCrypto.Key.symmetric_key()
) :: ExthCrypto.Cipher.ciphertext()
def encrypt(plaintext, :ecb, symmetric_key) do
padding_bits = ( 16 - rem(byte_size(plaintext), 16) ) * 8
padding_bits = (16 - rem(byte_size(plaintext), 16)) * 8

:crypto.block_encrypt(:aes_ecb, symmetric_key, <<0::size(padding_bits)>> <> plaintext)
end
Expand Down Expand Up @@ -130,7 +144,12 @@ defmodule ExthCrypto.AES do
iex> ExthCrypto.AES.decrypt(<<98, 60, 215, 107, 189, 132, 176, 63, 62, 225, 92, 13, 70, 53, 187, 240>>, :ecb, ExthCrypto.Test.symmetric_key)
<<0, 0, 0, 0, 0>> <> "jedi knight"
"""
@spec decrypt(ExthCrypto.Cipher.ciphertext, ExthCrypto.Cipher.mode, ExthCrypto.symmetric_key, ExthCrypto.Cipher.init_vector) :: ExthCrypto.Cipher.plaintext
@spec decrypt(
ExthCrypto.Cipher.ciphertext(),
ExthCrypto.Cipher.mode(),
ExthCrypto.Key.symmetric_key(),
ExthCrypto.Cipher.init_vector()
) :: ExthCrypto.Cipher.plaintext()
def decrypt(ciphertext, :cbc, symmetric_key, init_vector) do
:crypto.block_decrypt(:aes_cbc, symmetric_key, init_vector, ciphertext)
end
Expand All @@ -143,7 +162,11 @@ defmodule ExthCrypto.AES do
plaintext
end

@spec decrypt(ExthCrypto.Cipher.ciphertext, ExthCrypto.Cipher.mode, ExthCrypto.symmetric_key) :: ExthCrypto.Cipher.plaintext
@spec decrypt(
ExthCrypto.Cipher.ciphertext(),
ExthCrypto.Cipher.mode(),
ExthCrypto.Key.symmetric_key()
) :: ExthCrypto.Cipher.plaintext()
def decrypt(ciphertext, :ecb, symmetric_key) do
:crypto.block_decrypt(:aes_ecb, symmetric_key, ciphertext)
end
Expand All @@ -158,7 +181,11 @@ defmodule ExthCrypto.AES do
iex> is_nil(stream)
false
"""
@spec stream_init(ExthCrypto.Cipher.mode, ExthCrypto.Key.symmetric_key, ExthCrypto.Cipher.init_vector) :: ExthCrypto.Cipher.stream
@spec stream_init(
ExthCrypto.Cipher.mode(),
ExthCrypto.Key.symmetric_key(),
ExthCrypto.Cipher.init_vector()
) :: ExthCrypto.Cipher.stream()
def stream_init(:ctr, symmetric_key, init_vector) do
# IO.inspect(["Have symm key: ", symmetric_key])
:crypto.stream_init(:aes_ctr, symmetric_key, init_vector)
Expand All @@ -175,7 +202,8 @@ defmodule ExthCrypto.AES do
iex> ciphertext
"'d<KX"
"""
@spec stream_encrypt(ExthCrypto.Cipher.plaintext, ExthCrypto.Cipher.stream) :: { ExthCrypto.Cipher.stream, ExthCrypto.Cipher.ciphertext }
@spec stream_encrypt(ExthCrypto.Cipher.plaintext(), ExthCrypto.Cipher.stream()) ::
{ExthCrypto.Cipher.stream(), ExthCrypto.Cipher.ciphertext()}
def stream_encrypt(plaintext, stream) do
:crypto.stream_encrypt(stream, plaintext)
end
Expand All @@ -192,9 +220,9 @@ defmodule ExthCrypto.AES do
iex> plaintext
"hello"
"""
@spec stream_decrypt(ExthCrypto.Cipher.ciphertext, ExthCrypto.Cipher.stream) :: { ExthCrypto.Cipher.stream, ExthCrypto.Cipher.plaintrxt }
@spec stream_decrypt(ExthCrypto.Cipher.ciphertext(), ExthCrypto.Cipher.stream()) ::
{ExthCrypto.Cipher.stream(), ExthCrypto.Cipher.plaintext()}
def stream_decrypt(plaintext, stream) do
:crypto.stream_decrypt(stream, plaintext)
end

end
end
14 changes: 7 additions & 7 deletions lib/cipher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule ExthCrypto.Cipher do
@type plaintext :: iodata()
@type ciphertext :: binary()
@type init_vector :: binary()
@opaque stream :: :crypto.ctr_state
@type stream :: :crypto.stream_state()

@doc """
Encrypts the given plaintext for the given block cipher.
Expand All @@ -24,12 +24,12 @@ defmodule ExthCrypto.Cipher do
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
@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
@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
Expand All @@ -54,12 +54,12 @@ defmodule ExthCrypto.Cipher do
...> |> 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
@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
@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
Expand All @@ -75,8 +75,8 @@ defmodule ExthCrypto.Cipher do
iex> ExthCrypto.Cipher.generate_init_vector(32) == ExthCrypto.Cipher.generate_init_vector(32)
false
"""
@spec generate_init_vector(integer()) :: init_vector
@spec generate_init_vector(non_neg_integer()) :: init_vector
def generate_init_vector(block_size) do
:crypto.strong_rand_bytes(block_size)
end
end
end
19 changes: 12 additions & 7 deletions lib/ecies/ecdh.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ defmodule ExthCrypto.ECIES.ECDH do
@default_curve :secp256k1

@doc """
Generates a new keypair for elliptic curve diffie-hellman.
Generates a new key_pair for elliptic curve diffie-hellman.

These keys should be used as ephemeral keys in the key-exchange protocol.

## Examples

iex> {public_key, private_key} = ExthCrypto.ECIES.ECDH.new_ecdh_keypair()
iex> {public_key, private_key} = ExthCrypto.ECIES.ECDH.new_ecdh_key_pair()
iex> byte_size(public_key)
65
iex> byte_size(private_key)
32
iex> {public_key, private_key} == :crypto.generate_key(:ecdh, :secp256k1, private_key)
true
"""
@spec new_ecdh_keypair(ExthCrypto.named_curve) :: ExthCrypto.Key.keypair
def new_ecdh_keypair(curve \\ @default_curve) when is_atom(curve) do
@spec new_ecdh_key_pair(ExthCrypto.named_curve()) :: ExthCrypto.Key.key_pair()
def new_ecdh_key_pair(curve \\ @default_curve) when is_atom(curve) do
:crypto.generate_key(:ecdh, curve)
end

Expand All @@ -37,8 +37,13 @@ defmodule ExthCrypto.ECIES.ECDH do
iex> ExthCrypto.ECIES.ECDH.generate_shared_secret(ExthCrypto.Test.private_key(:key_a), ExthCrypto.Test.public_key(:key_b), :secp256k1)
<<68, 139, 102, 172, 32, 159, 198, 236, 33, 216, 132, 22, 62, 46, 163, 215, 53, 40, 177, 14, 51, 94, 155, 151, 21, 226, 9, 254, 153, 48, 112, 226>>
"""
@spec generate_shared_secret(ExthCrypto.Key.private_key, ExthCrypto.Key.public_key, ExthCrypto.named_curve) :: binary()
def generate_shared_secret(local_private_key, remote_public_key, curve \\ @default_curve) when is_atom(curve) do
@spec generate_shared_secret(
ExthCrypto.Key.private_key(),
ExthCrypto.Key.public_key(),
ExthCrypto.named_curve()
) :: binary()
def generate_shared_secret(local_private_key, remote_public_key, curve \\ @default_curve)
when is_atom(curve) do
:crypto.compute_key(:ecdh, remote_public_key, local_private_key, curve)
end
end
end