forked from mirage/mirage-crypto
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmirage_crypto_ec.mli
More file actions
267 lines (199 loc) · 9.24 KB
/
mirage_crypto_ec.mli
File metadata and controls
267 lines (199 loc) · 9.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
(** {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
(** Low-level group arithmetic. *)
module Group : sig
(** Points on the elliptic curve. *)
module Point : sig
type t
(** The type for points on the elliptic curve. *)
val of_octets : string -> (t, error) result
(** [of_octets buf] decodes a point from [buf] in uncompressed or
compressed SEC 1 format. Returns an error if the point is not on the
curve. *)
val to_octets : ?compress:bool -> t -> string
(** [to_octets ~compress point] encodes [point] to SEC 1 format. If
[compress] is [true] (default [false]), the compressed format is
used. *)
val generator : t
(** [generator] is the generator point (base point) of the curve. *)
val add : t -> t -> t
(** [add p q] is the sum of points [p] and [q]. *)
end
(** Scalars for the elliptic curve group. *)
module Scalar : sig
type t
(** The type for scalars. *)
val of_octets : string -> (t, error) result
(** [of_octets buf] decodes a scalar from [buf]. Returns an error if
the scalar is not in the valid range \[1, n-1\] where n is the group
order. *)
val to_octets : t -> string
(** [to_octets scalar] encodes [scalar] to a byte string. *)
val mult : t -> Point.t -> Point.t
(** [mult s p] is the scalar multiplication of [p] by [s]. *)
end
end
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