451 lines
15 KiB
OCaml
451 lines
15 KiB
OCaml
|
module Num : sig
|
||
|
type t
|
||
|
|
||
|
val zero : unit -> t
|
||
|
val one : unit -> t
|
||
|
val of_uint16 : int -> t
|
||
|
val of_uint32 : int32 -> t
|
||
|
val of_uint64 : int64 -> t
|
||
|
|
||
|
val copy : t -> t -> unit
|
||
|
(** Copy a number. *)
|
||
|
|
||
|
val get_bin : Cstruct.t -> t -> unit
|
||
|
(** Convert a number's absolute value to a binary big-endian string.
|
||
|
There must be enough place. *)
|
||
|
|
||
|
val set_bin : t -> Cstruct.t -> unit
|
||
|
(** Set a number to the value of a binary big-endian string. *)
|
||
|
|
||
|
val mod_inverse : t -> t -> t -> unit
|
||
|
(** [mod_inverse r a m] Compute a modular inverse. The input must be
|
||
|
less than the modulus. *)
|
||
|
|
||
|
val jacobi : t -> t -> int
|
||
|
(** Compute the jacobi symbol (a|b). b must be positive and odd. *)
|
||
|
|
||
|
val compare : t -> t -> int
|
||
|
(** Compare the absolute value of two numbers. *)
|
||
|
|
||
|
val equal : t -> t -> bool
|
||
|
(** Test whether two number are equal (including sign). *)
|
||
|
|
||
|
val add : t -> t -> t -> unit
|
||
|
(** [add r a b] Add two (signed) numbers. *)
|
||
|
|
||
|
val sub : t -> t -> t -> unit
|
||
|
(** [sub r a b] Subtract two (signed) numbers. *)
|
||
|
|
||
|
val mul : t -> t -> t -> unit
|
||
|
(** [mul r a b] Multiply two (signed) numbers. *)
|
||
|
|
||
|
val modulo : t -> t -> unit
|
||
|
(** Replace a number by its remainder modulo m. M's sign is
|
||
|
ignored. The result is a number between 0 and m-1, even if r was
|
||
|
negative. *)
|
||
|
|
||
|
val shift : t -> int -> unit
|
||
|
(** [shift t bits] Right-shift the passed number by [bits] bits. *)
|
||
|
|
||
|
val is_zero : t -> bool
|
||
|
(** Check whether a number is zero. *)
|
||
|
|
||
|
val is_one : t -> bool
|
||
|
(** Check whether a number is one. *)
|
||
|
|
||
|
val is_neg : t -> bool
|
||
|
(** Check whether a number is strictly negative. *)
|
||
|
|
||
|
val negate : t -> unit
|
||
|
(** Change a number's sign. *)
|
||
|
end
|
||
|
|
||
|
module Scalar : sig
|
||
|
type t
|
||
|
(** A scalar modulo the group order of the secp256k1 curve. *)
|
||
|
|
||
|
val zero : unit -> t
|
||
|
val one : unit -> t
|
||
|
val copy : t -> t
|
||
|
|
||
|
val const :
|
||
|
?d7:int64 -> ?d6:int64 -> ?d5:int64 -> ?d4:int64 ->
|
||
|
?d3:int64 -> ?d2:int64 -> ?d1:int64 -> ?d0:int64 -> unit -> t
|
||
|
|
||
|
val clear : t -> unit
|
||
|
(** Clear a scalar to prevent the leak of sensitive data. *)
|
||
|
|
||
|
val get_bits : t -> int -> int -> int
|
||
|
(** [get_bits a offset count] Access bits from a scalar. All
|
||
|
requested bits must belong to the same 32-bit limb. *)
|
||
|
|
||
|
val get_bits_var : t -> int -> int -> int
|
||
|
(** [get_bits a offset count] Access bits from a scalar. Not
|
||
|
constant time. *)
|
||
|
|
||
|
val set_b32 : t -> Cstruct.t -> bool
|
||
|
(** Set a scalar from a big endian byte array. *)
|
||
|
|
||
|
val set_int : t -> int -> unit
|
||
|
(** Set a scalar to an unsigned integer. *)
|
||
|
|
||
|
val get_b32 : Cstruct.t -> t -> unit
|
||
|
(** Convert a scalar to a byte array. *)
|
||
|
|
||
|
val add : t -> t -> t -> bool
|
||
|
(** [add r a b] Add two scalars together (modulo the group
|
||
|
order). Returns whether it overflowed. *)
|
||
|
|
||
|
val cadd_bit : t -> int -> bool -> unit
|
||
|
(** [cadd_bit r bit flag] Conditionally add a power of two to a
|
||
|
scalar. The result is not allowed to overflow. *)
|
||
|
|
||
|
val mul : t -> t -> t -> unit
|
||
|
(** [mul r a b] Multiply two scalars (modulo the group order). *)
|
||
|
|
||
|
val shr_int : t -> int -> int
|
||
|
(** Shift a scalar right by some amount strictly between 0 and 16,
|
||
|
returning the low bits that were shifted off *)
|
||
|
|
||
|
val sqr : t -> t -> unit
|
||
|
(** [sqr r a] Compute the square of a scalar (modulo the group
|
||
|
order). *)
|
||
|
|
||
|
val inverse : t -> t -> unit
|
||
|
(** [inverse r a] Compute the inverse of a scalar (modulo the group
|
||
|
order). *)
|
||
|
|
||
|
val inverse_var : t -> t -> unit
|
||
|
(** [inverse_var r a] Compute the inverse of a scalar (modulo the
|
||
|
group order), without constant-time guarantee. *)
|
||
|
|
||
|
val negate : t -> t -> unit
|
||
|
(** [negate r a] Compute the complement of a scalar (modulo the
|
||
|
group order). *)
|
||
|
|
||
|
val is_zero : t -> bool
|
||
|
(** Check whether a scalar equals zero. *)
|
||
|
|
||
|
val is_one : t -> bool
|
||
|
(** Check whether a scalar equals one. *)
|
||
|
|
||
|
val is_even : t -> bool
|
||
|
(** Check whether a scalar, considered as an nonnegative integer, is
|
||
|
even. *)
|
||
|
|
||
|
val is_high : t -> bool
|
||
|
(** Check whether a scalar is higher than the group order divided by
|
||
|
2. *)
|
||
|
|
||
|
val cond_negate : t -> bool -> bool
|
||
|
(** Conditionally negate a number, in constant time. Returns [true]
|
||
|
if the number was negated, [false] otherwise *)
|
||
|
|
||
|
val get_num : Num.t -> t -> unit
|
||
|
(** Convert a scalar to a number. *)
|
||
|
|
||
|
val order_get_num : Num.t -> unit
|
||
|
(** Get the order of the group as a number. *)
|
||
|
|
||
|
val equal : t -> t -> bool
|
||
|
(** Compare two scalars. *)
|
||
|
|
||
|
val mul_shift_var : t -> t -> t -> int -> unit
|
||
|
(** Multiply a and b (without taking the modulus!), divide by
|
||
|
2**shift, and round to the nearest integer. Shift must be at
|
||
|
least 256. *)
|
||
|
end
|
||
|
|
||
|
(** Field element module.
|
||
|
*
|
||
|
* Field elements can be represented in several ways, but code accessing
|
||
|
* it (and implementations) need to take certain properties into account:
|
||
|
* - Each field element can be normalized or not.
|
||
|
* - Each field element has a magnitude, which represents how far away
|
||
|
* its representation is away from normalization. Normalized elements
|
||
|
* always have a magnitude of 1, but a magnitude of 1 doesn't imply
|
||
|
* normality. *)
|
||
|
module Field : sig
|
||
|
type t
|
||
|
|
||
|
module Storage : sig
|
||
|
type t
|
||
|
val size : int
|
||
|
val of_cstruct : Cstruct.t -> t option
|
||
|
val of_cstruct_exn : Cstruct.t -> t
|
||
|
val to_cstruct : t -> Cstruct.t
|
||
|
val const :
|
||
|
?d7:int64 -> ?d6:int64 -> ?d5:int64 -> ?d4:int64 ->
|
||
|
?d3:int64 -> ?d2:int64 -> ?d1:int64 -> ?d0:int64 -> unit -> t
|
||
|
val cmov : t -> t -> bool -> unit
|
||
|
(** If flag is true, set *r equal to *a; otherwise leave
|
||
|
it. Constant-time. *)
|
||
|
end
|
||
|
|
||
|
val const :
|
||
|
?d7:int64 -> ?d6:int64 -> ?d5:int64 -> ?d4:int64 ->
|
||
|
?d3:int64 -> ?d2:int64 -> ?d1:int64 -> ?d0:int64 -> unit -> t
|
||
|
(** Unpacks a constant into a overlapping multi-limbed FE
|
||
|
element. *)
|
||
|
|
||
|
val normalize : t -> unit
|
||
|
(** Normalize a field element. *)
|
||
|
|
||
|
val normalize_weak : t -> unit
|
||
|
(** Weakly normalize a field element: reduce it magnitude to 1, but
|
||
|
don't fully normalize. *)
|
||
|
|
||
|
val normalize_var : t -> unit
|
||
|
(** Normalize a field element, without constant-time guarantee. *)
|
||
|
|
||
|
val normalizes_to_zero : t -> bool
|
||
|
(** Verify whether a field element represents zero i.e. would
|
||
|
normalize to a zero value. The field implementation may
|
||
|
optionally normalize the input, but this should not be relied
|
||
|
upon. *)
|
||
|
|
||
|
val normalizes_to_zero_var : t -> bool
|
||
|
(** Verify whether a field element represents zero i.e. would
|
||
|
normalize to a zero value. The field implementation may
|
||
|
optionally normalize the input, but this should not be relied
|
||
|
upon. *)
|
||
|
|
||
|
val set_int : t -> int -> unit
|
||
|
(** Set a field element equal to a small integer. Resulting field
|
||
|
element is normalized. *)
|
||
|
|
||
|
val clear : t -> unit
|
||
|
(** Sets a field element equal to zero, initializing all fields. *)
|
||
|
|
||
|
val is_zero : t -> bool
|
||
|
(** Verify whether a field element is zero. Requires the input to be
|
||
|
normalized. *)
|
||
|
|
||
|
val is_odd : t -> bool
|
||
|
(** Check the "oddness" of a field element. Requires the input to be
|
||
|
normalized. *)
|
||
|
|
||
|
val equal : t -> t -> bool
|
||
|
(** Compare two field elements. Requires magnitude-1 inputs. *)
|
||
|
|
||
|
val equal_var : t -> t -> bool
|
||
|
(** Same as secp256k1_fe_equal, but may be variable time. *)
|
||
|
|
||
|
val cmp_var : t -> t -> int
|
||
|
(** Compare two field elements. Requires both inputs to be
|
||
|
normalized. *)
|
||
|
|
||
|
val compare : t -> t -> int
|
||
|
(** Alias to [cmp_var]. *)
|
||
|
|
||
|
val set_b32 : t -> Cstruct.t -> bool
|
||
|
(** Set a field element equal to 32-byte big endian value. If
|
||
|
successful, the resulting field element is normalized. *)
|
||
|
|
||
|
val get_b32 : Cstruct.t -> t -> unit
|
||
|
(** Convert a field element to a 32-byte big endian value. Requires
|
||
|
the input to be normalized. *)
|
||
|
|
||
|
val negate : t -> t -> int -> unit
|
||
|
(** Set a field element equal to the additive inverse of
|
||
|
another. Takes a maximum magnitude of the input as an
|
||
|
argument. The magnitude of the output is one higher. *)
|
||
|
|
||
|
val mul_int : t -> int -> unit
|
||
|
(** Multiplies the passed field element with a small integer
|
||
|
constant. Multiplies the magnitude by that small integer. *)
|
||
|
|
||
|
val add : t -> t -> unit
|
||
|
(** Adds a field element to another. The result has the sum of the
|
||
|
inputs' magnitudes as magnitude. *)
|
||
|
|
||
|
val mul : t -> t -> t -> unit
|
||
|
(** Sets a field element to be the product of two others. Requires
|
||
|
the inputs' magnitudes to be at most 8. The output magnitude is
|
||
|
1 (but not guaranteed to be normalized). *)
|
||
|
|
||
|
val sqr : t -> t -> unit
|
||
|
(** Sets a field element to be the square of another. Requires the
|
||
|
input's magnitude to be at most 8. The output magnitude is 1
|
||
|
(but not guaranteed to be normalized). *)
|
||
|
|
||
|
val sqrt : t -> t -> int
|
||
|
(** If a has a square root, it is computed in r and 1 is
|
||
|
returned. If a does not have a square root, the root of its
|
||
|
negation is computed and 0 is returned. The input's magnitude
|
||
|
can be at most 8. The output magnitude is 1 (but not guaranteed
|
||
|
to be normalized). The result in r will always be a square
|
||
|
itself. *)
|
||
|
|
||
|
val is_quad_var : t -> bool
|
||
|
(** Checks whether a field element is a quadratic residue. *)
|
||
|
|
||
|
val inv : t -> t -> unit
|
||
|
(** Sets a field element to be the (modular) inverse of
|
||
|
another. Requires the input's magnitude to be at most 8. The
|
||
|
output magnitude is 1 (but not guaranteed to be normalized). *)
|
||
|
|
||
|
val inv_var : t -> t -> unit
|
||
|
(** Potentially faster version of secp256k1_fe_inv, without
|
||
|
constant-time guarantee. *)
|
||
|
|
||
|
val inv_all_var : t -> t list -> unit
|
||
|
(** Calculate the (modular) inverses of a batch of field
|
||
|
elements. Requires the inputs' magnitudes to be at most 8. The
|
||
|
output magnitudes are 1 (but not guaranteed to be
|
||
|
normalized). The inputs and outputs must not overlap in
|
||
|
memory. *)
|
||
|
|
||
|
val to_storage : Storage.t -> t -> unit
|
||
|
(** Convert a field element to the storage type. *)
|
||
|
|
||
|
val from_storage : t -> Storage.t -> unit
|
||
|
(** Convert a field element back from the storage type. *)
|
||
|
|
||
|
val cmov : t -> t -> bool -> unit
|
||
|
(** If flag is true, set *r equal to *a; otherwise leave
|
||
|
it. Constant-time. *)
|
||
|
end
|
||
|
|
||
|
module Group : sig
|
||
|
type t
|
||
|
(** Type of a group element (affine coordinates). *)
|
||
|
|
||
|
type ge = t
|
||
|
|
||
|
module Storage : sig
|
||
|
type t
|
||
|
val size : int
|
||
|
val of_cstruct : Cstruct.t -> t option
|
||
|
val of_cstruct_exn : Cstruct.t -> t
|
||
|
val to_cstruct : t -> Cstruct.t
|
||
|
val of_fields :
|
||
|
?x:Field.Storage.t -> ?y:Field.Storage.t -> unit -> t
|
||
|
val cmov : t -> t -> bool -> unit
|
||
|
(** If flag is true, set *r equal to *a; otherwise leave
|
||
|
it. Constant-time. *)
|
||
|
end
|
||
|
|
||
|
module Jacobian : sig
|
||
|
type t
|
||
|
(** Type of a group element (jacobian). *)
|
||
|
|
||
|
val of_fields :
|
||
|
?x:Field.t -> ?y:Field.t -> ?z:Field.t -> ?infinity:bool -> unit -> t
|
||
|
|
||
|
val set_infinity : t -> unit
|
||
|
(** Set a group element (jacobian) equal to the point at
|
||
|
infinity. *)
|
||
|
|
||
|
val get_ge : ge -> t -> unit
|
||
|
(** Set a group element equal to another which is given in jacobian
|
||
|
coordinates. *)
|
||
|
|
||
|
val set_ge : t -> ge -> unit
|
||
|
(** Set a group element (jacobian) equal to another which is given
|
||
|
in affine coordinates. *)
|
||
|
|
||
|
val eq_x_var : Field.t -> t -> int
|
||
|
(** Compare the X coordinate of a group element (jacobian). *)
|
||
|
|
||
|
val neg : t -> t -> unit
|
||
|
(** [neg r a] Set r equal to the inverse of a (i.e., mirrored
|
||
|
around the X axis) *)
|
||
|
|
||
|
val is_infinity : t -> bool
|
||
|
(** Check whether a group element is the point at infinity. *)
|
||
|
|
||
|
val has_quad_y_var : t -> bool
|
||
|
(** Check whether a group element's y coordinate is a quadratic
|
||
|
residue. *)
|
||
|
|
||
|
val double_nonzero : ?rzr:Field.t -> t -> t -> unit
|
||
|
(** [double_nonzero ?rzr r a] Set [r] equal to the double of
|
||
|
[a]. If rzr is not-None, [r->z = a->z * *rzr] (where infinity
|
||
|
means an implicit z = 0). [a] may not be zero. Constant
|
||
|
time. *)
|
||
|
|
||
|
val double_var : ?rzr:Field.t -> t -> t -> unit
|
||
|
(** [double_var ?rzr r a] Set [r] equal to the double of [a]. If
|
||
|
[rzr] is not-None, [r->z = a->z * *rzr] (where infinity means
|
||
|
an implicit z = 0). *)
|
||
|
|
||
|
val add_var : ?rzr:Field.t -> t -> t -> t -> unit
|
||
|
(** [add_var ?rzr r a b] Set [r] equal to the sum of [a] and
|
||
|
[b]. If rzr is non-None, [r->z = a->z * *rzr] ([a] cannot be
|
||
|
infinity in that case). *)
|
||
|
|
||
|
val add_ge : t -> t -> ge -> unit
|
||
|
(** [add_ge r a b] Set [r] equal to the sum of [a] and [b] (with [b] given
|
||
|
in affine coordinates, and not infinity). *)
|
||
|
|
||
|
val add_ge_var : ?rzr:Field.t -> t -> t -> ge -> unit
|
||
|
(** [add_ge_var ?rzr r a b] Set [r] equal to the sum of [a] and [b]
|
||
|
(with [b] given in affine coordinates). This is more efficient
|
||
|
than [add_var]. It is identical to [add_ge] but without
|
||
|
constant-time guarantee, and [b] is allowed to be infinity. If
|
||
|
rzr is non-None, [r->z = a->z * *rzr] ([a] cannot be infinity
|
||
|
in that case). *)
|
||
|
|
||
|
val add_zinv_var : t -> t -> ge -> Field.t -> unit
|
||
|
(** Set r equal to the sum of a and b (with the inverse of b's Z
|
||
|
coordinate passed as bzinv). *)
|
||
|
|
||
|
val mul : t -> ge -> Scalar.t -> unit
|
||
|
|
||
|
val clear : t -> unit
|
||
|
(** Clear a [t] to prevent leaking sensitive information. *)
|
||
|
|
||
|
val rescale : t -> Field.t -> unit
|
||
|
(** Rescale a jacobian point by b which must be
|
||
|
non-zero. Constant-time. *)
|
||
|
end
|
||
|
|
||
|
val of_fields :
|
||
|
?x:Field.t -> ?y:Field.t -> ?infinity:bool -> unit -> t
|
||
|
|
||
|
val g : t
|
||
|
|
||
|
val set_xy : t -> Field.t -> Field.t -> unit
|
||
|
(** Set a group element equal to the point with given X and Y
|
||
|
coordinates *)
|
||
|
|
||
|
val set_xquad : t -> Field.t -> unit
|
||
|
(** Set a group element (affine) equal to the point with the given X
|
||
|
coordinate and a Y coordinate that is a quadratic residue modulo
|
||
|
p. The return value is true iff a coordinate with the given X
|
||
|
coordinate exists. *)
|
||
|
|
||
|
val set_xovar : t -> Field.t -> int -> bool
|
||
|
(** Set a group element (affine) equal to the point with the given X
|
||
|
coordinate, and given oddness for Y. Return value indicates
|
||
|
whether the result is valid. *)
|
||
|
|
||
|
val is_infinity : t -> bool
|
||
|
(** Check whether a group element is the point at infinity. *)
|
||
|
|
||
|
val is_valid_var : t -> bool
|
||
|
(** Check whether a group element is valid (i.e., on the curve). *)
|
||
|
|
||
|
val neg : t -> t -> unit
|
||
|
(** [neg r a] Set r equal to the inverse of a (i.e., mirrored
|
||
|
around the X axis) *)
|
||
|
|
||
|
val clear : t -> unit
|
||
|
(** Clear a [t] to prevent leaking sensitive information. *)
|
||
|
|
||
|
val to_storage : Storage.t -> t -> unit
|
||
|
(** Convert a group element to the storage type. *)
|
||
|
|
||
|
val from_storage : t -> Storage.t -> unit
|
||
|
(** Convert a group element back from the storage type. *)
|
||
|
|
||
|
val to_pubkey : ?compress:bool -> Cstruct.t -> t -> Cstruct.t
|
||
|
(** [to_pubkey ?compress buf ge] serializes [ge] in [buf] and
|
||
|
returns [buf], adjusted to the actual size. *)
|
||
|
|
||
|
val from_pubkey : t -> Cstruct.t -> unit
|
||
|
(** [from_pubkey ge buf] parses a serialized pubkey in [buf] and
|
||
|
writes the result in [ge]. *)
|
||
|
end
|