diff --git a/src/lib_crypto/secp256k1.ml b/src/lib_crypto/secp256k1.ml index 1bbf05422..b204285e9 100644 --- a/src/lib_crypto/secp256k1.ml +++ b/src/lib_crypto/secp256k1.ml @@ -19,7 +19,11 @@ let () = open Libsecp256k1.External -let context = Context.(create [Verify; Sign]) +let context = + let ctx = Context.create () in + match Context.randomize ctx (Rand.generate 32) with + | false -> failwith "Secp256k1 context randomization failed. Aborting." + | true -> ctx module Public_key = struct @@ -36,7 +40,7 @@ module Public_key = struct let to_string s = MBytes.to_string (to_bytes s) let of_string_opt s = of_bytes_opt (MBytes.of_string s) - let size = 33 (* TODO not hardcoded ?? *) + let size = Key.compressed_pk_bytes type Base58.data += | Data of t @@ -58,7 +62,7 @@ module Public_key = struct include Compare.Make(struct type nonrec t = t let compare a b = - MBytes.compare (Key.to_buffer a) (Key.to_buffer b) + MBytes.compare (Key.buffer a) (Key.buffer b) end) include Helpers.MakeRaw(struct @@ -101,7 +105,7 @@ module Secret_key = struct let name = "Secp256k1.Secret_key" let title = "A Secp256k1 secret key" - let size = 32 (* TODO don't hardcode *) + let size = Key.secret_bytes let of_bytes_opt s = match Key.read_sk context s with @@ -131,7 +135,7 @@ module Secret_key = struct include Compare.Make(struct type nonrec t = t let compare a b = - MBytes.compare (Key.to_buffer a) (Key.to_buffer b) + MBytes.compare (Key.buffer a) (Key.buffer b) end) include Helpers.MakeRaw(struct @@ -167,16 +171,17 @@ module Secret_key = struct end -type t = MBytes.t +type t = Sign.plain Sign.t let name = "Secp256k1" let title = "A Secp256k1 signature" -let size = 64 (* TODO don't hardcode? *) +let size = Sign.plain_bytes let of_bytes_opt s = - if MBytes.length s = size then Some s else None -let to_bytes x = x + match Sign.read context s with Ok s -> Some s | Error _ -> None + +let to_bytes = Sign.to_bytes ~der:false context let to_string s = MBytes.to_string (to_bytes s) let of_string_opt s = of_bytes_opt (MBytes.of_string s) @@ -197,7 +202,8 @@ let () = include Compare.Make(struct type nonrec t = t - let compare = MBytes.compare + let compare a b = + MBytes.compare (Sign.buffer a) (Sign.buffer b) end) include Helpers.MakeRaw(struct @@ -233,38 +239,20 @@ let pp ppf t = Format.fprintf ppf "%s" (to_b58check t) let zero = of_bytes_exn (MBytes.init size '\000') -let sign secret_key message = - match Sign.msg_of_bytes message with - | None -> - Pervasives.invalid_arg - "Secp256k1.sign: argument message couldn't be converted" - | Some msg -> begin - match Sign.sign context ~sk:secret_key ~msg with - | Ok signature -> - Sign.to_bytes ~der:false context signature - | _ -> - Pervasives.invalid_arg "Secp256k1.sign: couldn't sign" - end - +let sign sk msg = + Sign.sign_exn context ~sk msg let check public_key signature msg = - match Sign.msg_of_bytes msg, Sign.read context signature with - | Some msg, Ok signature -> begin - match Sign.verify context ~pk:public_key ~msg ~signature with - | Ok b -> b - | _ -> false - end - | _, _ -> false + Sign.verify_exn context ~pk:public_key ~msg ~signature -let concat msg signature = - MBytes.concat msg signature +let concat msg t = + MBytes.concat msg (Sign.to_bytes ~der:false context t) -let append key msg = - let signature = sign key msg in - concat msg signature +let append sk msg = + concat msg (Sign.sign_exn context ~sk msg) let generate_key () = - let sk = Key.read_sk_exn context (Tweetnacl.Rand.gen 32) in + let sk = Key.read_sk_exn context (Rand.generate 32) in let pk = Key.neuterize_exn context sk in let pkh = Public_key.hash pk in (pkh, pk, sk) diff --git a/vendors/ocaml-secp256k1/Makefile b/vendors/ocaml-secp256k1/Makefile deleted file mode 100644 index 056adfb1e..000000000 --- a/vendors/ocaml-secp256k1/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -all: - jbuilder build @install @runtest - -clean: - rm -rf _build diff --git a/vendors/ocaml-secp256k1/src/external.ml b/vendors/ocaml-secp256k1/src/external.ml index 5fbfb2604..579b6ee0a 100644 --- a/vendors/ocaml-secp256k1/src/external.ml +++ b/vendors/ocaml-secp256k1/src/external.ml @@ -1,59 +1,19 @@ -open StdLabels - -module BA = struct - include Bigarray.Array1 - - let length = size_in_bytes - - let rec compare_rec a b i len_a len_b = - if i=len_a && i=len_b then 0 - else if i=len_a then -1 - else if i=len_b then 1 - else - match Char.compare (get a i) (get b i) with - | 0 -> compare_rec a b (i+1) len_a len_b - | n -> n - - let compare a b = - compare_rec a b 0 (length a) (length b) - - let equal a b = compare a b = 0 - - let create len = - Bigarray.(create char c_layout len) -end - -type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t - module Context = struct - type flag = - | Verify - | Sign - type t - external flags : buffer -> int = "context_flags" - external create : int -> t = "context_create" - external clone : t -> t = "context_clone" - external randomize : t -> buffer -> bool = "context_randomize" [@@noalloc] - external get_16 : buffer -> int -> int = "%caml_bigstring_get16" [@@noalloc] + external create : int -> t = "caml_secp256k1_context_create" + external clone : t -> t = "caml_secp256k1_context_clone" + external randomize : t -> Bigstring.t -> bool = "caml_secp256k1_context_randomize" [@@noalloc] - let flags = - let buf = BA.create (3 * 2) in - let _ = flags buf in - buf - - let int_of_flag = function - | Verify -> get_16 flags 2 - | Sign -> get_16 flags 4 - - let create a = - List.fold_left a ~init:(get_16 flags 0) ~f:(fun a f -> a lor (int_of_flag f)) |> - create + let create ?(sign=true) ?(verify=true) () = + let flags = 1 lor + (if sign then 0x100 else 0) lor + (if verify then 0x200 else 0) in + create flags let randomize ctx buf = - if BA.length buf <> 32 then - invalid_arg "Context.randomize: input must be 32 bytes long" ; + if Bigstring.length buf < 32 then + invalid_arg "Context.randomize: input must be at least 32 bytes long" ; randomize ctx buf end @@ -61,49 +21,51 @@ module Key = struct type secret type public type _ t = - | Sk : buffer -> secret t - | Pk : buffer -> public t + | Sk : Bigstring.t -> secret t + | Pk : Bigstring.t -> public t - let to_buffer : type a. a t -> buffer = function - | Sk k -> k - | Pk k -> k + let buffer : type a. a t -> Bigstring.t = function + | Sk sk -> sk + | Pk pk -> pk let secret_bytes = 32 let public_bytes = 64 + let compressed_pk_bytes = 33 + let uncompressed_pk_bytes = 65 - let length : type a. a t -> int = function - | Sk _ -> 32 - | Pk _ -> 64 + let bytes : type a. a t -> int = function + | Sk _ -> secret_bytes + | Pk _ -> public_bytes + + let serialized_bytes : + type a. ?compressed:bool -> a t -> int = + fun ?(compressed=true) -> function + | Sk _ -> secret_bytes + | Pk _ -> if compressed then public_bytes + 1 else secret_bytes + 1 let equal : type a. a t -> a t -> bool = fun a b -> match a, b with - | Sk a, Sk b -> BA.equal a b - | Pk a, Pk b -> BA.equal a b + | Sk a, Sk b -> Bigstring.equal a b + | Pk a, Pk b -> Bigstring.equal a b let copy : type a. a t -> a t = function - | Sk k -> - let k' = BA.create secret_bytes in - BA.blit k k' ; - Sk k' - | Pk k -> - let k' = BA.create public_bytes in - BA.blit k k' ; - Pk k' + | Sk sk -> Sk (Bigstring.copy sk) + | Pk pk -> Pk (Bigstring.copy pk) - external sk_negate_inplace : Context.t -> buffer -> unit = - "ec_privkey_negate" [@@noalloc] - external sk_add_tweak_inplace : Context.t -> buffer -> buffer -> bool = - "ec_privkey_tweak_add" [@@noalloc] - external sk_mul_tweak_inplace : Context.t -> buffer -> buffer -> bool = - "ec_privkey_tweak_mul" [@@noalloc] - external pk_negate_inplace : Context.t -> buffer -> unit = - "ec_pubkey_negate" [@@noalloc] - external pk_add_tweak_inplace : Context.t -> buffer -> buffer -> bool = - "ec_pubkey_tweak_add" [@@noalloc] - external pk_mul_tweak_inplace : Context.t -> buffer -> buffer -> bool = - "ec_pubkey_tweak_mul" [@@noalloc] - external pk_combine : Context.t -> buffer -> buffer list -> bool = - "ec_pubkey_combine" [@@noalloc] + external sk_negate_inplace : Context.t -> Bigstring.t -> unit = + "caml_secp256k1_ec_privkey_negate" [@@noalloc] + external sk_add_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ec_privkey_tweak_add" [@@noalloc] + external sk_mul_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ec_privkey_tweak_mul" [@@noalloc] + external pk_negate_inplace : Context.t -> Bigstring.t -> unit = + "caml_secp256k1_ec_pubkey_negate" [@@noalloc] + external pk_add_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ec_pubkey_tweak_add" [@@noalloc] + external pk_mul_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ec_pubkey_tweak_mul" [@@noalloc] + external pk_combine : Context.t -> Bigstring.t -> Bigstring.t list -> bool = + "caml_secp256k1_ec_pubkey_combine" [@@noalloc] let negate_inplace : type a. Context.t -> a t -> unit = fun ctx -> function @@ -116,44 +78,43 @@ module Key = struct k' let op_tweak : - type a. string -> (Context.t -> buffer -> buffer -> bool) -> - Context.t -> a t -> ?pos:int -> buffer -> buffer = - fun name f ctx k ?(pos=0) buf -> - let buflen = BA.length buf in - if pos < 0 || pos > buflen - 32 then - invalid_arg (Printf.sprintf "Key.%s: pos < 0 or pos > buflen - 32" name) ; - let buf = BA.sub buf pos 32 in - let k' = copy k |> to_buffer in + type a. string -> (Context.t -> Bigstring.t -> Bigstring.t -> bool) -> + Context.t -> a t -> Bigstring.t -> Bigstring.t = + fun name f ctx k buf -> + let buflen = Bigstring.length buf in + if buflen < 32 then + invalid_arg (Printf.sprintf "Key.%s: " name) ; + let k' = buffer (copy k) in if not (f ctx k' buf) then failwith (Printf.sprintf "Key.%s: operation failed" name) ; k' let add_tweak : - type a. Context.t -> a t -> ?pos:int -> buffer -> a t = - fun ctx k ?pos buf -> + type a. Context.t -> a t -> Bigstring.t -> a t = + fun ctx k buf -> match k with - | Sk _ -> Sk (op_tweak "add_tweak" sk_add_tweak_inplace ctx k ?pos buf) - | Pk _ -> Pk (op_tweak "add_tweak" pk_add_tweak_inplace ctx k ?pos buf) + | Sk _ -> Sk (op_tweak "add_tweak" sk_add_tweak_inplace ctx k buf) + | Pk _ -> Pk (op_tweak "add_tweak" pk_add_tweak_inplace ctx k buf) let mul_tweak : - type a. Context.t -> a t -> ?pos:int -> buffer -> a t = - fun ctx k ?pos buf -> + type a. Context.t -> a t -> Bigstring.t -> a t = + fun ctx k buf -> match k with - | Sk _ -> Sk (op_tweak "mul_tweak" sk_mul_tweak_inplace ctx k ?pos buf) - | Pk _ -> Pk (op_tweak "mul_tweak" pk_mul_tweak_inplace ctx k ?pos buf) + | Sk _ -> Sk (op_tweak "mul_tweak" sk_mul_tweak_inplace ctx k buf) + | Pk _ -> Pk (op_tweak "mul_tweak" pk_mul_tweak_inplace ctx k buf) - external pk_parse : Context.t -> buffer -> buffer -> bool = - "ec_pubkey_parse" [@@noalloc] - external pk_serialize : Context.t -> buffer -> buffer -> int = - "ec_pubkey_serialize" [@@noalloc] - external pk_create : Context.t -> buffer -> buffer -> bool = - "ec_pubkey_create" [@@noalloc] + external pk_parse : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ec_pubkey_parse" [@@noalloc] + external pk_serialize : Context.t -> Bigstring.t -> Bigstring.t -> int = + "caml_secp256k1_ec_pubkey_serialize" [@@noalloc] + external pk_create : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ec_pubkey_create" [@@noalloc] let neuterize : type a. Context.t -> a t -> public t option = fun ctx -> function | Pk pk -> Some (Pk pk) | Sk sk -> - let pk = BA.create public_bytes in + let pk = Bigstring.create public_bytes in if pk_create ctx pk sk then Some (Pk pk) else None let neuterize_exn ctx k = @@ -162,7 +123,7 @@ module Key = struct | Some pk -> pk let list_map_filter_opt ~f l = - List.fold_left ~init:[] ~f:begin fun a e -> + ListLabels.fold_left ~init:[] ~f:begin fun a e -> match f e with | None -> a | Some r -> r :: a @@ -172,7 +133,7 @@ module Key = struct let nb_pks = List.length pks in if nb_pks = 0 || nb_pks > 1024 then None else - let pk = BA.create public_bytes in + let pk = Bigstring.create public_bytes in let pks = list_map_filter_opt ~f:begin fun k -> match neuterize ctx k with | None -> None @@ -186,70 +147,64 @@ module Key = struct | None -> invalid_arg "Key.combine_exn: sum of pks is invalid" | Some pk -> pk - external verify_sk : Context.t -> buffer -> bool = - "ec_seckey_verify" [@@noalloc] + external verify_sk : Context.t -> Bigstring.t -> bool = + "caml_secp256k1_ec_seckey_verify" [@@noalloc] - let read_sk_exn ctx ?(pos=0) buf = - let buflen = BA.length buf in - if pos < 0 || pos > buflen - secret_bytes then - invalid_arg "Key.read_sk: pos < 0 or pos + 32 > buflen" ; - let buf = BA.sub buf pos secret_bytes in + let read_sk_exn ctx buf = + let buflen = Bigstring.length buf in + if buflen < secret_bytes then + invalid_arg (Printf.sprintf "Key.read_sk: invalid buffer size %d" buflen) ; match verify_sk ctx buf with - | true -> - let t = BA.create secret_bytes in - BA.blit buf t ; - Sk buf - | false -> invalid_arg "Key.read_sk_exn: secret key is invalid" + | true -> Sk Bigstring.(copy (sub buf 0 secret_bytes)) + | false -> invalid_arg "Key.read_sk: secret key is invalid" - let read_sk ctx ?pos buf = - try Ok (read_sk_exn ctx ?pos buf) with + let read_sk ctx buf = + try Ok (read_sk_exn ctx buf) with | Invalid_argument msg -> Error msg - let read_pk_exn ctx ?(pos=0) inbuf = - let pklen = BA.length inbuf in - if pos < 0 || pos > pklen - 33 then - invalid_arg "Key.read_pk: pos < 0 or pos > buflen - 33" ; - let inbuf = BA.(sub inbuf pos (length inbuf)) in - if BA.(length inbuf < 33) then - invalid_arg "Key.read_pk: input must be at least 33 bytes long" ; - let outbuf = BA.create public_bytes in - if (pk_parse ctx outbuf inbuf) then Pk outbuf - else invalid_arg "Key.read_pk_exn: public key is invalid" + let read_pk_exn ctx buf = + let buflen = Bigstring.length buf in + if buflen < compressed_pk_bytes then + invalid_arg (Printf.sprintf "Key.read_pk: invalid buffer size %d" buflen) ; + let outbuf = Bigstring.create public_bytes in + if pk_parse ctx outbuf buf then + Pk outbuf + else + invalid_arg "Key.read_pk_exn: public key is invalid" - let read_pk ctx ?pos buf = - try Ok (read_pk_exn ctx ?pos buf) with + let read_pk ctx buf = + try Ok (read_pk_exn ctx buf) with | Invalid_argument msg -> Error msg let write : - type a. ?compress:bool -> Context.t -> ?pos:int -> buffer -> a t -> int = + type a. ?compress:bool -> Context.t -> ?pos:int -> Bigstring.t -> a t -> int = fun ?(compress=true) ctx ?(pos=0) buf -> function | Sk sk -> - let buflen = BA.length buf in + let buflen = Bigstring.length buf in if pos < 0 || pos > buflen - secret_bytes then invalid_arg "Key.write (secret): pos < 0 or pos + 32 > buflen" ; - let buf = BA.sub buf pos secret_bytes in - BA.blit sk buf ; + Bigstring.blit sk 0 buf pos secret_bytes ; secret_bytes | Pk pk -> - let buflen = BA.length buf in + let buflen = Bigstring.length buf in if pos < 0 - || (compress && pos > buflen - 33) - || (not compress && pos > buflen - 65) then + || (compress && pos > buflen - compressed_pk_bytes) + || (not compress && pos > buflen - uncompressed_pk_bytes) then invalid_arg (Printf.sprintf "Key.write (public): pos=%d, buflen=%d" pos buflen) ; let len = if compress then 33 else 65 in - let buf = BA.sub buf pos len in + let buf = Bigstring.sub buf pos len in pk_serialize ctx buf pk let to_bytes : - type a. ?compress:bool -> Context.t -> a t -> buffer = + type a. ?compress:bool -> Context.t -> a t -> Bigstring.t = fun ?(compress=true) ctx -> function | Sk _ as sk -> - let buf = BA.create secret_bytes in + let buf = Bigstring.create secret_bytes in let _ = write ~compress ctx buf sk in buf | Pk _ as pk -> let buf = - BA.create (1 + (if compress then secret_bytes else public_bytes)) in + Bigstring.create (1 + (if compress then secret_bytes else public_bytes)) in let _ = write ~compress ctx buf pk in buf end @@ -258,167 +213,199 @@ module Sign = struct type plain type recoverable type _ t = - | P : buffer -> plain t - | R : buffer -> recoverable t + | P : Bigstring.t -> plain t + | R : Bigstring.t -> recoverable t + + let buffer : type a. a t -> Bigstring.t = function + | P plain -> plain + | R recoverable -> recoverable let plain_bytes = 64 let recoverable_bytes = 65 let msg_bytes = 32 - type msg = buffer - - let msg_of_bytes ?(pos=0) buf = - try Some (BA.sub buf pos msg_bytes) with _ -> None - let msg_of_bytes_exn ?pos buf = - match msg_of_bytes ?pos buf with - | None -> invalid_arg "msg_of_bytes_exn" - | Some msg -> msg - let write_msg_exn ?(pos=0) buf msg = - let buflen = BA.length buf in - if pos < 0 || pos > buflen - msg_bytes then - invalid_arg "Sign.read_exn: pos < 0 or pos > buflen - 64" ; - BA.blit (BA.sub msg 0 msg_bytes) (BA.sub buf pos msg_bytes) ; - msg_bytes - - let write_msg ?pos buf msg = - try Ok (write_msg_exn ?pos buf msg) with - | Invalid_argument msg -> Error msg - - let msg_to_bytes msg = msg - let equal : type a. a t -> a t -> bool = fun a b -> match a, b with - | P a, P b -> BA.equal a b - | R a, R b -> BA.equal a b + | P a, P b -> Bigstring.equal a b + | R a, R b -> Bigstring.equal a b - external parse_compact : Context.t -> buffer -> buffer -> bool = - "ecdsa_signature_parse_compact" [@@noalloc] - external parse_der : Context.t -> buffer -> buffer -> bool = - "ecdsa_signature_parse_der" [@@noalloc] - external serialize_compact : Context.t -> buffer -> buffer -> unit = - "ecdsa_signature_serialize_compact" [@@noalloc] - external serialize_der : Context.t -> buffer -> buffer -> int = - "ecdsa_signature_serialize_der" [@@noalloc] - external parse_recoverable : Context.t -> buffer -> buffer -> int -> bool = - "ecdsa_recoverable_signature_parse_compact" [@@noalloc] - external serialize_recoverable : Context.t -> buffer -> buffer -> int = - "ecdsa_recoverable_signature_serialize_compact" [@@noalloc] + external parse_compact : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ecdsa_signature_parse_compact" [@@noalloc] + external parse_der : Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ecdsa_signature_parse_der" [@@noalloc] + external serialize_compact : Context.t -> Bigstring.t -> Bigstring.t -> unit = + "caml_secp256k1_ecdsa_signature_serialize_compact" [@@noalloc] + external serialize_der : Context.t -> Bigstring.t -> Bigstring.t -> int = + "caml_secp256k1_ecdsa_signature_serialize_der" [@@noalloc] + external parse_recoverable : Context.t -> Bigstring.t -> Bigstring.t -> int -> bool = + "caml_secp256k1_ecdsa_recoverable_signature_parse_compact" [@@noalloc] + external serialize_recoverable : Context.t -> Bigstring.t -> Bigstring.t -> int = + "caml_secp256k1_ecdsa_recoverable_signature_serialize_compact" [@@noalloc] - let read_exn ctx ?(pos=0) buf = - let buflen = BA.length buf in - if pos < 0 || pos > buflen - plain_bytes then - invalid_arg "Sign.read_exn: pos < 0 or pos > buflen - 64" ; - let signature = BA.create plain_bytes in - if parse_compact ctx signature (BA.sub buf pos plain_bytes) then + let read_exn ctx buf = + let buflen = Bigstring.length buf in + if buflen < plain_bytes then + invalid_arg (Printf.sprintf "Sign.read: invalid buffer size %d" buflen) ; + let signature = Bigstring.create plain_bytes in + if parse_compact ctx signature buf then P signature - else invalid_arg "Sign.read_exn: signature could not be parsed" + else + invalid_arg "Sign.read: signature could not be parsed" - let read ctx ?pos buf = - try Ok (read_exn ctx ?pos buf) with - | Invalid_argument msg -> Error msg + let read ctx buf = + try Ok (read_exn ctx buf) with + Invalid_argument msg -> Error msg - let read_der_exn ctx ?(pos=0) buf = - let buflen = BA.length buf in - if pos < 0 || pos > buflen - plain_bytes then - invalid_arg "Sign.read_der: pos < 0 or pos > buflen - 72" ; - let signature = BA.create plain_bytes in - if parse_der ctx signature BA.(sub buf pos (length buf)) then + let read_der_exn ctx buf = + let signature = Bigstring.create plain_bytes in + if parse_der ctx signature buf then P signature - else invalid_arg "Sign.read_der_exn: signature could not be parsed" + else + invalid_arg "Sign.read_der: signature could not be parsed" - let read_der ctx ?pos buf = - try Ok (read_der_exn ctx ?pos buf) with - | Invalid_argument msg -> Error msg + let read_der ctx buf = + try Ok (read_der_exn ctx buf) with + Invalid_argument msg -> Error msg - let read_recoverable_exn ctx ~recid ?(pos=0) buf = - let buflen = BA.length buf in - if pos < 0 || pos > buflen - plain_bytes then - invalid_arg "Sign.read_recoverable_exn: pos < 0 or pos > buflen - 64" ; - let signature = BA.create recoverable_bytes in - if parse_recoverable ctx signature (BA.sub buf pos plain_bytes) recid then (R signature) - else invalid_arg "Sign.read_recoverable_exn: signature could not be parsed" + let read_recoverable_exn ctx buf = + let buflen = Bigstring.length buf in + if buflen < recoverable_bytes then + invalid_arg (Printf.sprintf "Sign.read_recoverable: invalid buffer size %d" buflen) ; + let signature = Bigstring.create recoverable_bytes in + let recid = int_of_char (Bigstring.get buf 64) in + if parse_recoverable ctx signature buf recid then + R signature + else + invalid_arg "Sign.read_recoverable: signature could not be parsed" - let read_recoverable ctx ~recid ?pos buf = - try Ok (read_recoverable_exn ctx ~recid ?pos buf) with + let read_recoverable ctx buf = + try Ok (read_recoverable_exn ctx buf) with | Invalid_argument msg -> Error msg let write_exn : - type a. ?der:bool -> Context.t -> ?pos:int -> buffer -> a t -> int = - fun ?(der=false) ctx ?(pos=0) buf -> function + type a. ?der:bool -> Context.t -> Bigstring.t -> a t -> int = + fun ?(der=false) ctx buf -> function | P signature -> - let buf = BA.(sub buf pos (length buf)) in - if der then serialize_der ctx buf signature - else (serialize_compact ctx buf signature ; plain_bytes) + let buflen = Bigstring.length buf in + if not der then begin + if buflen < plain_bytes then + invalid_arg (Printf.sprintf "Sign.write: buffer length too small (%d)" buflen) ; + serialize_compact ctx buf signature ; + plain_bytes + end + else begin + match serialize_der ctx buf signature with + | 0 -> invalid_arg "Sign.write_exn: buffer too small to \ + contain a DER signature" + | len -> len + end | R signature -> - let buflen = BA.length buf in - if pos < 0 || pos > buflen - plain_bytes then - invalid_arg "write: pos < 0 or pos > buflen - 64" ; - ignore (serialize_recoverable ctx (BA.sub buf pos plain_bytes) signature) ; - plain_bytes + let buflen = Bigstring.length buf in + if buflen < recoverable_bytes then + invalid_arg (Printf.sprintf "Sign.write: buffer length too small (%d)" buflen) ; + let recid = serialize_recoverable ctx buf signature in + Bigstring.set buf 64 (char_of_int recid) ; + recoverable_bytes - let write ?der ctx ?pos buf signature = - try Ok (write_exn ?der ctx ?pos buf signature) with - | Invalid_argument msg -> Error msg + let write ?der ctx buf signature = + try Ok (write_exn ?der ctx buf signature) with + Invalid_argument msg -> Error msg - let to_bytes ?der ctx signature = - let buf = BA.create 72 in - let nb_written = write_exn ?der ctx buf signature in - BA.sub buf 0 nb_written + let to_bytes : + type a. ?der:bool -> Context.t -> a t -> Bigstring.t = + fun ?(der=false) ctx -> function + | P _ as signature -> + if der then begin + let buf = Bigstring.create 72 in + let nb_written = write_exn ~der ctx buf signature in + Bigstring.sub buf 0 nb_written + end + else + let buf = Bigstring.create plain_bytes in + let _nb_written = write_exn ~der ctx buf signature in + buf + | R _ as signature -> + let buf = Bigstring.create recoverable_bytes in + let _nb_written = write_exn ctx buf signature in + buf - let to_bytes_recid ctx (R signature) = - let buf = BA.create plain_bytes in - let recid = serialize_recoverable ctx buf signature in - buf, recid + external normalize : + Context.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ecdsa_signature_normalize" [@@noalloc] - external sign : Context.t -> buffer -> buffer -> buffer -> bool = - "ecdsa_sign" [@@noalloc] - external verify : Context.t -> buffer -> buffer -> buffer -> bool = - "ecdsa_verify" [@@noalloc] + let normalize ctx (P signature) = + let normalized_sig = Bigstring.create plain_bytes in + if normalize ctx normalized_sig signature then + Some (P normalized_sig) else None - let write_sign_exn ctx ~sk ~msg ?(pos=0) buf = - let buflen = BA.length buf in - if pos < 0 || pos > buflen - plain_bytes then - invalid_arg "Sign.write_sign: outpos < 0 or outpos > outbuf - 64" ; - if sign ctx (BA.sub buf pos plain_bytes) (Key.to_buffer sk) msg then plain_bytes - else invalid_arg - "Sign.write_sign: the nonce generation function failed, or the private key was invalid" + (* [sign ctx signature msg sk] *) + external sign : + Context.t -> Bigstring.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ecdsa_sign" [@@noalloc] - let write_sign ctx ~sk ~msg ?pos buf = - try Ok (write_sign_exn ctx ~sk ~msg ?pos buf) with - | Invalid_argument msg -> Error msg + (* [verify ctx pk msg signature] *) + external verify : + Context.t -> Bigstring.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ecdsa_verify" [@@noalloc] - let sign ctx ~sk ~msg = - let signature = BA.create plain_bytes in - match write_sign ctx ~sk ~msg signature with - | Error msg -> Error msg - | Ok _nb_written -> Ok (P signature) + let check_msglen msg = + let msglen = Bigstring.length msg in + if msglen < msg_bytes + then invalid_arg + (Printf.sprintf "message is too small (%d < %d)" msglen msg_bytes) - let sign_exn ctx ~sk ~msg = - match sign ctx ~sk ~msg with - | Error msg -> invalid_arg msg - | Ok signature -> signature + let sign_exn ctx buf ~sk ~msg = + check_msglen msg ; + let buflen = Bigstring.length buf in + if buflen < plain_bytes then + invalid_arg (Printf.sprintf "Sign.write_sign: buffer length too \ + small (%d)" buflen) ; + match sign ctx buf (Key.buffer sk) msg with + | true -> () + | false -> invalid_arg "Sign.write_sign: the nonce generation \ + function failed, or the private key was \ + invalid" - external sign_recoverable : Context.t -> buffer -> buffer -> buffer -> bool = - "ecdsa_sign_recoverable" [@@noalloc] + let write_sign_exn ctx buf ~sk ~msg = + let signature = Bigstring.create plain_bytes in + sign_exn ctx signature ~sk ~msg ; + write_exn ctx buf (P signature) - let write_sign_recoverable_exn ctx ~sk ~msg ?(pos=0) buf = - let buflen = BA.length buf in - if pos < 0 || pos > buflen - recoverable_bytes then - invalid_arg "Sign.write_sign_recoverable_exn: \ - outpos < 0 or outpos > outbuflen - 65" ; - if sign_recoverable ctx - (BA.sub buf pos recoverable_bytes) - (Key.to_buffer sk) msg then recoverable_bytes - else invalid_arg - "Sign.write_sign_recoverable_exn: \ - the nonce generation function failed, or the private key was invalid" + let write_sign ctx buf ~sk ~msg = + try Ok (write_sign_exn ctx ~sk ~msg buf) + with Invalid_argument msg -> Error msg - let write_sign_recoverable ctx ~sk ~msg ?pos buf = - try Ok (write_sign_recoverable_exn ctx ~sk ~msg ?pos buf) with - | Invalid_argument msg -> Error msg + let sign_exn ctx ~sk msg = + let signature = Bigstring.create plain_bytes in + sign_exn ctx signature ~sk ~msg ; + P signature + + let sign ctx ~sk msg = + try Ok (sign_exn ctx ~sk msg) + with Invalid_argument msg -> Error msg + + external sign_recoverable : + Context.t -> Bigstring.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ecdsa_sign_recoverable" [@@noalloc] + + let write_sign_recoverable_exn ctx ~sk ~msg buf = + check_msglen msg ; + let buflen = Bigstring.length buf in + if buflen < recoverable_bytes then + invalid_arg (Printf.sprintf "Sign.write_sign_recoverable: buffer \ + length too small (%d)" buflen) ; + if sign_recoverable ctx buf (Key.buffer sk) msg then + recoverable_bytes + else invalid_arg "Sign.write_sign_recoverable_exn: the nonce \ + generation function failed, or the private key \ + was invalid" + + let write_sign_recoverable ctx ~sk ~msg buf = + try Ok (write_sign_recoverable_exn ctx ~sk ~msg buf) + with Invalid_argument msg -> Error msg let sign_recoverable ctx ~sk msg = - let signature = BA.create recoverable_bytes in + let signature = Bigstring.create recoverable_bytes in match write_sign_recoverable ctx ~sk ~msg signature with | Error error -> Error error | Ok _nb_written -> Ok (R signature) @@ -428,42 +415,44 @@ module Sign = struct | Error msg -> invalid_arg msg | Ok signature -> signature - external to_plain : Context.t -> buffer -> buffer -> unit = - "ecdsa_recoverable_signature_convert" [@@noalloc] + external to_plain : Context.t -> Bigstring.t -> Bigstring.t -> unit = + "caml_secp256k1_ecdsa_recoverable_signature_convert" [@@noalloc] - let to_plain ctx (R recoverable) = - let plain = BA.create plain_bytes in - to_plain ctx plain recoverable ; - P plain + let to_plain : type a. Context.t -> a t -> plain t = fun ctx -> function + | P _ as signature -> signature + | R recoverable -> + let plain = Bigstring.create plain_bytes in + to_plain ctx plain recoverable ; + P plain - let verify_plain_exn ctx ~pk ?(pos=0) msg signature = - let msglen = BA.length msg in - if pos < 0 || pos > msglen - 32 then - invalid_arg "Sign.verify: msg must be at least 32 bytes long" ; - verify ctx (Key.to_buffer pk) (BA.sub msg pos 32) signature + let verify_plain_exn ctx ~pk msg signature = + check_msglen msg ; + let siglen = Bigstring.length signature in + if siglen < plain_bytes then + invalid_arg (Printf.sprintf "verify: signature too short (%d < %d)" + siglen plain_bytes) ; + verify ctx (Key.buffer pk) msg signature - let verify_exn : - type a. Context.t -> pk:Key.public Key.t -> msg:msg -> signature:a t -> bool = - fun ctx ~pk ~msg ~signature -> match signature with - | P signature -> verify_plain_exn ctx ~pk msg signature - | R _ as r -> - let P signature = to_plain ctx r in - verify_plain_exn ctx ~pk msg signature + let verify_exn ctx ~pk ~msg ~signature = + let P signature = to_plain ctx signature in + verify_plain_exn ctx ~pk msg signature let verify ctx ~pk ~msg ~signature = try Ok (verify_exn ctx ~pk ~msg ~signature) with | Invalid_argument msg -> Error msg - external recover : Context.t -> buffer -> buffer -> buffer -> bool = - "ecdsa_recover" [@@noalloc] + external recover : + Context.t -> Bigstring.t -> Bigstring.t -> Bigstring.t -> bool = + "caml_secp256k1_ecdsa_recover" [@@noalloc] - let recover_exn ctx ~signature:(R signature) ~msg = - let pk = BA.create Key.public_bytes in + let recover_exn ctx ~signature:(R signature) msg = + check_msglen msg ; + let pk = Bigstring.create Key.public_bytes in if recover ctx pk signature msg then Key.Pk pk else invalid_arg "Sign.recover: pk could not be recovered" - let recover ctx ~signature ~msg = - try Ok (recover_exn ctx ~signature ~msg) with - | Invalid_argument msg -> Error msg + let recover ctx ~signature msg = + try Ok (recover_exn ctx ~signature msg) with + Invalid_argument msg -> Error msg end diff --git a/vendors/ocaml-secp256k1/src/external.mli b/vendors/ocaml-secp256k1/src/external.mli index 348ff75b5..e4adc883c 100644 --- a/vendors/ocaml-secp256k1/src/external.mli +++ b/vendors/ocaml-secp256k1/src/external.mli @@ -1,11 +1,4 @@ -type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t - module Context : sig - type flag = - | Verify - | Sign - (** which parts of the context to initialize. *) - type t (** Opaque data structure that holds context information (precomputed tables etc.). @@ -24,13 +17,13 @@ module Context : sig which case you do not need any locking for the other calls), or use a read-write lock. *) - val create : flag list -> t - (** Create a secp256k1 context object. *) + val create : ?sign:bool -> ?verify:bool -> unit -> t + (** [create ?sign ?bool ()] is a freshly allocated [t]. *) val clone : t -> t - (** Copies a secp256k1 context object. *) + (** [clone t] is a copy of [t]. *) - val randomize : t -> buffer -> bool + val randomize : t -> Bigstring.t -> bool (** While secp256k1 code is written to be constant-time no matter what secret values are, it's possible that a future compiler may output code which isn't, and also that the CPU may not emit the @@ -52,20 +45,39 @@ end module Key : sig type secret type public - type _ t = private - | Sk : buffer -> secret t - | Pk : buffer -> public t + type _ t + + val buffer : _ t -> Bigstring.t + (** [buffer k] is the underlying buffer of [k]. DO NOT MODIFY. *) + + val secret_bytes : int + (** Length of a secret key in memory: 32 bytes *) + + val public_bytes : int + (** Length of a public key in memory: 64 bytes *) + + val compressed_pk_bytes : int + (** Length of the compressed serialization of a public key: 33 bytes *) + + val uncompressed_pk_bytes : int + (** Length of the uncompressed serialization of a public key: 65 bytes *) + + val bytes : _ t -> int + (** [bytes k] is the length of [k] in memory (the length of the + underlying [Bigstring.t]). *) + + val serialized_bytes : ?compressed:bool -> _ t -> int + (** [serialized_bytes ?compressed k] is the length of the + serialization (compressed) of [k].*) - val to_buffer : _ t -> buffer - val length : _ t -> int val equal : 'a t -> 'a t -> bool val copy : 'a t -> 'a t (** {2 Aritmetic operations } *) val negate : Context.t -> 'a t -> 'a t - val add_tweak : Context.t -> 'a t -> ?pos:int -> buffer -> 'a t - val mul_tweak : Context.t -> 'a t -> ?pos:int -> buffer -> 'a t + val add_tweak : Context.t -> 'a t -> Bigstring.t -> 'a t + val mul_tweak : Context.t -> 'a t -> Bigstring.t -> 'a t val neuterize : Context.t -> _ t -> public t option val neuterize_exn : Context.t -> _ t -> public t val combine : Context.t -> _ t list -> public t option @@ -73,74 +85,122 @@ module Key : sig (** {2 Input/Output} *) - val read_sk : Context.t -> ?pos:int -> buffer -> (secret t, string) result - val read_sk_exn : Context.t -> ?pos:int -> buffer -> secret t - val read_pk : Context.t -> ?pos:int -> buffer -> (public t, string) result - val read_pk_exn : Context.t -> ?pos:int -> buffer -> public t - val write : ?compress:bool -> Context.t -> ?pos:int -> buffer -> _ t -> int - val to_bytes : ?compress:bool -> Context.t -> _ t -> buffer + val read_sk : Context.t -> Bigstring.t -> (secret t, string) result + val read_sk_exn : Context.t -> Bigstring.t -> secret t + val read_pk : Context.t -> Bigstring.t -> (public t, string) result + val read_pk_exn : Context.t -> Bigstring.t -> public t + val write : ?compress:bool -> Context.t -> ?pos:int -> Bigstring.t -> _ t -> int + val to_bytes : ?compress:bool -> Context.t -> _ t -> Bigstring.t end module Sign : sig - (** {2 Message} *) - - type msg - - val msg_of_bytes : ?pos:int -> buffer -> msg option - val msg_of_bytes_exn : ?pos:int -> buffer -> msg - val write_msg_exn : ?pos:int -> buffer -> msg -> int - val write_msg : ?pos:int -> buffer -> msg -> (int, string) result - val msg_to_bytes : msg -> buffer - (** {2 Signature} *) type plain type recoverable - type _ t = private - | P : buffer -> plain t - | R : buffer -> recoverable t + type _ t + + val buffer : _ t -> Bigstring.t + (** [buffer signature] is the underlying buffer of [signature]. DO + NOT MODIFY. *) + + val plain_bytes : int + (** 64 bytes *) + + val recoverable_bytes : int + (** 65 bytes *) + + val msg_bytes : int + (** 32 bytes *) val equal : 'a t -> 'a t -> bool - val to_plain : Context.t -> recoverable t -> plain t + val to_plain : Context.t -> _ t -> plain t (** {3 Input/Output} *) - val read : Context.t -> ?pos:int -> buffer -> (plain t, string) result - val read_exn : Context.t -> ?pos:int -> buffer -> plain t - val read_der : Context.t -> ?pos:int -> buffer -> (plain t, string) result - val read_der_exn : Context.t -> ?pos:int -> buffer -> plain t - val read_recoverable : Context.t -> recid:int -> ?pos:int -> buffer -> (recoverable t, string) result - val read_recoverable_exn : Context.t -> recid:int -> ?pos:int -> buffer -> recoverable t + val read : Context.t -> Bigstring.t -> (plain t, string) result + val read_exn : Context.t -> Bigstring.t -> plain t + val read_der : Context.t -> Bigstring.t -> (plain t, string) result + val read_der_exn : Context.t -> Bigstring.t -> plain t - val write_exn : ?der:bool -> Context.t -> ?pos:int -> buffer -> _ t -> int - val write : ?der:bool -> Context.t -> ?pos:int -> buffer -> _ t -> (int, string) result - val to_bytes : ?der:bool -> Context.t -> _ t -> buffer - val to_bytes_recid : Context.t -> recoverable t -> buffer * int + val read_recoverable : + Context.t -> Bigstring.t -> (recoverable t, string) result + (** [read_recoverable_exn ctx buf] reads a recoverable signature in + [buf] if everything goes well or return an error otherwise. *) + + val read_recoverable_exn : Context.t -> Bigstring.t -> recoverable t + (** [read_recoverable_exn ctx buf] reads a recoverable signature in + [buf]. + + @raises [Invalid_argument] if [buf] is less than 65 bytes long + or [buf] does not contain a valid recoverable signature. *) + + val write_exn : ?der:bool -> Context.t -> Bigstring.t -> _ t -> int + + val write : ?der:bool -> Context.t -> Bigstring.t -> _ t -> (int, string) result + + val to_bytes : ?der:bool -> Context.t -> _ t -> Bigstring.t + (** [to_bytes ?der ctx signature] writes the serialization of + [signature] in a freshly allocated [Bigstring.t], which is then + returned. *) (** {3 Sign} *) + val normalize : + Context.t -> plain t -> plain t option + (** [normalize ctx sig] is the normalized lower-S form of [Some + normalized_sig] if [sig] was not already in this form, or [None] + otherwise. *) + (** {4 Creation} *) - val sign : Context.t -> sk:Key.secret Key.t -> msg:msg -> (plain t, string) result - val sign_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> plain t - val sign_recoverable : Context.t -> sk:Key.secret Key.t -> msg -> (recoverable t, string) result - val sign_recoverable_exn : Context.t -> sk:Key.secret Key.t -> msg -> recoverable t + val sign : Context.t -> sk:Key.secret Key.t -> Bigstring.t -> (plain + t, string) result - (** {4 Direct write in buffers} *) + val sign_exn : Context.t -> sk:Key.secret Key.t -> Bigstring.t -> + plain t - val write_sign : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> (int, string) result - val write_sign_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> int - val write_sign_recoverable : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> (int, string) result - val write_sign_recoverable_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> int + val sign_recoverable : Context.t -> sk:Key.secret Key.t -> + Bigstring.t -> (recoverable t, string) result + + val sign_recoverable_exn : Context.t -> sk:Key.secret Key.t -> + Bigstring.t -> recoverable t + + (** {4 Direct write} *) + + val write_sign : Context.t -> Bigstring.t -> sk:Key.secret Key.t -> + msg:Bigstring.t -> (int, string) result (** [write_sign ctx buf ~sk + ~msg] writes signs [msg] with [sk] and writes the signature to + [buf] at [?pos]. It returns the number of bytes written (64) on + success, or ar error message otherwise. *) + + val write_sign_exn : Context.t -> Bigstring.t -> sk:Key.secret Key.t + -> msg:Bigstring.t -> int (** [write_sign_exn ctx buf ~sk ~msg] + writes signs [msg] with [sk] and writes the signature to [buf] at + [?pos]. It returns the number of bytes written (64). + + @raise [Invalid_argument] if [buf] is not long enough to contain + a signature or signing has failed. *) + + val write_sign_recoverable : Context.t -> sk:Key.secret Key.t -> + msg:Bigstring.t -> Bigstring.t -> (int, string) result + + val write_sign_recoverable_exn : Context.t -> sk:Key.secret Key.t -> + msg:Bigstring.t -> Bigstring.t -> int (** {4 Verification} *) - val verify_exn : Context.t -> pk:Key.public Key.t -> msg:msg -> signature:_ t -> bool - val verify : Context.t -> pk:Key.public Key.t -> msg:msg -> signature:_ t -> (bool, string) result + val verify_exn : Context.t -> pk:Key.public Key.t -> msg:Bigstring.t + -> signature:_ t -> bool + + val verify : Context.t -> pk:Key.public Key.t -> msg:Bigstring.t -> + signature:_ t -> (bool, string) result (** {4 Recovery} *) - val recover_exn : Context.t -> signature:recoverable t -> msg:msg -> Key.public Key.t - val recover : Context.t -> signature:recoverable t -> msg:msg -> (Key.public Key.t, string) result -end + val recover_exn : Context.t -> signature:recoverable t -> + Bigstring.t -> Key.public Key.t + + val recover : Context.t -> signature:recoverable t -> Bigstring.t -> + (Key.public Key.t, string) result end diff --git a/vendors/ocaml-secp256k1/src/jbuild b/vendors/ocaml-secp256k1/src/jbuild index ef1ade958..9c00fa8b5 100644 --- a/vendors/ocaml-secp256k1/src/jbuild +++ b/vendors/ocaml-secp256k1/src/jbuild @@ -4,7 +4,7 @@ ((name libsecp256k1) (public_name secp256k1) (modules (internal external)) - (libraries (cstruct)) + (libraries (bigstring cstruct)) (c_names (secp256k1 secp256k1_wrap)) (c_flags (:include c_flags.sexp)) diff --git a/vendors/ocaml-secp256k1/src/secp256k1_wrap.c b/vendors/ocaml-secp256k1/src/secp256k1_wrap.c index 5a6de4534..477eca19a 100644 --- a/vendors/ocaml-secp256k1/src/secp256k1_wrap.c +++ b/vendors/ocaml-secp256k1/src/secp256k1_wrap.c @@ -1,18 +1,16 @@ -#include - -#include "secp256k1.h" -#include "secp256k1_recovery.h" - #include #include #include #include #include +#include "secp256k1.h" +#include "secp256k1_recovery.h" + /* Accessing the secp256k1_context * part of an OCaml custom block */ #define Context_val(v) (*((secp256k1_context **) Data_custom_val(v))) -void context_destroy(value ctx) { +static void context_destroy(value ctx) { secp256k1_context_destroy (Context_val(ctx)); } @@ -32,68 +30,60 @@ static value alloc_context (secp256k1_context *ctx) { return ml_ctx; } -CAMLprim value context_flags (value buf) { - uint16_t *a = Caml_ba_data_val(buf); - a[0] = SECP256K1_CONTEXT_NONE; - a[1] = SECP256K1_CONTEXT_VERIFY; - a[2] = SECP256K1_CONTEXT_SIGN; - return Val_int(3 * sizeof(uint16_t)); -} - -CAMLprim value context_create (value flags) { +CAMLprim value caml_secp256k1_context_create (value flags) { CAMLparam1(flags); secp256k1_context *ctx = secp256k1_context_create (Int_val(flags)); if (!ctx) caml_failwith("context_create"); CAMLreturn(alloc_context(ctx)); } -CAMLprim value context_randomize (value ctx, value seed) { +CAMLprim value caml_secp256k1_context_randomize (value ctx, value seed) { return Val_bool(secp256k1_context_randomize(Context_val(ctx), - String_val(seed))); + Caml_ba_data_val(seed))); } -CAMLprim value context_clone (value ctx) { +CAMLprim value caml_secp256k1_context_clone (value ctx) { CAMLparam1(ctx); secp256k1_context *new = secp256k1_context_clone (Context_val(ctx)); if (!new) caml_failwith("context_clone"); CAMLreturn(alloc_context(new)); } -CAMLprim value ec_seckey_verify (value ctx, value sk) { - return Val_bool(secp256k1_ec_seckey_verify(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_seckey_verify (value ctx, value sk) { + return Val_bool(secp256k1_ec_seckey_verify(Context_val(ctx), Caml_ba_data_val(sk))); } -CAMLprim value ec_privkey_negate(value ctx, value sk) { - int ret = secp256k1_ec_privkey_negate(Context_val (ctx), +CAMLprim value caml_secp256k1_ec_privkey_negate(value ctx, value sk) { + int ret = secp256k1_ec_privkey_negate(Context_val(ctx), Caml_ba_data_val(sk)); return Val_unit; } -CAMLprim value ec_privkey_tweak_add(value ctx, value sk, value tweak) { - return Val_bool(secp256k1_ec_privkey_tweak_add(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_privkey_tweak_add(value ctx, value sk, value tweak) { + return Val_bool(secp256k1_ec_privkey_tweak_add(Context_val(ctx), Caml_ba_data_val(sk), Caml_ba_data_val(tweak))); } -CAMLprim value ec_privkey_tweak_mul(value ctx, value sk, value tweak) { - return Val_bool(secp256k1_ec_privkey_tweak_mul(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_privkey_tweak_mul(value ctx, value sk, value tweak) { + return Val_bool(secp256k1_ec_privkey_tweak_mul(Context_val(ctx), Caml_ba_data_val(sk), Caml_ba_data_val(tweak))); } -CAMLprim value ec_pubkey_create (value ctx, value buf, value sk) { - return Val_bool(secp256k1_ec_pubkey_create (Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_pubkey_create (value ctx, value buf, value sk) { + return Val_bool(secp256k1_ec_pubkey_create (Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(sk))); } -CAMLprim value ec_pubkey_serialize (value ctx, value buf, value pk) { +CAMLprim value caml_secp256k1_ec_pubkey_serialize (value ctx, value buf, value pk) { size_t size = Caml_ba_array_val(buf)->dim[0]; unsigned int flags = size == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED; - secp256k1_ec_pubkey_serialize(Caml_ba_data_val(ctx), + secp256k1_ec_pubkey_serialize(Context_val(ctx), Caml_ba_data_val(buf), &size, Caml_ba_data_val(pk), @@ -102,32 +92,32 @@ CAMLprim value ec_pubkey_serialize (value ctx, value buf, value pk) { return Val_int(size); } -CAMLprim value ec_pubkey_parse(value ctx, value buf, value pk) { - return Val_bool(secp256k1_ec_pubkey_parse(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_pubkey_parse(value ctx, value buf, value pk) { + return Val_bool(secp256k1_ec_pubkey_parse(Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(pk), Caml_ba_array_val(pk)->dim[0])); } -CAMLprim value ec_pubkey_negate(value ctx, value pk) { - int ret = secp256k1_ec_pubkey_negate(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_pubkey_negate(value ctx, value pk) { + int ret = secp256k1_ec_pubkey_negate(Context_val(ctx), Caml_ba_data_val(pk)); return Val_unit; } -CAMLprim value ec_pubkey_tweak_add(value ctx, value pk, value tweak) { - return Val_bool(secp256k1_ec_pubkey_tweak_add(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_pubkey_tweak_add(value ctx, value pk, value tweak) { + return Val_bool(secp256k1_ec_pubkey_tweak_add(Context_val(ctx), Caml_ba_data_val(pk), Caml_ba_data_val(tweak))); } -CAMLprim value ec_pubkey_tweak_mul(value ctx, value pk, value tweak) { - return Val_bool(secp256k1_ec_pubkey_tweak_mul(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ec_pubkey_tweak_mul(value ctx, value pk, value tweak) { + return Val_bool(secp256k1_ec_pubkey_tweak_mul(Context_val(ctx), Caml_ba_data_val(pk), Caml_ba_data_val(tweak))); } -CAMLprim value ec_pubkey_combine(value ctx, value out, value pks) { +CAMLprim value caml_secp256k1_ec_pubkey_combine(value ctx, value out, value pks) { int size = 0; const secp256k1_pubkey* cpks[1024] = {0}; @@ -137,44 +127,50 @@ CAMLprim value ec_pubkey_combine(value ctx, value out, value pks) { pks = Field(pks, 1); } - return Val_int(secp256k1_ec_pubkey_combine(Caml_ba_data_val(ctx), + return Val_int(secp256k1_ec_pubkey_combine(Context_val(ctx), Caml_ba_data_val(out), cpks, size)); } -CAMLprim value ecdsa_signature_parse_compact (value ctx, value buf, value sig) { - return Val_bool(secp256k1_ecdsa_signature_parse_compact (Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_signature_parse_compact (value ctx, value buf, value sig) { + return Val_bool(secp256k1_ecdsa_signature_parse_compact (Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(sig))); } -CAMLprim value ecdsa_signature_parse_der (value ctx, value buf, value sig) { - return Val_bool(secp256k1_ecdsa_signature_parse_der (Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_signature_parse_der (value ctx, value buf, value sig) { + return Val_bool(secp256k1_ecdsa_signature_parse_der (Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(sig), Caml_ba_array_val(sig)->dim[0])); } -CAMLprim value ecdsa_verify (value ctx, value pubkey, value msg, value signature) { - return Val_bool(secp256k1_ecdsa_verify (Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_signature_normalize(value ctx, value buf, value sig) { + return Val_bool(secp256k1_ecdsa_signature_normalize (Context_val(ctx), + Caml_ba_data_val(buf), + Caml_ba_data_val(sig))); +} + +CAMLprim value caml_secp256k1_ecdsa_verify (value ctx, value pubkey, value msg, value signature) { + return Val_bool(secp256k1_ecdsa_verify (Context_val(ctx), Caml_ba_data_val(signature), Caml_ba_data_val(msg), Caml_ba_data_val(pubkey))); } -CAMLprim value ecdsa_sign (value ctx, value buf, value seckey, value msg) { - return Val_bool(secp256k1_ecdsa_sign (Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_sign (value ctx, value buf, value seckey, value msg) { + return Val_bool(secp256k1_ecdsa_sign (Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(msg), Caml_ba_data_val(seckey), NULL, NULL)); } -CAMLprim value ecdsa_signature_serialize_der(value ctx, value buf, value signature) { +CAMLprim value caml_secp256k1_ecdsa_signature_serialize_der(value ctx, value buf, value signature) { size_t size = Caml_ba_array_val(buf)->dim[0]; - int ret = secp256k1_ecdsa_signature_serialize_der(Caml_ba_data_val(ctx), + int ret = secp256k1_ecdsa_signature_serialize_der(Context_val(ctx), Caml_ba_data_val(buf), &size, Caml_ba_data_val(signature)); @@ -182,46 +178,46 @@ CAMLprim value ecdsa_signature_serialize_der(value ctx, value buf, value signatu return (ret == 0 ? Val_int(ret) : Val_int(size)); } -CAMLprim value ecdsa_signature_serialize_compact(value ctx, value buf, value signature) { - secp256k1_ecdsa_signature_serialize_compact(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_signature_serialize_compact(value ctx, value buf, value signature) { + secp256k1_ecdsa_signature_serialize_compact(Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(signature)); return Val_unit; } -CAMLprim value ecdsa_recoverable_signature_parse_compact (value ctx, value buf, value signature, value recid) { - return Val_bool(secp256k1_ecdsa_recoverable_signature_parse_compact (Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_recoverable_signature_parse_compact (value ctx, value buf, value signature, value recid) { + return Val_bool(secp256k1_ecdsa_recoverable_signature_parse_compact (Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(signature), Int_val(recid))); } -CAMLprim value ecdsa_sign_recoverable (value ctx, value buf, value seckey, value msg) { - return Val_bool(secp256k1_ecdsa_sign_recoverable (Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_sign_recoverable (value ctx, value buf, value seckey, value msg) { + return Val_bool(secp256k1_ecdsa_sign_recoverable (Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(msg), Caml_ba_data_val(seckey), NULL, NULL)); } -CAMLprim value ecdsa_recoverable_signature_serialize_compact(value ctx, value buf, value signature) { +CAMLprim value caml_secp256k1_ecdsa_recoverable_signature_serialize_compact(value ctx, value buf, value signature) { int recid; - secp256k1_ecdsa_recoverable_signature_serialize_compact(Caml_ba_data_val(ctx), + secp256k1_ecdsa_recoverable_signature_serialize_compact(Context_val(ctx), Caml_ba_data_val(buf), &recid, Caml_ba_data_val(signature)); return Val_int(recid); } -CAMLprim value ecdsa_recoverable_signature_convert(value ctx, value buf, value signature) { - secp256k1_ecdsa_recoverable_signature_convert(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_recoverable_signature_convert(value ctx, value buf, value signature) { + secp256k1_ecdsa_recoverable_signature_convert(Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(signature)); return Val_unit; } -CAMLprim value ecdsa_recover(value ctx, value buf, value signature, value msg) { - return Val_bool(secp256k1_ecdsa_recover(Caml_ba_data_val(ctx), +CAMLprim value caml_secp256k1_ecdsa_recover(value ctx, value buf, value signature, value msg) { + return Val_bool(secp256k1_ecdsa_recover(Context_val(ctx), Caml_ba_data_val(buf), Caml_ba_data_val(signature), Caml_ba_data_val(msg))); diff --git a/vendors/ocaml-secp256k1/test/jbuild b/vendors/ocaml-secp256k1/test/jbuild index 36e0f7647..df0c30c92 100644 --- a/vendors/ocaml-secp256k1/test/jbuild +++ b/vendors/ocaml-secp256k1/test/jbuild @@ -5,6 +5,10 @@ (libraries (hex libsecp256k1 alcotest)))) (alias - ((name runtest) + ((name runtest-secp256k1) (deps (test.exe)) (action (run ${<})))) + +(alias + ((name runtest) + (deps ((alias runtest-secp256k1))))) diff --git a/vendors/ocaml-secp256k1/test/test.ml b/vendors/ocaml-secp256k1/test/test.ml index a8f60c58c..f95044bd3 100644 --- a/vendors/ocaml-secp256k1/test/test.ml +++ b/vendors/ocaml-secp256k1/test/test.ml @@ -1,13 +1,11 @@ open Libsecp256k1 -let assert_equal a b = assert (a = b) - module Num = struct open Internal open Num let basic () = let z = zero () in - assert_equal true (is_zero z) + Alcotest.(check bool "Num.is_zero" true (is_zero z)) let runtest = [ "basic", `Quick, basic ; @@ -19,12 +17,12 @@ module Scalar = struct open Scalar let basic () = let z = zero () in - assert_equal true (is_zero z) ; + Alcotest.(check bool "Scalar.is_zero" true (is_zero z)) ; (* set_int z 1 ; *) let z = const ~d0:1L () in - assert_equal false (is_zero z) ; - assert_equal false (is_even z) ; - assert_equal true (is_one z) + Alcotest.(check bool "Scalar.is_zero" false (is_zero z)) ; + Alcotest.(check bool "Scalar.is_even" false (is_even z)) ; + Alcotest.(check bool "Scalar.is_one" true (is_one z)) let runtest = [ "basic", `Quick, basic ; @@ -34,10 +32,9 @@ end module External = struct open External let buffer_of_hex s = - let { Cstruct.buffer; off = _ ; len = _ } = Hex.to_cstruct (`Hex s) in - buffer + Cstruct.to_bigarray (Hex.to_cstruct (`Hex s)) - let ctx = Context.create [ Sign ; Verify ] + let ctx = Context.create () let cstruct_testable = Alcotest.testable Cstruct.hexdump_pp Cstruct.equal @@ -55,8 +52,7 @@ module External = struct assert_eq_cstruct sign_orig sign let test_valid_signature _ = - let ctx = Context.create [Verify] in - let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex + let msg = buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in let signature = Sign.read_der_exn ctx (buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in @@ -65,8 +61,7 @@ module External = struct assert (Sign.verify_exn ctx ~signature ~pk ~msg) let test_invalid_signature _ = - let ctx = Context.create [Verify] in - let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex + let msg = buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91" in let signature = Sign.read_der_exn ctx (buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in @@ -98,27 +93,25 @@ module External = struct assert_eq_cstruct pubtrue pubkey_serialized let test_sign _ = - let ctx = Context.create [Sign] in - let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in + let msg = buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in let sk = Key.read_sk_exn ctx (buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530") in let validsign = Sign.read_der_exn ctx (buffer_of_hex "30440220182a108e1448dc8f1fb467d06a0f3bb8ea0533584cb954ef8da112f1d60e39a202201c66f36da211c087f3af88b50edf4f9bdaa6cf5fd6817e74dca34db12390c6e9") in - let sign = Sign.sign_exn ctx ~sk ~msg in + let sign = Sign.sign_exn ctx ~sk msg in assert (Sign.equal sign validsign) let test_recover _ = - let ctx = Context.create [Sign; Verify] in - let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in + let msg = buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in let seckey = Key.read_sk_exn ctx (buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530") in let pubkey = Key.neuterize_exn ctx seckey in let recoverable_sign = Sign.sign_recoverable_exn ctx ~sk:seckey msg in let usual_sign = Sign.to_plain ctx recoverable_sign in assert (Sign.verify_exn ctx ~pk:pubkey ~signature:usual_sign ~msg); - let compact, recid = Sign.to_bytes_recid ctx recoverable_sign in - let usual_sign' = Sign.read_exn ctx compact in + let recoverable_bytes = Sign.to_bytes ctx recoverable_sign in + let usual_sign' = Sign.read_exn ctx recoverable_bytes in assert (Sign.equal usual_sign' usual_sign) ; - let parsed = Sign.read_recoverable_exn ctx compact ~recid in - assert (Sign.equal parsed recoverable_sign); - match Sign.recover ctx ~signature:recoverable_sign ~msg with + let recoverable_sign' = Sign.read_recoverable_exn ctx recoverable_bytes in + assert (Sign.equal recoverable_sign' recoverable_sign); + match Sign.recover ctx ~signature:recoverable_sign msg with | Error _ -> assert false | Ok recovered -> assert (Key.equal recovered pubkey)