(** {1 Elliptic curve cryptography} *) (** Mirage-crypto-ec implements public key cryptography with named elliptic curves. Ephemeral key exchanges with {{!Dh}Diffie-Hellman} and {{!Dsa}digital signatures (ECDSA)} are implemented. The arithmetic operations uses code generated by {{:https://github.com/mit-plv/fiat-crypto}fiat-crypto} which is proven to consume a constant amount of time, independent of the input values. *) type error = [ | `Invalid_range | `Invalid_format | `Invalid_length | `Not_on_curve | `At_infinity | `Low_order ] (** The type for errors. *) val pp_error : Format.formatter -> error -> unit (** Pretty printer for errors *) exception Message_too_long (** Raised if the provided message is too long for the curve. *) (** Diffie-Hellman key exchange. *) module type Dh = sig type secret (** Type for private keys. *) val secret_of_octets : ?compress:bool -> string -> (secret * string, error) result (** [secret_of_octets ~compress secret] decodes the provided buffer as {!secret}. If [compress] is provided and [true] (defaults to [false]), the shared part will be compressed. May result in an error if the buffer had an invalid length or was not in bounds. *) val secret_to_octets : secret -> string (** [secret_to_octets secret] encodes the provided secret into a freshly allocated buffer. *) val gen_key : ?compress:bool -> ?g:Mirage_crypto_rng.g -> unit -> secret * string (** [gen_key ~compress ~g ()] generates a private and a public key for Ephemeral Diffie-Hellman. If [compress] is provided and [true] (defaults to [false]), the shared part will be compressed. The returned key pair MUST only be used for a single key exchange. The generated private key is checked to be greater than zero and lower than the group order meaning the public key cannot be the point at inifinity. *) val key_exchange : secret -> string -> (string, error) result (** [key_exchange secret received_public_key] performs Diffie-Hellman key exchange using your secret and the data received from the other party. Returns the shared secret or an error if the received data is wrongly encoded, doesn't represent a point on the curve or represent the point at infinity. The shared secret is returned as is i.e. not stripped from leading 0x00 bytes. The public key encoding is described {{:http://www.secg.org/sec1-v2.pdf}in SEC 1} from SECG. *) end (** Digital signature algorithm. *) module type Dsa = sig type priv (** The type for private keys. *) type pub (** The type for public keys. *) val byte_length : int (** [byte_length] is the size of a ECDSA signature in bytes. *) val bit_length : int (** [bit_length] is the number of significant bits in a ECDSA signature *) (** {2 Serialisation} *) val priv_of_octets : string -> (priv, error) result (** [priv_of_octets buf] decodes a private key from the buffer [buf]. If the provided data is invalid, an error is returned. *) val priv_to_octets : priv -> string (** [priv_to_octets p] encode the private key [p] to a buffer. *) val pub_of_octets : string -> (pub, error) result (** [pub_of_octets buf] decodes a public key from the buffer [buf]. If the provided data is invalid, an error is returned. *) val pub_to_octets : ?compress:bool -> pub -> string (** [pub_to_octets ~compress p] encodes the public key [p] into a buffer. If [compress] is provided and [true] (default [false]), the compressed representation is returned. *) (** {2 Deriving the public key} *) val pub_of_priv : priv -> pub (** [pub_of_priv p] extracts the public key from the private key [p]. *) (** {2 Key generation} *) val generate : ?g:Mirage_crypto_rng.g -> unit -> priv * pub (** [generate ~g ()] generates a key pair. *) (** {2 Cryptographic operations} *) val sign : key:priv -> ?k:string -> string -> string * string (** [sign ~key ~k digest] signs the message [digest] using the private [key]. The [digest] is not processed further - it should be the hash of the message to sign. If [k] is not provided, it is computed using the deterministic construction from RFC 6979. The result is a pair of [r] and [s]. Warning: there {{:https://www.hertzbleed.com/2h2b.pdf}are} {{:https://www.hertzbleed.com/hertzbleed.pdf}attacks} that recover the private key from a power and timing analysis of the RFC 6979 computation of [k] - thus it is advised to provide a good nonce ([k]) explicitly, which is independent of key and digest. @raise Invalid_argument if [k] is not suitable or not in range. @raise Message_too_long if the bit size of [msg] exceeds the curve. *) val verify : key:pub -> string * string -> string -> bool (** [verify ~key (r, s) digest] verifies the signature [r, s] on the message [digest] with the public [key]. The return value is [true] if verification was successful, [false] otherwise. If the message has more bits than the group order, the result is false. *) (** [K_gen] can be instantiated over a hashing module to obtain an RFC6979 compliant [k]-generator for that hash. *) module K_gen (H : Digestif.S) : sig val generate : key:priv -> string -> string (** [generate ~key digest] deterministically takes the given private key and message digest to a [k] suitable for seeding the signing process. *) end (** {2 Misc} *) (** Operations to precompute useful data meant to be hardcoded in [mirage-crypto-ec] before compilation *) module Precompute : sig val generator_tables : unit -> string array array array (** Return an array of shape (Fe_length * 2, 15, 3) containing multiples of the generator point for the curve. Useful only to bootstrap tables necessary for scalar multiplication. *) end end (** Elliptic curve with Diffie-Hellman and DSA. *) module type Dh_dsa = sig (** Diffie-Hellman key exchange. *) module Dh : Dh (** Digital signature algorithm. *) module Dsa : Dsa end (** The NIST P-256 curve, also known as SECP256R1. *) module P256 : Dh_dsa (** The NIST P-384 curve, also known as SECP384R1. *) module P384 : Dh_dsa (** The NIST P-521 curve, also known as SECP521R1. *) module P521 : Dh_dsa (** Curve 25519 Diffie-Hellman, also known as X25519. *) module X25519 : Dh (** Curve 25519 DSA, also known as Ed25519. *) module Ed25519 : sig type priv (** The type for private keys. *) type pub (** The type for public keys. *) (** {2 Serialisation} *) val priv_of_octets : string -> (priv, error) result (** [priv_of_octets buf] decodes a private key from the buffer [buf]. If the provided data is invalid, an error is returned. *) val priv_to_octets : priv -> string (** [priv_to_octets p] encode the private key [p] to a buffer. *) val pub_of_octets : string -> (pub, error) result (** [pub_of_octets buf] decodes a public key from the buffer [buf]. If the provided data is invalid, an error is returned. *) val pub_to_octets : pub -> string (** [pub_to_octets p] encodes the public key [p] into a buffer. *) (** {2 Deriving the public key} *) val pub_of_priv : priv -> pub (** [pub_of_priv p] extracts the public key from the private key [p]. *) (** {2 Key generation} *) val generate : ?g:Mirage_crypto_rng.g -> unit -> priv * pub (** [generate ~g ()] generates a key pair. *) (** {2 Cryptographic operations} *) val sign : key:priv -> string -> string (** [sign ~key msg] signs the message [msg] using the private [key]. The result is the concatenation of [r] and [s], as specified in RFC 8032. *) val verify : key:pub -> string -> msg:string -> bool (** [verify ~key signature msg] verifies the [signature] on the message [msg] with the public [key]. The return value is [true] if verification was successful, [false] otherwise. *) end