DOC: convert library(crypto) documentation to DocLog format
This commit is contained in:
@@ -1,20 +1,20 @@
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Written 2020, 2021, 2022 by Markus Triska (triska@metalevel.at)
|
Written 2020-2023 by Markus Triska (triska@metalevel.at)
|
||||||
Part of Scryer Prolog.
|
Part of Scryer Prolog.
|
||||||
|
|
||||||
Predicates for cryptographic applications.
|
/** Predicates for cryptographic applications.
|
||||||
|
|
||||||
This library assumes that the Prolog flag double_quotes is set to chars.
|
This library assumes that the Prolog flag `double_quotes` is set to `chars`.
|
||||||
In Scryer Prolog, lists of characters are very efficiently represented,
|
In Scryer Prolog, lists of characters are very efficiently represented,
|
||||||
and strings have the advantage that the atom table remains unmodified.
|
and strings have the advantage that the atom table remains unmodified.
|
||||||
|
|
||||||
Especially for cryptographic applications, it is an advantage that
|
Especially for cryptographic applications, it is an advantage that
|
||||||
using strings leaves little trace of what was processed in the system.
|
using strings leaves little trace of what was processed in the system.
|
||||||
|
|
||||||
For predicates that accept an encoding/1 option to specify the encoding
|
For predicates that accept an `encoding/1` option to specify the encoding
|
||||||
of the input data, if encoding(octet) is used, then the input can also
|
of the input data, if `encoding(octet)` is used, then the input can also
|
||||||
be specified as a list of bytes, i.e., integers between 0 and 255.
|
be specified as a list of _bytes_, i.e., integers between 0 and 255.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
*/
|
||||||
|
|
||||||
:- module(crypto,
|
:- module(crypto,
|
||||||
[hex_bytes/2, % ?Hex, ?Bytes
|
[hex_bytes/2, % ?Hex, ?Bytes
|
||||||
@@ -48,20 +48,20 @@
|
|||||||
:- use_module(library(si)).
|
:- use_module(library(si)).
|
||||||
:- use_module(library(iso_ext), [partial_string/3]).
|
:- use_module(library(iso_ext), [partial_string/3]).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
hex_bytes(?Hex, ?Bytes) is det.
|
|
||||||
|
|
||||||
Relation between a hexadecimal sequence and a list of bytes. Hex
|
|
||||||
is a string of hexadecimal numbers. Bytes is a list of *integers*
|
|
||||||
between 0 and 255 that represent the sequence as a list of bytes.
|
|
||||||
At least one of the arguments must be instantiated.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
?- hex_bytes("501ACE", Bs).
|
|
||||||
Bs = [80,26,206].
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
|
%% hex_bytes(?Hex, ?Bytes) is det.
|
||||||
|
%
|
||||||
|
% Relation between a hexadecimal sequence and a list of bytes. Hex
|
||||||
|
% is a string of hexadecimal numbers. Bytes is a list of _integers_
|
||||||
|
% between 0 and 255 that represent the sequence as a list of bytes.
|
||||||
|
% At least one of the arguments must be instantiated.
|
||||||
|
%
|
||||||
|
% Example:
|
||||||
|
%
|
||||||
|
% ```
|
||||||
|
% ?- hex_bytes("501ACE", Bs).
|
||||||
|
% Bs = [80,26,206].
|
||||||
|
% ```
|
||||||
|
|
||||||
hex_bytes(Hs, Bytes) :-
|
hex_bytes(Hs, Bytes) :-
|
||||||
( ground(Hs) ->
|
( ground(Hs) ->
|
||||||
@@ -113,47 +113,52 @@ must_be_octet_chars(Chars, Context) :-
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Cryptographically secure random numbers
|
Cryptographically secure random numbers
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
crypto_n_random_bytes(+N, -Bytes) is det
|
|
||||||
|
|
||||||
Bytes is unified with a list of N cryptographically secure
|
|
||||||
pseudo-random bytes. Each byte is an integer between 0 and 255. If
|
|
||||||
the internal pseudo-random number generator (PRNG) has not been
|
|
||||||
seeded with enough entropy to ensure an unpredictable byte
|
|
||||||
sequence, an exception is thrown.
|
|
||||||
|
|
||||||
One way to relate such a list of bytes to an _integer_ is to use
|
|
||||||
CLP(ℤ) constraints as follows:
|
|
||||||
|
|
||||||
:- use_module(library(clpz)).
|
|
||||||
:- use_module(library(lists)).
|
|
||||||
|
|
||||||
bytes_integer(Bs, N) :-
|
|
||||||
foldl(pow, Bs, 0-0, N-_).
|
|
||||||
|
|
||||||
pow(B, N0-I0, N-I) :-
|
|
||||||
B in 0..255,
|
|
||||||
N #= N0 + B*256^I0,
|
|
||||||
I #= I0 + 1.
|
|
||||||
|
|
||||||
With this definition, we can generate a random 256-bit integer
|
|
||||||
_from_ a list of 32 random _bytes_:
|
|
||||||
|
|
||||||
?- crypto_n_random_bytes(32, Bs),
|
|
||||||
bytes_integer(Bs, I).
|
|
||||||
Bs = [146,166,162,210,242,7,25,132,64,94|...],
|
|
||||||
I = 337420085690608915485...(56 digits omitted).
|
|
||||||
|
|
||||||
The above relation also works in the other direction, letting you
|
|
||||||
translate an integer _to_ a list of bytes. In addition, you can
|
|
||||||
use hex_bytes/2 to convert bytes to _tokens_ that can be easily
|
|
||||||
exchanged in your applications.
|
|
||||||
|
|
||||||
?- crypto_n_random_bytes(12, Bs),
|
|
||||||
hex_bytes(Hex, Bs).
|
|
||||||
Bs = [34,25,50,72,58,63,50,172,32,46|...], Hex = "221932483a3f32ac202 ...".
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
%% crypto_n_random_bytes(+N, -Bytes) is det.
|
||||||
|
%
|
||||||
|
% Bytes is unified with a list of N cryptographically secure
|
||||||
|
% pseudo-random bytes. Each byte is an integer between 0 and 255. If
|
||||||
|
% the internal pseudo-random number generator (PRNG) has not been
|
||||||
|
% seeded with enough entropy to ensure an unpredictable byte
|
||||||
|
% sequence, an exception is thrown.
|
||||||
|
%
|
||||||
|
% One way to relate such a list of bytes to an _integer_ is to use
|
||||||
|
% CLP(ℤ) constraints as follows:
|
||||||
|
%
|
||||||
|
% ```
|
||||||
|
% :- use_module(library(clpz)).
|
||||||
|
% :- use_module(library(lists)).
|
||||||
|
%
|
||||||
|
% bytes_integer(Bs, N) :-
|
||||||
|
% foldl(pow, Bs, 0-0, N-_).
|
||||||
|
%
|
||||||
|
% pow(B, N0-I0, N-I) :-
|
||||||
|
% B in 0..255,
|
||||||
|
% N #= N0 + B*256^I0,
|
||||||
|
% I #= I0 + 1.
|
||||||
|
% ```
|
||||||
|
%
|
||||||
|
% With this definition, we can generate a random 256-bit integer
|
||||||
|
% _from_ a list of 32 random _bytes_:
|
||||||
|
%
|
||||||
|
% ```
|
||||||
|
% ?- crypto_n_random_bytes(32, Bs),
|
||||||
|
% bytes_integer(Bs, I).
|
||||||
|
% Bs = [146,166,162,210,242,7,25,132,64,94|...],
|
||||||
|
% I = 337420085690608915485...(56 digits omitted).
|
||||||
|
% ```
|
||||||
|
%
|
||||||
|
% The above relation also works in the other direction, letting you
|
||||||
|
% translate an integer _to_ a list of bytes. In addition, you can
|
||||||
|
% use `hex_bytes/2` to convert bytes to _tokens_ that can be easily
|
||||||
|
% exchanged in your applications.
|
||||||
|
%
|
||||||
|
% ```
|
||||||
|
% ?- crypto_n_random_bytes(12, Bs),
|
||||||
|
% hex_bytes(Hex, Bs).
|
||||||
|
% Bs = [34,25,50,72,58,63,50,172,32,46|...], Hex = "221932483a3f32ac202 ...".
|
||||||
|
% ```
|
||||||
|
|
||||||
crypto_n_random_bytes(N, Bs) :-
|
crypto_n_random_bytes(N, Bs) :-
|
||||||
must_be(integer, N),
|
must_be(integer, N),
|
||||||
@@ -165,30 +170,34 @@ crypto_random_byte(B) :- '$crypto_random_byte'(B).
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Hashing
|
Hashing
|
||||||
=======
|
=======
|
||||||
|
|
||||||
crypto_data_hash(+Data, -Hash, +Options)
|
|
||||||
|
|
||||||
Where Data is a list of characters, and Hash is the computed hash
|
|
||||||
as a list of hexadecimal characters.
|
|
||||||
|
|
||||||
Options is a list of:
|
|
||||||
|
|
||||||
- algorithm(+A)
|
|
||||||
where A is one of ripemd160, sha256, sha384, sha512, sha512_256,
|
|
||||||
sha3_224, sha3_256, sha3_384, sha3_512, blake2s256, blake2b512,
|
|
||||||
or a variable. If A is a variable, then it is unified with the
|
|
||||||
default algorithm, which is an algorithm that is considered
|
|
||||||
cryptographically secure at the time of this writing.
|
|
||||||
- encoding(+Encoding)
|
|
||||||
The default encoding is utf8. The alternative is octet,
|
|
||||||
to treat the input as a list of raw bytes.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
?- crypto_data_hash("abc", Hs, [algorithm(sha256)]).
|
|
||||||
Hs = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
%% crypto_data_hash(+Data, -Hash, +Options)
|
||||||
|
%
|
||||||
|
% Where Data is a list of characters, and Hash is the computed hash
|
||||||
|
% as a list of hexadecimal characters.
|
||||||
|
%
|
||||||
|
% Options is a list of:
|
||||||
|
%
|
||||||
|
% - `algorithm(+A)`
|
||||||
|
% where `A` is one of `ripemd160`, `sha256`, `sha384`, `sha512`,
|
||||||
|
% `sha512_256`, `sha3_224`, `sha3_256`, `sha3_384`,
|
||||||
|
% `sha3_512`, `blake2s256`, `blake2b512`, or a variable. If `A` is
|
||||||
|
% a variable, then it is unified with the default algorithm,
|
||||||
|
% which is an algorithm that is considered cryptographically
|
||||||
|
% secure at the time of this writing.
|
||||||
|
%
|
||||||
|
% - `encoding(+Encoding)`
|
||||||
|
% The default encoding is `utf8`. The alternative is `octet`, to
|
||||||
|
% treat the input as a list of raw bytes.
|
||||||
|
%
|
||||||
|
% Example:
|
||||||
|
%
|
||||||
|
% ```
|
||||||
|
% ?- crypto_data_hash("abc", Hs, [algorithm(sha256)]).
|
||||||
|
% Hs = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".
|
||||||
|
% ```
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SHA256 is the current default for several hash-related predicates.
|
SHA256 is the current default for several hash-related predicates.
|
||||||
It is deemed sufficiently secure for the foreseeable future. Yet,
|
It is deemed sufficiently secure for the foreseeable future. Yet,
|
||||||
@@ -238,38 +247,36 @@ hash_algorithm(blake2s256).
|
|||||||
hash_algorithm(blake2b512).
|
hash_algorithm(blake2b512).
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% crypto_data_hkdf(+Data, +Length, -Bytes, +Options) is det.
|
||||||
crypto_data_hkdf(+Data, +Length, -Bytes, +Options) is det.
|
%
|
||||||
|
% Concentrate possibly dispersed entropy of Data and then expand it
|
||||||
Concentrate possibly dispersed entropy of Data and then expand it
|
% to the desired length. Data is a list of characters.
|
||||||
to the desired length. Data is a list of characters.
|
%
|
||||||
|
% Bytes is unified with a list of bytes of length Length, and is
|
||||||
Bytes is unified with a list of bytes of length Length, and is
|
% suitable as input keying material and initialization vectors to
|
||||||
suitable as input keying material and initialization vectors to
|
% symmetric encryption algorithms.
|
||||||
symmetric encryption algorithms.
|
%
|
||||||
|
% Admissible options are:
|
||||||
Admissible options are:
|
%
|
||||||
|
% - `algorithm(+Algorithm)`
|
||||||
- algorithm(+Algorithm)
|
% One of `sha256`, `sha384` or `sha512`. If you specify a variable,
|
||||||
One of sha256, sha384 or sha512. If you specify a variable,
|
% then it is unified with the algorithm that was used, which is a
|
||||||
then it is unified with the algorithm that was used, which is a
|
% cryptographically secure algorithm by default.
|
||||||
cryptographically secure algorithm by default.
|
% - `info(+Info)`
|
||||||
- info(+Info)
|
% Optional context and application specific information,
|
||||||
Optional context and application specific information,
|
% specified as a list of characters. The default is `[]`.
|
||||||
specified as a list of characters. The default is [].
|
% - `salt(+List)`
|
||||||
- salt(+List)
|
% Optionally, a list of bytes that are used as salt. The
|
||||||
Optionally, a list of bytes that are used as salt. The
|
% default is all zeroes.
|
||||||
default is all zeroes.
|
% - `encoding(+Encoding)`
|
||||||
- encoding(+Encoding)
|
% The default encoding is `utf8`. The alternative is `octet`,
|
||||||
The default encoding is utf8. The alternative is octet,
|
% to treat the input as a list of raw bytes.
|
||||||
to treat the input as a list of raw bytes.
|
%
|
||||||
|
% The `info/1` option can be used to generate multiple keys from a
|
||||||
The `info/1` option can be used to generate multiple keys from a
|
% single master key, using for example values such as "key" and
|
||||||
single master key, using for example values such as "key" and
|
% "iv", or the name of a file that is to be encrypted.
|
||||||
"iv", or the name of a file that is to be encrypted.
|
%
|
||||||
|
% See `crypto_n_random_bytes/2` to obtain a suitable salt.
|
||||||
See crypto_n_random_bytes/2 to obtain a suitable salt.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
crypto_data_hkdf(Data0, L, Bytes, Options0) :-
|
crypto_data_hkdf(Data0, L, Bytes, Options0) :-
|
||||||
functor_hash_options(algorithm, Algorithm, Options0, Options),
|
functor_hash_options(algorithm, Algorithm, Options0, Options),
|
||||||
@@ -323,14 +330,12 @@ chars_bytes_(Cs, Bytes, Context) :-
|
|||||||
know if you need to rely on any specifics of this format.
|
know if you need to rely on any specifics of this format.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% crypto_password_hash(+Password, ?Hash) is semidet.
|
||||||
crypto_password_hash(+Password, ?Hash) is semidet.
|
%
|
||||||
|
% If Hash is instantiated, the predicate succeeds _iff_ the hash
|
||||||
If Hash is instantiated, the predicate succeeds _iff_ the hash
|
% matches the given password. Otherwise, the call is equivalent to
|
||||||
matches the given password. Otherwise, the call is equivalent to
|
% `crypto_password_hash(Password, Hash, [])` and computes a
|
||||||
crypto_password_hash(Password, Hash, []) and computes a
|
% password-based hash using the default options.
|
||||||
password-based hash using the default options.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
crypto_password_hash(Password0, Hash) :-
|
crypto_password_hash(Password0, Hash) :-
|
||||||
( nonvar(Hash) ->
|
( nonvar(Hash) ->
|
||||||
@@ -353,58 +358,56 @@ dollar_segments(Ls, Segments) :-
|
|||||||
).
|
).
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% crypto_password_hash(+Password, -Hash, +Options) is det.
|
||||||
crypto_password_hash(+Password, -Hash, +Options) is det.
|
%
|
||||||
|
% Derive Hash based on Password. This predicate is similar to
|
||||||
Derive Hash based on Password. This predicate is similar to
|
% `crypto_data_hash/3` in that it derives a hash from given data.
|
||||||
crypto_data_hash/3 in that it derives a hash from given data.
|
% However, it is tailored for the specific use case of _passwords_.
|
||||||
However, it is tailored for the specific use case of _passwords_.
|
% One essential distinction is that for this use case, the derivation
|
||||||
One essential distinction is that for this use case, the derivation
|
% of a hash should be _as slow as possible_ to counteract brute-force
|
||||||
of a hash should be _as slow as possible_ to counteract brute-force
|
% attacks over possible passwords.
|
||||||
attacks over possible passwords.
|
%
|
||||||
|
% Another important distinction is that equal passwords must yield,
|
||||||
Another important distinction is that equal passwords must yield,
|
% with very high probability, _different_ hashes. For this reason,
|
||||||
with very high probability, _different_ hashes. For this reason,
|
% cryptographically strong random numbers are automatically added to
|
||||||
cryptographically strong random numbers are automatically added to
|
% the password before a hash is derived.
|
||||||
the password before a hash is derived.
|
%
|
||||||
|
% Hash is unified with a string that contains the computed hash and
|
||||||
Hash is unified with a string that contains the computed hash and
|
% all parameters that were used, except for the password. Instead of
|
||||||
all parameters that were used, except for the password. Instead of
|
% storing passwords, store these hashes. Later, you can verify the
|
||||||
storing passwords, store these hashes. Later, you can verify the
|
% validity of a password with `crypto_password_hash/2`, comparing the
|
||||||
validity of a password with crypto_password_hash/2, comparing the
|
% then entered password to the stored hash. If you need to export this
|
||||||
then entered password to the stored hash. If you need to export this
|
% atom, you should treat it as opaque ASCII data with up to 255 bytes
|
||||||
atom, you should treat it as opaque ASCII data with up to 255 bytes
|
% of length. The maximal length may increase in the future.
|
||||||
of length. The maximal length may increase in the future.
|
%
|
||||||
|
% Admissible options are:
|
||||||
Admissible options are:
|
%
|
||||||
|
% - `algorithm(+Algorithm)`
|
||||||
- algorithm(+Algorithm)
|
% The algorithm to use. Currently, the only available algorithm
|
||||||
The algorithm to use. Currently, the only available algorithm
|
% is `'pbkdf2-sha512'`, which is therefore also the default.
|
||||||
is 'pbkdf2-sha512', which is therefore also the default.
|
% - `cost(+C)`
|
||||||
- cost(+C)
|
% C is an integer, denoting the binary logarithm of the number
|
||||||
C is an integer, denoting the binary logarithm of the number
|
% of _iterations_ used for the derivation of the hash. This
|
||||||
of _iterations_ used for the derivation of the hash. This
|
% means that the number of iterations is set to 2^C. Currently,
|
||||||
means that the number of iterations is set to 2^C. Currently,
|
% the default is 17, and thus more than one hundred _thousand_
|
||||||
the default is 17, and thus more than one hundred _thousand_
|
% iterations. You should set this option as high as your server
|
||||||
iterations. You should set this option as high as your server
|
% and users can tolerate. The default is subject to change and
|
||||||
and users can tolerate. The default is subject to change and
|
% will likely increase in the future or adapt to new algorithms.
|
||||||
will likely increase in the future or adapt to new algorithms.
|
% - `salt(+Salt)`
|
||||||
- salt(+Salt)
|
% Use the given list of bytes as salt. By default,
|
||||||
Use the given list of bytes as salt. By default,
|
% cryptographically secure random numbers are generated for this
|
||||||
cryptographically secure random numbers are generated for this
|
% purpose. The default is intended to be secure, and constitutes
|
||||||
purpose. The default is intended to be secure, and constitutes
|
% the typical use case of this predicate.
|
||||||
the typical use case of this predicate.
|
%
|
||||||
|
% Currently, PBKDF2 with SHA-512 is used as the hash derivation
|
||||||
Currently, PBKDF2 with SHA-512 is used as the hash derivation
|
% function, using 128 bits of salt. All default parameters, including
|
||||||
function, using 128 bits of salt. All default parameters, including
|
% the algorithm, are subject to change, and other algorithms will also
|
||||||
the algorithm, are subject to change, and other algorithms will also
|
% become available in the future. Since computed hashes store all
|
||||||
become available in the future. Since computed hashes store all
|
% parameters that were used during their derivation, such changes will
|
||||||
parameters that were used during their derivation, such changes will
|
% not affect the operation of existing deployments. Note though that
|
||||||
not affect the operation of existing deployments. Note though that
|
% new hashes will then be computed with the new default parameters.
|
||||||
new hashes will then be computed with the new default parameters.
|
%
|
||||||
|
% See `crypto_data_hkdf/4` for generating keys from Hash.
|
||||||
See crypto_data_hkdf/4 for generating keys from Hash.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
crypto_password_hash(Password0, Hash, Options) :-
|
crypto_password_hash(Password0, Hash, Options) :-
|
||||||
chars_bytes_(Password0, Password, crypto_password_hash/3),
|
chars_bytes_(Password0, Password, crypto_password_hash/3),
|
||||||
@@ -435,97 +438,94 @@ bytes_base64(Bytes, Base64) :-
|
|||||||
chars_base64(Chars, Base64, [padding(false)])
|
chars_base64(Chars, Base64, [padding(false)])
|
||||||
).
|
).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% crypto_data_encrypt(+PlainText, +Algorithm, +Key, +IV, -CipherText, +Options).
|
||||||
crypto_data_encrypt(+PlainText,
|
%
|
||||||
+Algorithm,
|
% Encrypt the given PlainText, using the symmetric algorithm
|
||||||
+Key,
|
% Algorithm, key Key, and initialization vector (or nonce) IV, to
|
||||||
+IV,
|
% give CipherText.
|
||||||
-CipherText,
|
%
|
||||||
+Options).
|
% PlainText must be a list of characters, Key and IV must be lists of
|
||||||
|
% bytes, and CipherText is created as a list of characters.
|
||||||
Encrypt the given PlainText, using the symmetric algorithm
|
%
|
||||||
Algorithm, key Key, and initialization vector (or nonce) IV, to
|
% Keys and IVs can be chosen at random (using for example
|
||||||
give CipherText.
|
% `crypto_n_random_bytes/2`) or derived from input keying material (IKM)
|
||||||
|
% using for example `crypto_data_hkdf/4`. This input is often a shared
|
||||||
PlainText must be a list of characters, Key and IV must be lists of
|
% secret, such as a negotiated point on an elliptic curve, or the hash
|
||||||
bytes, and CipherText is created as a list of characters.
|
% that was computed from a password via `crypto_password_hash/3` with a
|
||||||
|
% freshly generated and specified _salt_.
|
||||||
Keys and IVs can be chosen at random (using for example
|
%
|
||||||
crypto_n_random_bytes/2) or derived from input keying material (IKM)
|
% Reusing the same combination of Key and IV typically leaks at least
|
||||||
using for example crypto_data_hkdf/4. This input is often a shared
|
% _some_ information about the plaintext. For example, identical
|
||||||
secret, such as a negotiated point on an elliptic curve, or the hash
|
% plaintexts will then correspond to identical ciphertexts. For some
|
||||||
that was computed from a password via crypto_password_hash/3 with a
|
% algorithms, reusing an IV with the same Key has disastrous results
|
||||||
freshly generated and specified _salt_.
|
% and can cause the loss of all properties that are otherwise
|
||||||
|
% guaranteed. Especially in such cases, an IV is also called a
|
||||||
Reusing the same combination of Key and IV typically leaks at least
|
% _nonce_ (number used once).
|
||||||
_some_ information about the plaintext. For example, identical
|
%
|
||||||
plaintexts will then correspond to identical ciphertexts. For some
|
% It is safe to store and transfer the used initialization vector (or
|
||||||
algorithms, reusing an IV with the same Key has disastrous results
|
% nonce) in plain text, but the key _must be kept secret_.
|
||||||
and can cause the loss of all properties that are otherwise
|
%
|
||||||
guaranteed. Especially in such cases, an IV is also called a
|
% Currently, the only supported algorithm is 'chacha20-poly1305', a
|
||||||
_nonce_ (number used once).
|
% powerful and efficient _authenticated_ encryption scheme, providing
|
||||||
|
% secrecy and at the same time reliable protection against undetected
|
||||||
It is safe to store and transfer the used initialization vector (or
|
% _modifications_ of the encrypted data. This is a very good choice
|
||||||
nonce) in plain text, but the key _must be kept secret_.
|
% for virtually all use cases. It is a stream cipher and can encrypt
|
||||||
|
% data of any length up to 256 GB. Further, the encrypted data has
|
||||||
Currently, the only supported algorithm is 'chacha20-poly1305', a
|
% exactly the same length as the original, and no padding is used.
|
||||||
powerful and efficient _authenticated_ encryption scheme, providing
|
%
|
||||||
secrecy and at the same time reliable protection against undetected
|
% Options:
|
||||||
_modifications_ of the encrypted data. This is a very good choice
|
%
|
||||||
for virtually all use cases. It is a stream cipher and can encrypt
|
% - `encoding(+Encoding)`
|
||||||
data of any length up to 256 GB. Further, the encrypted data has
|
% Encoding to use for PlainText. Default is utf8. The alternative
|
||||||
exactly the same length as the original, and no padding is used.
|
% is octet to treat PlainText as raw bytes.
|
||||||
|
%
|
||||||
Options:
|
% - `tag(-List)`
|
||||||
|
% For authenticated encryption schemes, List is unified with a
|
||||||
- encoding(+Encoding)
|
% list of _bytes_ holding the tag. This tag must be provided for
|
||||||
Encoding to use for PlainText. Default is utf8. The alternative
|
% decryption.
|
||||||
is octet to treat PlainText as raw bytes.
|
%
|
||||||
|
% - `aad(+Data)`
|
||||||
- tag(-List)
|
% Data is additional authenticated data (AAD), a list of
|
||||||
For authenticated encryption schemes, List is unified with a
|
% characters. It is authenticated in that it influences the tag,
|
||||||
list of _bytes_ holding the tag. This tag must be provided for
|
% but it is not encrypted. The `encoding/1` option also specifies
|
||||||
decryption.
|
% the encoding of Data.
|
||||||
|
%
|
||||||
- aad(+Data)
|
% Here is an example encryption and decryption, using the ChaCha20
|
||||||
Data is additional authenticated data (AAD), a list of
|
% stream cipher with the Poly1305 authenticator. This cipher uses a
|
||||||
characters. It is authenticated in that it influences the tag,
|
% 256-bit key and a 96-bit nonce, i.e., 32 and 12 _bytes_,
|
||||||
but it is not encrypted. The encoding/1 option also specifies
|
% respectively:
|
||||||
the encoding of Data.
|
%
|
||||||
|
% ```
|
||||||
Here is an example encryption and decryption, using the ChaCha20
|
% ?- Algorithm = 'chacha20-poly1305',
|
||||||
stream cipher with the Poly1305 authenticator. This cipher uses a
|
% crypto_n_random_bytes(32, Key),
|
||||||
256-bit key and a 96-bit nonce, i.e., 32 and 12 _bytes_,
|
% crypto_n_random_bytes(12, IV),
|
||||||
respectively:
|
% crypto_data_encrypt("this text is to be encrypted", Algorithm,
|
||||||
|
% Key, IV, CipherText, [tag(Tag)]),
|
||||||
?- Algorithm = 'chacha20-poly1305',
|
% crypto_data_decrypt(CipherText, Algorithm,
|
||||||
crypto_n_random_bytes(32, Key),
|
% Key, IV, RecoveredText, [tag(Tag)]).
|
||||||
crypto_n_random_bytes(12, IV),
|
% ```
|
||||||
crypto_data_encrypt("this text is to be encrypted", Algorithm,
|
%
|
||||||
Key, IV, CipherText, [tag(Tag)]),
|
% Yielding:
|
||||||
crypto_data_decrypt(CipherText, Algorithm,
|
%
|
||||||
Key, IV, RecoveredText, [tag(Tag)]).
|
% ```
|
||||||
|
% Algorithm = 'chacha20-poly1305',
|
||||||
Yielding:
|
% Key = [113,247,153,134,177,220,13,193,50,150|...],
|
||||||
|
% IV = [135,20,149,153,63,35,68,114,247,171|...],
|
||||||
Algorithm = 'chacha20-poly1305',
|
% CipherText = "\x94\0Ej\x94\®Â\x95\óÑÆXÃn¾ð©b\x1c\ ...",
|
||||||
Key = [113,247,153,134,177,220,13,193,50,150|...],
|
% RecoveredText = "this text is to be ...",
|
||||||
IV = [135,20,149,153,63,35,68,114,247,171|...],
|
% Tag = [152,117,152,17,162,75,150,206,144,40|...]
|
||||||
CipherText = "\x94\0Ej\x94\®Â\x95\óÑÆXÃn¾ð©b\x1c\ ...",
|
% ```
|
||||||
RecoveredText = "this text is to be ...",
|
%
|
||||||
Tag = [152,117,152,17,162,75,150,206,144,40|...]
|
% In this example, we use `crypto_n_random_bytes/2` to generate a key
|
||||||
|
% and nonce from cryptographically secure random numbers. For
|
||||||
In this example, we use crypto_n_random_bytes/2 to generate a key
|
% repeated applications, you must ensure that a nonce is only used
|
||||||
and nonce from cryptographically secure random numbers. For
|
% _once_ together with the same key. Note that for _authenticated_
|
||||||
repeated applications, you must ensure that a nonce is only used
|
% encryption schemes, the _tag_ that was computed during encryption
|
||||||
_once_ together with the same key. Note that for _authenticated_
|
% is necessary for decryption. It is safe to store and transfer the
|
||||||
encryption schemes, the _tag_ that was computed during encryption
|
% tag in plain text.
|
||||||
is necessary for decryption. It is safe to store and transfer the
|
%
|
||||||
tag in plain text.
|
% See also `crypto_data_decrypt/6`, and `hex_bytes/2` for conversion
|
||||||
|
% between bytes and hex encoding.
|
||||||
See also crypto_data_decrypt/6, and hex_bytes/2 for conversion
|
|
||||||
between bytes and hex encoding.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
crypto_data_encrypt(PlainText0, Algorithm, Key, IV, CipherText, Options) :-
|
crypto_data_encrypt(PlainText0, Algorithm, Key, IV, CipherText, Options) :-
|
||||||
options_data_chars(Options, PlainText0, PlainText, Encoding),
|
options_data_chars(Options, PlainText0, PlainText, Encoding),
|
||||||
@@ -549,37 +549,30 @@ algorithm_key_iv('chacha20-poly1305', Key, IV) :-
|
|||||||
length(Key, 32),
|
length(Key, 32),
|
||||||
length(IV, 12).
|
length(IV, 12).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% crypto_data_decrypt(+CipherText, +Algorithm, +Key, +IV, -PlainText, +Options).
|
||||||
crypto_data_decrypt(+CipherText,
|
%
|
||||||
+Algorithm,
|
% Decrypt the given CipherText, using the symmetric algorithm
|
||||||
+Key,
|
% Algorithm, key Key, and initialization vector IV, to give
|
||||||
+IV,
|
% PlainText. CipherText must be a list of characters, and Key and IV
|
||||||
-PlainText,
|
% must be lists of bytes. PlainText is created as a list of
|
||||||
+Options).
|
% characters.
|
||||||
|
%
|
||||||
Decrypt the given CipherText, using the symmetric algorithm
|
% Currently, the only supported algorithm is 'chacha20-poly1305',
|
||||||
Algorithm, key Key, and initialization vector IV, to give
|
% a very secure, fast and versatile authenticated encryption method.
|
||||||
PlainText. CipherText must be a list of characters, and Key and IV
|
%
|
||||||
must be lists of bytes. PlainText is created as a list of
|
% Options is a list of:
|
||||||
characters.
|
%
|
||||||
|
% - `encoding(+Encoding)`
|
||||||
Currently, the only supported algorithm is 'chacha20-poly1305',
|
% Encoding to use for PlainText. The default is utf8. The
|
||||||
a very secure, fast and versatile authenticated encryption method.
|
% alternative is octet, which is used if the data are raw bytes.
|
||||||
|
%
|
||||||
Options is a list of:
|
% - `tag(+Tag)`
|
||||||
|
% For authenticated encryption schemes, the tag must be specified as
|
||||||
- encoding(+Encoding)
|
% a list of bytes exactly as they were generated upon encryption.
|
||||||
Encoding to use for PlainText. The default is utf8. The
|
%
|
||||||
alternative is octet, which is used if the data are raw bytes.
|
% - `aad(+Data)`
|
||||||
|
% Any additional authenticated data (AAD) must be specified. The
|
||||||
- tag(+Tag)
|
% `encoding/1` option also specifies the encoding of Data.
|
||||||
For authenticated encryption schemes, the tag must be specified as
|
|
||||||
a list of bytes exactly as they were generated upon encryption.
|
|
||||||
|
|
||||||
- aad(+Data)
|
|
||||||
Any additional authenticated data (AAD) must be specified. The
|
|
||||||
encoding/1 option also specifies the encoding of Data.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
crypto_data_decrypt(CipherText0, Algorithm, Key, IV, PlainText, Options) :-
|
crypto_data_decrypt(CipherText0, Algorithm, Key, IV, PlainText, Options) :-
|
||||||
option(tag(Tag), Options, []),
|
option(tag(Tag), Options, []),
|
||||||
@@ -617,49 +610,53 @@ encoding_chars(utf8, Cs, Cs) :-
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Digital signatures with Ed25519
|
Digital signatures with Ed25519
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
- ed25519_new_keypair(-Pair)
|
|
||||||
Yields a new Ed25519 key pair Pair, a list of characters. The
|
|
||||||
pair contains the private key and must be kept absolutely secret.
|
|
||||||
Pair can be used for signing. Its public key can be obtained
|
|
||||||
with ed25519_keypair_public_key/2.
|
|
||||||
|
|
||||||
- ed25519_keypair_public_key(+Pair, -PublicKey)
|
|
||||||
PublicKey is the public key of the given key pair. The public key
|
|
||||||
can be used for signature verification, and can be shared freely.
|
|
||||||
The public key is represented as a list of characters.
|
|
||||||
|
|
||||||
- ed25519_sign(+Key, +Data, -Signature, +Options)
|
|
||||||
Key and Data must be lists of characters. Key is a key pair in
|
|
||||||
PKCS#8 v2 format as generated by ed25519_new_keypair/1. Sign Data
|
|
||||||
with Key, yielding Signature as a list of hexadecimal characters.
|
|
||||||
|
|
||||||
- ed25519_verify(+Key, +Data, +Signature, +Options)
|
|
||||||
Key and Data must be lists of characters. Key is a public key.
|
|
||||||
Succeeds if Data was signed with the private key corresponding to
|
|
||||||
Key, where Signature is a list of hexadecimal characters as
|
|
||||||
generated by ed25519_sign/4. Fails otherwise.
|
|
||||||
|
|
||||||
Currently, the only option for signing and verifying is:
|
|
||||||
|
|
||||||
- encoding(+Encoding)
|
|
||||||
The default encoding of Data is utf8. The alternative is octet,
|
|
||||||
which treats Data as a list of raw bytes.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
%% ed25519_new_keypair(-Pair)
|
||||||
|
%
|
||||||
|
% Yields a new Ed25519 key pair Pair, a list of characters. The
|
||||||
|
% pair contains the private key and must be kept absolutely secret.
|
||||||
|
% Pair can be used for signing. Its public key can be obtained
|
||||||
|
% with `ed25519_keypair_public_key/2`.
|
||||||
|
|
||||||
ed25519_new_keypair(Pair) :-
|
ed25519_new_keypair(Pair) :-
|
||||||
'$ed25519_new_keypair'(Pair).
|
'$ed25519_new_keypair'(Pair).
|
||||||
|
|
||||||
|
%% ed25519_keypair_public_key(+Pair, -PublicKey)
|
||||||
|
%
|
||||||
|
% PublicKey is the public key of the given key pair. The public key
|
||||||
|
% can be used for signature verification, and can be shared freely.
|
||||||
|
% The public key is represented as a list of characters.
|
||||||
|
|
||||||
ed25519_keypair_public_key(Pair, PublicKey) :-
|
ed25519_keypair_public_key(Pair, PublicKey) :-
|
||||||
must_be_octet_chars(Pair, ed25519_keypair_public_key),
|
must_be_octet_chars(Pair, ed25519_keypair_public_key),
|
||||||
'$ed25519_keypair_public_key'(Pair, PublicKey).
|
'$ed25519_keypair_public_key'(Pair, PublicKey).
|
||||||
|
|
||||||
|
%% ed25519_sign(+Key, +Data, -Signature, +Options)
|
||||||
|
%
|
||||||
|
% Key and Data must be lists of characters. Key is a key pair in
|
||||||
|
% PKCS#8 v2 format as generated by `ed25519_new_keypair/1`. Sign Data
|
||||||
|
% with Key, yielding Signature as a list of hexadecimal characters.
|
||||||
|
|
||||||
ed25519_sign(Key, Data0, Signature, Options) :-
|
ed25519_sign(Key, Data0, Signature, Options) :-
|
||||||
must_be_octet_chars(Key, ed25519_sign),
|
must_be_octet_chars(Key, ed25519_sign),
|
||||||
options_data_chars(Options, Data0, Data, Encoding),
|
options_data_chars(Options, Data0, Data, Encoding),
|
||||||
'$ed25519_sign'(Key, Data, Encoding, Signature0),
|
'$ed25519_sign'(Key, Data, Encoding, Signature0),
|
||||||
hex_bytes(Signature, Signature0).
|
hex_bytes(Signature, Signature0).
|
||||||
|
|
||||||
|
%% ed25519_verify(+Key, +Data, +Signature, +Options)
|
||||||
|
%
|
||||||
|
% Key and Data must be lists of characters. Key is a public key.
|
||||||
|
% Succeeds if Data was signed with the private key corresponding to
|
||||||
|
% Key, where Signature is a list of hexadecimal characters as
|
||||||
|
% generated by `ed25519_sign/4`. Fails otherwise.
|
||||||
|
%
|
||||||
|
% Currently, the only option for signing and verifying is:
|
||||||
|
%
|
||||||
|
% - `encoding(+Encoding)`
|
||||||
|
% The default encoding of Data is `utf8`. The alternative is `octet`,
|
||||||
|
% which treats Data as a list of raw bytes.
|
||||||
|
|
||||||
ed25519_verify(Key, Data0, Signature0, Options) :-
|
ed25519_verify(Key, Data0, Signature0, Options) :-
|
||||||
must_be_octet_chars(Key, ed25519_verify),
|
must_be_octet_chars(Key, ed25519_verify),
|
||||||
options_data_chars(Options, Data0, Data, Encoding),
|
options_data_chars(Options, Data0, Data, Encoding),
|
||||||
@@ -669,38 +666,43 @@ ed25519_verify(Key, Data0, Signature0, Options) :-
|
|||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
X25519: ECDH key exchange over Curve25519
|
X25519: ECDH key exchange over Curve25519
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
Points on Curve25519 are represented as lists of characters that denote
|
|
||||||
the u-coordinate of the Montgomery curve.
|
|
||||||
|
|
||||||
- curve25519_generator(-Gs)
|
|
||||||
Gs is the generator point of Curve25519.
|
|
||||||
|
|
||||||
- curve25519_scalar_mult(+Scalar, +Ps, -Rs)
|
|
||||||
Scalar must be an integer between 0 and 2^256-1,
|
|
||||||
or a list of 32 bytes, and Ps must be a point on the curve.
|
|
||||||
Computes the point Rs = Scalar*Ps as mandated by X25519.
|
|
||||||
|
|
||||||
Alice and Bob can use this to establish a shared secret as follows,
|
|
||||||
where Gs is the generator point of Curve25519:
|
|
||||||
|
|
||||||
1. Alice creates a random integer a and sends As = a*Gs to Bob.
|
|
||||||
2. Bob creates a random integer b and sends Bs = b*Gs to Alice.
|
|
||||||
3. Alice computes Rs = a*Bs.
|
|
||||||
4. Bob computes Rs = b*As.
|
|
||||||
5. Alice and Bob use crypto_data_hkdf/4 on Rs with suitable
|
|
||||||
(same) parameters to obtain lists of bytes that can be used as
|
|
||||||
keys and initialization vectors for symmetric encryption.
|
|
||||||
|
|
||||||
If a and b are kept secret, this method is considered very secure.
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
%% curve25519_generator(-Gs)
|
||||||
|
%
|
||||||
|
% Points on Curve25519 are represented as lists of characters that
|
||||||
|
% denote the u-coordinate of the Montgomery curve. Gs is the
|
||||||
|
% generator point of Curve25519.
|
||||||
|
|
||||||
curve25519_generator(Gs) :-
|
curve25519_generator(Gs) :-
|
||||||
length(Gs0, 32),
|
length(Gs0, 32),
|
||||||
Gs0 = [9|Zs],
|
Gs0 = [9|Zs],
|
||||||
maplist(=(0), Zs),
|
maplist(=(0), Zs),
|
||||||
maplist(char_code, Gs, Gs0).
|
maplist(char_code, Gs, Gs0).
|
||||||
|
|
||||||
|
%% curve25519_scalar_mult(+Scalar, +Ps, -Rs)
|
||||||
|
%
|
||||||
|
% Scalar must be an integer between 0 and 2^256-1,
|
||||||
|
% or a list of 32 bytes, and Ps must be a point on the curve.
|
||||||
|
% Computes the point _Rs = Scalar*Ps as_ mandated by X25519.
|
||||||
|
%
|
||||||
|
% Alice and Bob can use this to establish a shared secret as follows,
|
||||||
|
% where Gs is the generator point of Curve25519:
|
||||||
|
%
|
||||||
|
% 1. Alice creates a random integer _a_ and sends _As = a*Gs_ to Bob.
|
||||||
|
%
|
||||||
|
% 2. Bob creates a random integer _b_ and sends _Bs = b*Gs_ to Alice.
|
||||||
|
%
|
||||||
|
% 3. Alice computes _Rs = a*Bs_.
|
||||||
|
%
|
||||||
|
% 4. Bob computes _Rs = b*As_.
|
||||||
|
%
|
||||||
|
% 5. Alice and Bob use `crypto_data_hkdf/4` on Rs with suitable
|
||||||
|
% (same) parameters to obtain lists of bytes that can be used as
|
||||||
|
% keys and initialization vectors for symmetric encryption.
|
||||||
|
%
|
||||||
|
% If _a_ and _b_ are kept secret, this method is considered very secure.
|
||||||
|
|
||||||
curve25519_scalar_mult(Scalar, Point, Result) :-
|
curve25519_scalar_mult(Scalar, Point, Result) :-
|
||||||
( integer_si(Scalar) ->
|
( integer_si(Scalar) ->
|
||||||
length(ScalarBytes, 32),
|
length(ScalarBytes, 32),
|
||||||
|
|||||||
Reference in New Issue
Block a user