package spoke
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=b9999ab024b8b6d0949d198551c9d0a20a564b1c8a56a6fb9a875e7e008d4d68
sha512=135d138d4a6d4793e782e42a27fb2d0acb1f41bd304897792acd16d0a450a31cd4f8fab2bdeeb7fecaa7c6cbeb002b0be3c51baca71629548ab2b7b04d96b784
doc/spoke.core/Spoke/index.html
Module SpokeSource
Spoke, an implementation of SPAKE2+EE in OCaml.
Spoke is an implementation of SPAKE2+EE, a Password-Authenticated Key Agreement. It permits to find an agreement between two people who share a weak password with a strong key via an exchange of few information. From the shared strong key, 2 people can initiate a communication via, for example, a symmetric cryptographic method such as GCM or ChaCha20 Poly1305.
This module wants to implement the necessary cryptographic primitives for this agreement.
The Handshake.
We identify 2 persons, a server and a client. The server will generate some values and a salt and send it to the client with generate. 2 values are then generated, secret and public. The first must be strictly known only by the server. The second must be transferred to the client.
The client can manipulate public with hello and generate a value to be passed to the server. The value is named X. hello returns a client value which must be kept by the client.
The server can then manipulate this received value with server_compute to produce 2 values (which can be concatenated) to send to the client. These values are: Y and client_validator. The first participates to the handshake, the second checks the shared key on the client side. server_compute returns a server which must be kept by the server and used later.
The client can finalise the agreement with client_compute by finally calculating the
ype:shared_keys |
. It requires the Y value and the client_validator value as well as the client value returned previously. It will then send a final value to ensure that the server can correctly produce the said shared key. The name of this value is the server_validator.
Finally, the server can commit the agreement by checking the value transmitted by the client as well as the server value generated previously and in turn generating the shared key.
Parameters.
The user is able to choose:
- the
KDFfunction used to generate values (seealgorithm) - an argument which will be used by the chosen algorithm
ciphers which will be used by the client and the server- tha
hashalgorithm used to craft internal values
Order of primities.
Following the handshake explanation above, here is an example of the order in which the primitives should be executed:
let run ~password =
let secret, public = Spoke.generate ~password ~algorithm:Pbkdf2 16 in
let+ client, _X = Spoke.hello ~public password in
let+ server, (_Y, client_validator) = Spoke.server_compute ~secret
~identity:("Bob", "Alice") _X in
let+ sk0, server_validator = Spoke.client_compute ~client
~identity:("Bob", "Alice") _Y client_validator in
let+ sk1 = Spoke.server_finalize ~server server_validator in
assert (sk0 = sk1)The type of a client.
The type of a server.
The KDF (Key Derivation Function) used to generate common informations between client & server.
type _ aead = | GCM : Mirage_crypto.Cipher_block.AES.GCM.key aead| CCM16 : Mirage_crypto.Cipher_block.AES.CCM16.key aead| ChaCha20_Poly1305 : Mirage_crypto.Chacha20.key aead
The type of Authenticated Encryptions with Associated Data.
The type of the public part of the handshake.
The type of the secret part of the handshake.
The type of shared keys.
type error = [ | `Point_is_not_on_prime_order_subgroup| `Invalid_client_validator| `Invalid_server_validator| `Invalid_public_packet| `Invalid_secret_packet
]The type of errors.
The version of the handshake.
public_to_string public serializes the public information into bytes. Therefore, the public information can be transmitted to a client throught a (secured?) channel.
public_of_string str tries to deserialize a serie of bytes to a public information.
ciphers_of_public str returns ciphers announced by the public information serialized.
ciphers_of_client client returns ciphers from a client value.
ciphers_of_secret secret returns ciphers from a secret value.
val hello :
?g:Random.State.t ->
public:string ->
string ->
(client * string, [> error ]) resultval server_compute :
?g:Random.State.t ->
secret:secret ->
identity:(string * string) ->
string ->
(server * (string * string), [> error ]) resultserver_compute ?g ~secret ~identity:(client, server) _X tries to validate _X with the given secret information and identities. It returns a server information if it succeed as well as a curve point _Y and a client validator. _Y and client_validator should be transmitted to the client.
NOTE: identities is something known to both parties. The client must recognise the server with a unique identifier (like "Bob") and the server must recognise the client with a unique identifier (like "Alice"). But more concretely, the identifier can be the IP address as well as the port of each of the two peers.
val client_compute :
client:client ->
identity:(string * string) ->
string ->
string ->
(shared_keys * string, [> error ]) resultclient_compute ~client ~identity:(client, server) _Y client_validator tries to validate _Y and the client_validator with the given client information and identities (for more details, about identities, you can look at the note for server_compute). It returns shared_keys and the server validator if it succeed. The server_validator should be transmitted to the server.
server_finalize ~server server_validator finalizes the handshake and tries to validate the given server_validator with the given server information. If it succeed, it returns the shared_keys. Then, the user is able to initiate a secure communication with the given client.