DoAuth.Crypto (do_auth v0.5.0-pre)
Wrappers around just enough of enacl to be able to exectute both client and server parts of the protocol.
Link to this section Summary
Types
Only accept atoms as keys of canonicalisable entities.
Only accept atoms, strings and numbers as values of canonocalisable entities.
Detached signature along with the public key needed to validate.
Enacl iolist.
Message representation: either enacl text or urlsafe encoding of some binary.
Enacl text data representation.
Hash sizes, analogously.
This is a keypair, marking explicitly what's private (secret) key and what's public key.
A keypair that maybe has its secret component omitted.
Derivation limits type. Currently used in default_params function and slip type. They govern how many instructions and how much memory is allowed to be consumed by the system.
Marked public key.
Libsodium-compatible salt size.
Marked private (secret) key.
Main key derivation slip.
Returned by main_key_init
, and required for main_key_reproduce
.
Functions
Unkeyed generic hash of an iolist, represented as a URL-safe Base64 string. Note: the hash size is crypto_generic_BYTES, manually written down as @hash_size macro in this file.
Preventing canonicalisation bugs by ordering maps lexicographically into a list. NB! This makes it so that list representations of JSON objects are also accepted by verifiers, but it's OK, since no data can seemingly be falsified like this.
Currently we use moderate limits, because we want to support small computers. TODO: Use configurable values here, based on the power of a computer.
Create a signing keypair from main key at index n.
Generate slip and main key from password.
Generate slip and main key from password with given parameters.
This function is used directly for testing and flexibility, but shouldn't be normally used.
For most purposes, you should use main_key_init/1
.
Generate main key from password and a slip.
DON'T USE THIS FUNCTION, IT'S EXPORTED JUST FOR BETTER TYPECHEKING!
Keyed (salted) generic hash of an iolist, represented as a URL-safe Base64 string. The key is obtained from the application configuration's paramterer "hash_salt". Note: this parameter is expected to be long-lived and secret. Note: the hash size is crypto_generic_BYTES, manually written down as @hash_size macro in this file.
Simple way to get the server keypair.
DON'T USE THIS FUNCTION, IT'S EXPORTED JUST FOR BETTER TYPECHEKING!
Wrapper around detached signatures that creates an object tracking corresponding public key.
Signs a map and embeds detached signature into it. This function is configurable via options and has the following options
Verify a detached signature object.
Verifies a map that has a proof embedded into it by converting said object into a map, deleting embedding, canonicalising the result and verifying the result against the embedding. This function is configurable via options and has the following options
Verify a raw detached signature object.
Link to this section Types
canonicalisable_key()
Specs
canonicalisable_key() :: atom()
Only accept atoms as keys of canonicalisable entities.
canonicalisable_value()
Specs
canonicalisable_value() :: atom() | Uptight.Base.t() | Uptight.Text.t() | number() | DateTime.t() | [canonicalisable_value()] | %{required(canonicalisable_key()) => canonicalisable_value()}
Only accept atoms, strings and numbers as values of canonocalisable entities.
canonicalised_value()
Specs
canonicalised_value() :: Uptight.Base.t() | Uptight.Text.t() | number() | [[Uptight.Text.t() | canonicalised_value()]]
detached_sig()
Specs
detached_sig() :: %{public: Uptight.Binary.t(), signature: Uptight.Binary.t()}
Detached signature along with the public key needed to validate.
enacl_iolist()
Specs
enacl_iolist() :: binary() | maybe_improper_list( binary() | maybe_improper_list(any(), binary() | []) | byte(), binary() | [] )
Enacl iolist.
enacl_message()
Specs
enacl_message() :: enacl_text() | Uptight.Base.Urlsafe.t()
Message representation: either enacl text or urlsafe encoding of some binary.
enacl_text()
Specs
enacl_text() :: Uptight.Text.t() | enacl_iolist()
Enacl text data representation.
hash()
Specs
hash() :: Uptight.Binary.t()
hash_size()
Specs
hash_size() :: pos_integer()
Hash sizes, analogously.
keypair()
Specs
keypair() :: %{secret: Uptight.Binary.t(), public: Uptight.Binary.t()}
This is a keypair, marking explicitly what's private (secret) key and what's public key.
keypair_opt()
Specs
keypair_opt() :: %{ optional(:secret) => Uptight.Binary.t(), public: Uptight.Binary.t() }
A keypair that maybe has its secret component omitted.
limits()
Specs
limits() :: %{ops: :enacl.pwhash_limit(), mem: :enacl.pwhash_limit()}
Derivation limits type. Currently used in default_params function and slip type. They govern how many instructions and how much memory is allowed to be consumed by the system.
params()
Specs
params() :: %{ ops: :enacl.pwhash_limit(), mem: :enacl.pwhash_limit(), salt_size: salt_size() }
public()
Specs
public() :: %{public: Uptight.Binary.t()}
Marked public key.
salt()
Specs
salt() :: Uptight.Binary.t()
salt_size()
Specs
salt_size() :: pos_integer()
Libsodium-compatible salt size.
Used in defaultparams, but NOT used in @type slip! If you change this parameter, you MUST change :salt, << :: ...>> section of @type slip as well! Some additional safety is provided by defining a simple macro @salt_size below.
secret()
Specs
secret() :: %{secret: Uptight.Binary.t()}
Marked private (secret) key.
slip()
Specs
slip() :: %{ ops: :enacl.pwhash_limit(), mem: :enacl.pwhash_limit(), salt: salt() }
Main key derivation slip.
Returned by main_key_init
, and required for main_key_reproduce
.
slip_raw()
Specs
slip_raw() :: %{ ops: :enacl.pwhash_limit(), mem: :enacl.pwhash_limit(), salt: binary() }
Link to this section Functions
base2raw(arg1)
Specs
base2raw(binary() | Uptight.Text.t() | Uptight.Base.Urlsafe.t()) :: binary()
binary_server_keypair()
Specs
binary_server_keypair() :: %{ secret: Uptight.Binary.t(), public: Uptight.Binary.t() }
bland_hash(msg)
Specs
bland_hash(enacl_text()) :: String.t()
Unkeyed generic hash of an iolist, represented as a URL-safe Base64 string. Note: the hash size is crypto_generic_BYTES, manually written down as @hash_size macro in this file.
canonical_sign(canonical_term, kp)
Specs
canonical_sign(canonicalised_value(), keypair()) :: Uptight.Result.t()
canonical_sign!(canonical_term, kp)
Specs
canonical_sign!(canonicalised_value(), keypair()) :: detached_sig()
canonicalise_term(x)
Specs
canonicalise_term(canonicalisable_value()) :: Uptight.Result.t()
canonicalise_term!(v)
Specs
canonicalise_term!(canonicalisable_value()) :: canonicalised_value()
Preventing canonicalisation bugs by ordering maps lexicographically into a list. NB! This makes it so that list representations of JSON objects are also accepted by verifiers, but it's OK, since no data can seemingly be falsified like this.
TODO: Audit this function really well, both here and in JavaScript reference implementation, since a bug here can sabotage the security guarantees of the cryptographic system.
default_params()
Specs
default_params() :: params()
Currently we use moderate limits, because we want to support small computers. TODO: Use configurable values here, based on the power of a computer.
derive_signing_keypair(mkey, n)
Specs
derive_signing_keypair(Uptight.Binary.t(), pos_integer()) :: keypair()
Create a signing keypair from main key at index n.
is_canonicalised?(x)
Specs
main_key_init(pass)
Specs
main_key_init(enacl_text()) :: {Uptight.Binary.t(), slip()}
Generate slip and main key from password.
main_key_init(pass, map)
Specs
main_key_init(enacl_text(), params()) :: {Uptight.Binary.t(), slip()}
Generate slip and main key from password with given parameters.
This function is used directly for testing and flexibility, but shouldn't be normally used.
For most purposes, you should use main_key_init/1
.
NB! I've used autogenerated spec here, because for some reason, after I moved to enacl types, local typedefs for slip and params stopped working. Gah.
main_key_reproduce(pass, slip)
Specs
main_key_reproduce(enacl_text(), slip()) :: Uptight.Binary.t()
Generate main key from password and a slip.
main_key_reproduce_raw(pass, map)
Specs
main_key_reproduce_raw(binary() | enacl_iolist(), slip_raw()) :: Uptight.Binary.t()
raw2base(arg1)
Specs
raw2base(binary() | Uptight.Binary.t() | Uptight.Base.Urlsafe.t()) :: binary()
DON'T USE THIS FUNCTION, IT'S EXPORTED JUST FOR BETTER TYPECHEKING!
salted_hash(msg)
Specs
salted_hash(enacl_text()) :: String.t()
Keyed (salted) generic hash of an iolist, represented as a URL-safe Base64 string. The key is obtained from the application configuration's paramterer "hash_salt". Note: this parameter is expected to be long-lived and secret. Note: the hash size is crypto_generic_BYTES, manually written down as @hash_size macro in this file.
server_keypair()
Specs
server_keypair() :: keypair()
Simple way to get the server keypair.
TODO: audit key management practices in Phoenix and here.
server_keypair64()
Specs
server_keypair64() :: keypair()
DON'T USE THIS FUNCTION, IT'S EXPORTED JUST FOR BETTER TYPECHEKING!
server_pk()
Specs
server_pk() :: Uptight.Binary.t()
sig64_to_proof_map(arg1, arg2, timestamp \\ nil)
Specs
sig64_to_proof_map(String.t(), String.t(), DateTime.t() | nil) :: map()
See #26!
sign(msg, kp)
Specs
sign(enacl_message(), keypair()) :: detached_sig()
Wrapper around detached signatures that creates an object tracking corresponding public key.
sign_map(kp, the_map, overrides \\ [], defaults \\ sign_map_def_opts())
Specs
sign_map(keypair_opt(), map(), list(), list()) :: Uptight.Result.t()
Signs a map and embeds detached signature into it. This function is configurable via options and has the following options:
- :proof_field - which field carries the embedded proof. Defaults to "proof".
- :signature_field - which field of the proof carries the detached signature. Defaults to "signature".
- :signature - if present, this function won't use :secret from keypair, but instead will add this signature verbatim. No verification shall be conducted in case the signature provided is invalid!
- :key_field - which field of the proof stores information related to key retrieval. Defaults to "verificationMethod".
- :key_field_constructor - a function that takes the public key and options and constructs value for :key_field, perhaps stateful. By default it queries for a DID corresponding to the key and returns its string representation.
- :if_did_missing - if set to :insert, default key constructor will insert a new DID, otherwise will error out. By default set to :fail.
- ignore: [] - list of fields to omit from building a canonicalised object. Defaults to ["id"].
sign_map!(kp, to_prove, overrides \\ [], defopts \\ sign_map_def_opts())
Specs
sign_map!(keypair_opt(), map(), list(), list()) :: map()
sign_map_def_opts()
Specs
sign_raw(msg, map)
Specs
urlsafe_server_keypair()
Specs
urlsafe_server_keypair() :: %{ secret: Uptight.Base.Urlsafe.t(), public: Uptight.Base.Urlsafe.t() }
urlsafe_server_pk()
Specs
urlsafe_server_pk() :: Uptight.Base.Urlsafe.t()
verify(msg, map)
Specs
verify(enacl_message(), detached_sig()) :: boolean()
Verify a detached signature object.
verify_map( verifiable_map, overrides \\ [], defaults \\ [ proof_field: "proof", signature_field: "signature", key_extractor: fn proof_map -> Map.get( proof_map, "verificationMethod" ) end, ignore: ["id"] ] )
Specs
verify_map(map(), list(), list()) :: Uptight.Result.t()
Verifies a map that has a proof embedded into it by converting said object into a map, deleting embedding, canonicalising the result and verifying the result against the embedding. This function is configurable via options and has the following options:
- :proof_field - which field carries the embedded proof. Defaults to "proof".
- ignore: [] - list of fields to ignore. Defaults to ["id"].
- :signature_field - which field carries the detached signature. Defaults to "signature".
- :key_extractor - a function that retreives public key needed to verify embedded proof. Defaults to taking 0th element of DID.all_by_string ran against "verificationMethod" field of the proof object. As per https://www.w3.org/TR/vc-data-model/, proof object may be a list, this function accounts for it. Uses Uptight.Result for returning a value. Exceptions are wrapped in Err and aren't re-raised.
verify_raw(msg, map)
Specs
verify_raw( binary() | maybe_improper_list() | %{ :__struct__ => Uptight.Base.Urlsafe | Uptight.Text, optional(any()) => any() }, %{:public => binary(), :signature => binary(), optional(any()) => any()} ) :: boolean()
Verify a raw detached signature object.