Current section

Files

Jump to
saltpack lib saltpack.ex
Raw

lib/saltpack.ex

defmodule Saltpack do
@moduledoc """
saltpack implementation
https://saltpack.org/
This library presently only handles complete, ASCII-armored messages at rest.
Planned future support for streaming may entail a complete reconsideration of
the API.
"""
@typedoc """
a public or private key
"""
@type key :: <<_ :: 32 * 8>>
@typedoc """
desired key variety
"""
@type key_variety :: :encrypt | :sign
@typedoc """
signature mode
"""
@type signature_mode :: :attached | :detached
@doc """
generate a new `{private, public}` key pair
"""
@spec new_key_pair(key_variety) :: {key, key}
def new_key_pair(kv \\ :encrypt), do: Kcl.generate_key_pair(kv)
@doc """
encrypt a new message
`recipients` should contain a list of all recipient public keys.
An entry may be `nil` for anonymous recipients.
Any supplied `app` name will appear in the message ASCII armoring.
"""
@spec encrypt_message(binary, [key], key, String.t, key) :: binary
def encrypt_message(message, recipients, private, app \\ "", public \\ nil) do
Saltpack.Crypt.create_message(message, recipients, private, public)
|> Saltpack.Armor.armor_message("ENCRYPTED MESSAGE", app)
end
@doc """
sign a new message
This is presently considerably slower than encrypting a same-sized message and
has slightly different calling semantics. Where possible, `encrypt_message/4` should
be preferred.
"""
@spec sign_message(binary, key, String.t, signature_mode, key) :: binary
def sign_message(message, private, app \\ "", mode \\ :attached, public \\ nil)
def sign_message(message, private, app, :attached, public) do
Saltpack.Sign.create_message(message, private, 1, public)
|> Saltpack.Armor.armor_message("SIGNED MESSAGE", app)
end
def sign_message(message, private, app, :detached, public) do
Saltpack.Sign.create_message(message, private, 2, public)
|> Saltpack.Armor.armor_message("DETACHED SIGNATURE", app)
end
@doc """
armor a new message
Any supplied `app` name will appear in the message ASCII armoring.
"""
@spec armor_message(binary, String.t) :: binary
def armor_message(message, app \\ ""), do: message |> Saltpack.Armor.armor_message("MESSAGE", app)
@doc """
open a saltpack message
This may fail in spectacular ways with messages which are not properly
formatted for the supplied key.
Opening a detached signature with plaintext will return the signing public key.
All other versions return the decoded contents upon validation.
"""
@spec open_message(binary, key, binary) :: binary
def open_message(message, key \\ nil, plaintext \\ nil) do
case message |> Saltpack.Armor.dearmor_message do
{"ENCRYPTEDMESSAGE", msg} -> Saltpack.Crypt.open_message(msg, key)
{"SIGNEDMESSAGE", msg} -> Saltpack.Sign.open_message(msg, nil)
{"DETACHEDSIGNATURE", msg} -> Saltpack.Sign.open_message(msg, plaintext)
{"MESSAGE", msg} -> msg
_ -> :noop
end
end
end