Crypto: fixes for secp256k1
This commit is contained in:
parent
3a0cdfd90a
commit
47f9c2460b
@ -19,7 +19,11 @@ let () =
|
|||||||
|
|
||||||
open Libsecp256k1.External
|
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
|
module Public_key = struct
|
||||||
|
|
||||||
@ -36,7 +40,7 @@ module Public_key = struct
|
|||||||
let to_string s = MBytes.to_string (to_bytes s)
|
let to_string s = MBytes.to_string (to_bytes s)
|
||||||
let of_string_opt s = of_bytes_opt (MBytes.of_string 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 +=
|
type Base58.data +=
|
||||||
| Data of t
|
| Data of t
|
||||||
@ -58,7 +62,7 @@ module Public_key = struct
|
|||||||
include Compare.Make(struct
|
include Compare.Make(struct
|
||||||
type nonrec t = t
|
type nonrec t = t
|
||||||
let compare a b =
|
let compare a b =
|
||||||
MBytes.compare (Key.to_buffer a) (Key.to_buffer b)
|
MBytes.compare (Key.buffer a) (Key.buffer b)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
include Helpers.MakeRaw(struct
|
include Helpers.MakeRaw(struct
|
||||||
@ -101,7 +105,7 @@ module Secret_key = struct
|
|||||||
let name = "Secp256k1.Secret_key"
|
let name = "Secp256k1.Secret_key"
|
||||||
let title = "A 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 =
|
let of_bytes_opt s =
|
||||||
match Key.read_sk context s with
|
match Key.read_sk context s with
|
||||||
@ -131,7 +135,7 @@ module Secret_key = struct
|
|||||||
include Compare.Make(struct
|
include Compare.Make(struct
|
||||||
type nonrec t = t
|
type nonrec t = t
|
||||||
let compare a b =
|
let compare a b =
|
||||||
MBytes.compare (Key.to_buffer a) (Key.to_buffer b)
|
MBytes.compare (Key.buffer a) (Key.buffer b)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
include Helpers.MakeRaw(struct
|
include Helpers.MakeRaw(struct
|
||||||
@ -167,16 +171,17 @@ module Secret_key = struct
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
type t = MBytes.t
|
type t = Sign.plain Sign.t
|
||||||
|
|
||||||
let name = "Secp256k1"
|
let name = "Secp256k1"
|
||||||
let title = "A Secp256k1 signature"
|
let title = "A Secp256k1 signature"
|
||||||
|
|
||||||
let size = 64 (* TODO don't hardcode? *)
|
let size = Sign.plain_bytes
|
||||||
|
|
||||||
let of_bytes_opt s =
|
let of_bytes_opt s =
|
||||||
if MBytes.length s = size then Some s else None
|
match Sign.read context s with Ok s -> Some s | Error _ -> None
|
||||||
let to_bytes x = x
|
|
||||||
|
let to_bytes = Sign.to_bytes ~der:false context
|
||||||
|
|
||||||
let to_string s = MBytes.to_string (to_bytes s)
|
let to_string s = MBytes.to_string (to_bytes s)
|
||||||
let of_string_opt s = of_bytes_opt (MBytes.of_string s)
|
let of_string_opt s = of_bytes_opt (MBytes.of_string s)
|
||||||
@ -197,7 +202,8 @@ let () =
|
|||||||
|
|
||||||
include Compare.Make(struct
|
include Compare.Make(struct
|
||||||
type nonrec t = t
|
type nonrec t = t
|
||||||
let compare = MBytes.compare
|
let compare a b =
|
||||||
|
MBytes.compare (Sign.buffer a) (Sign.buffer b)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
include Helpers.MakeRaw(struct
|
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 zero = of_bytes_exn (MBytes.init size '\000')
|
||||||
|
|
||||||
let sign secret_key message =
|
let sign sk msg =
|
||||||
match Sign.msg_of_bytes message with
|
Sign.sign_exn context ~sk msg
|
||||||
| 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 check public_key signature msg =
|
let check public_key signature msg =
|
||||||
match Sign.msg_of_bytes msg, Sign.read context signature with
|
Sign.verify_exn context ~pk:public_key ~msg ~signature
|
||||||
| Some msg, Ok signature -> begin
|
|
||||||
match Sign.verify context ~pk:public_key ~msg ~signature with
|
|
||||||
| Ok b -> b
|
|
||||||
| _ -> false
|
|
||||||
end
|
|
||||||
| _, _ -> false
|
|
||||||
|
|
||||||
let concat msg signature =
|
let concat msg t =
|
||||||
MBytes.concat msg signature
|
MBytes.concat msg (Sign.to_bytes ~der:false context t)
|
||||||
|
|
||||||
let append key msg =
|
let append sk msg =
|
||||||
let signature = sign key msg in
|
concat msg (Sign.sign_exn context ~sk msg)
|
||||||
concat msg signature
|
|
||||||
|
|
||||||
let generate_key () =
|
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 pk = Key.neuterize_exn context sk in
|
||||||
let pkh = Public_key.hash pk in
|
let pkh = Public_key.hash pk in
|
||||||
(pkh, pk, sk)
|
(pkh, pk, sk)
|
||||||
|
5
vendors/ocaml-secp256k1/Makefile
vendored
5
vendors/ocaml-secp256k1/Makefile
vendored
@ -1,5 +0,0 @@
|
|||||||
all:
|
|
||||||
jbuilder build @install @runtest
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf _build
|
|
581
vendors/ocaml-secp256k1/src/external.ml
vendored
581
vendors/ocaml-secp256k1/src/external.ml
vendored
@ -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
|
module Context = struct
|
||||||
type flag =
|
|
||||||
| Verify
|
|
||||||
| Sign
|
|
||||||
|
|
||||||
type t
|
type t
|
||||||
|
|
||||||
external flags : buffer -> int = "context_flags"
|
external create : int -> t = "caml_secp256k1_context_create"
|
||||||
external create : int -> t = "context_create"
|
external clone : t -> t = "caml_secp256k1_context_clone"
|
||||||
external clone : t -> t = "context_clone"
|
external randomize : t -> Bigstring.t -> bool = "caml_secp256k1_context_randomize" [@@noalloc]
|
||||||
external randomize : t -> buffer -> bool = "context_randomize" [@@noalloc]
|
|
||||||
external get_16 : buffer -> int -> int = "%caml_bigstring_get16" [@@noalloc]
|
|
||||||
|
|
||||||
let flags =
|
let create ?(sign=true) ?(verify=true) () =
|
||||||
let buf = BA.create (3 * 2) in
|
let flags = 1 lor
|
||||||
let _ = flags buf in
|
(if sign then 0x100 else 0) lor
|
||||||
buf
|
(if verify then 0x200 else 0) in
|
||||||
|
create flags
|
||||||
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 randomize ctx buf =
|
let randomize ctx buf =
|
||||||
if BA.length buf <> 32 then
|
if Bigstring.length buf < 32 then
|
||||||
invalid_arg "Context.randomize: input must be 32 bytes long" ;
|
invalid_arg "Context.randomize: input must be at least 32 bytes long" ;
|
||||||
randomize ctx buf
|
randomize ctx buf
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -61,49 +21,51 @@ module Key = struct
|
|||||||
type secret
|
type secret
|
||||||
type public
|
type public
|
||||||
type _ t =
|
type _ t =
|
||||||
| Sk : buffer -> secret t
|
| Sk : Bigstring.t -> secret t
|
||||||
| Pk : buffer -> public t
|
| Pk : Bigstring.t -> public t
|
||||||
|
|
||||||
let to_buffer : type a. a t -> buffer = function
|
let buffer : type a. a t -> Bigstring.t = function
|
||||||
| Sk k -> k
|
| Sk sk -> sk
|
||||||
| Pk k -> k
|
| Pk pk -> pk
|
||||||
|
|
||||||
let secret_bytes = 32
|
let secret_bytes = 32
|
||||||
let public_bytes = 64
|
let public_bytes = 64
|
||||||
|
let compressed_pk_bytes = 33
|
||||||
|
let uncompressed_pk_bytes = 65
|
||||||
|
|
||||||
let length : type a. a t -> int = function
|
let bytes : type a. a t -> int = function
|
||||||
| Sk _ -> 32
|
| Sk _ -> secret_bytes
|
||||||
| Pk _ -> 64
|
| 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 ->
|
let equal : type a. a t -> a t -> bool = fun a b ->
|
||||||
match a, b with
|
match a, b with
|
||||||
| Sk a, Sk b -> BA.equal a b
|
| Sk a, Sk b -> Bigstring.equal a b
|
||||||
| Pk a, Pk b -> BA.equal a b
|
| Pk a, Pk b -> Bigstring.equal a b
|
||||||
|
|
||||||
let copy : type a. a t -> a t = function
|
let copy : type a. a t -> a t = function
|
||||||
| Sk k ->
|
| Sk sk -> Sk (Bigstring.copy sk)
|
||||||
let k' = BA.create secret_bytes in
|
| Pk pk -> Pk (Bigstring.copy pk)
|
||||||
BA.blit k k' ;
|
|
||||||
Sk k'
|
|
||||||
| Pk k ->
|
|
||||||
let k' = BA.create public_bytes in
|
|
||||||
BA.blit k k' ;
|
|
||||||
Pk k'
|
|
||||||
|
|
||||||
external sk_negate_inplace : Context.t -> buffer -> unit =
|
external sk_negate_inplace : Context.t -> Bigstring.t -> unit =
|
||||||
"ec_privkey_negate" [@@noalloc]
|
"caml_secp256k1_ec_privkey_negate" [@@noalloc]
|
||||||
external sk_add_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
external sk_add_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ec_privkey_tweak_add" [@@noalloc]
|
"caml_secp256k1_ec_privkey_tweak_add" [@@noalloc]
|
||||||
external sk_mul_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
external sk_mul_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ec_privkey_tweak_mul" [@@noalloc]
|
"caml_secp256k1_ec_privkey_tweak_mul" [@@noalloc]
|
||||||
external pk_negate_inplace : Context.t -> buffer -> unit =
|
external pk_negate_inplace : Context.t -> Bigstring.t -> unit =
|
||||||
"ec_pubkey_negate" [@@noalloc]
|
"caml_secp256k1_ec_pubkey_negate" [@@noalloc]
|
||||||
external pk_add_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
external pk_add_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ec_pubkey_tweak_add" [@@noalloc]
|
"caml_secp256k1_ec_pubkey_tweak_add" [@@noalloc]
|
||||||
external pk_mul_tweak_inplace : Context.t -> buffer -> buffer -> bool =
|
external pk_mul_tweak_inplace : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ec_pubkey_tweak_mul" [@@noalloc]
|
"caml_secp256k1_ec_pubkey_tweak_mul" [@@noalloc]
|
||||||
external pk_combine : Context.t -> buffer -> buffer list -> bool =
|
external pk_combine : Context.t -> Bigstring.t -> Bigstring.t list -> bool =
|
||||||
"ec_pubkey_combine" [@@noalloc]
|
"caml_secp256k1_ec_pubkey_combine" [@@noalloc]
|
||||||
|
|
||||||
let negate_inplace :
|
let negate_inplace :
|
||||||
type a. Context.t -> a t -> unit = fun ctx -> function
|
type a. Context.t -> a t -> unit = fun ctx -> function
|
||||||
@ -116,44 +78,43 @@ module Key = struct
|
|||||||
k'
|
k'
|
||||||
|
|
||||||
let op_tweak :
|
let op_tweak :
|
||||||
type a. string -> (Context.t -> buffer -> buffer -> bool) ->
|
type a. string -> (Context.t -> Bigstring.t -> Bigstring.t -> bool) ->
|
||||||
Context.t -> a t -> ?pos:int -> buffer -> buffer =
|
Context.t -> a t -> Bigstring.t -> Bigstring.t =
|
||||||
fun name f ctx k ?(pos=0) buf ->
|
fun name f ctx k buf ->
|
||||||
let buflen = BA.length buf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0 || pos > buflen - 32 then
|
if buflen < 32 then
|
||||||
invalid_arg (Printf.sprintf "Key.%s: pos < 0 or pos > buflen - 32" name) ;
|
invalid_arg (Printf.sprintf "Key.%s: " name) ;
|
||||||
let buf = BA.sub buf pos 32 in
|
let k' = buffer (copy k) in
|
||||||
let k' = copy k |> to_buffer in
|
|
||||||
if not (f ctx k' buf) then
|
if not (f ctx k' buf) then
|
||||||
failwith (Printf.sprintf "Key.%s: operation failed" name) ;
|
failwith (Printf.sprintf "Key.%s: operation failed" name) ;
|
||||||
k'
|
k'
|
||||||
|
|
||||||
let add_tweak :
|
let add_tweak :
|
||||||
type a. Context.t -> a t -> ?pos:int -> buffer -> a t =
|
type a. Context.t -> a t -> Bigstring.t -> a t =
|
||||||
fun ctx k ?pos buf ->
|
fun ctx k buf ->
|
||||||
match k with
|
match k with
|
||||||
| Sk _ -> Sk (op_tweak "add_tweak" sk_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 ?pos buf)
|
| Pk _ -> Pk (op_tweak "add_tweak" pk_add_tweak_inplace ctx k buf)
|
||||||
|
|
||||||
let mul_tweak :
|
let mul_tweak :
|
||||||
type a. Context.t -> a t -> ?pos:int -> buffer -> a t =
|
type a. Context.t -> a t -> Bigstring.t -> a t =
|
||||||
fun ctx k ?pos buf ->
|
fun ctx k buf ->
|
||||||
match k with
|
match k with
|
||||||
| Sk _ -> Sk (op_tweak "mul_tweak" sk_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 ?pos buf)
|
| Pk _ -> Pk (op_tweak "mul_tweak" pk_mul_tweak_inplace ctx k buf)
|
||||||
|
|
||||||
external pk_parse : Context.t -> buffer -> buffer -> bool =
|
external pk_parse : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ec_pubkey_parse" [@@noalloc]
|
"caml_secp256k1_ec_pubkey_parse" [@@noalloc]
|
||||||
external pk_serialize : Context.t -> buffer -> buffer -> int =
|
external pk_serialize : Context.t -> Bigstring.t -> Bigstring.t -> int =
|
||||||
"ec_pubkey_serialize" [@@noalloc]
|
"caml_secp256k1_ec_pubkey_serialize" [@@noalloc]
|
||||||
external pk_create : Context.t -> buffer -> buffer -> bool =
|
external pk_create : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ec_pubkey_create" [@@noalloc]
|
"caml_secp256k1_ec_pubkey_create" [@@noalloc]
|
||||||
|
|
||||||
let neuterize :
|
let neuterize :
|
||||||
type a. Context.t -> a t -> public t option = fun ctx -> function
|
type a. Context.t -> a t -> public t option = fun ctx -> function
|
||||||
| Pk pk -> Some (Pk pk)
|
| Pk pk -> Some (Pk pk)
|
||||||
| Sk sk ->
|
| 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
|
if pk_create ctx pk sk then Some (Pk pk) else None
|
||||||
|
|
||||||
let neuterize_exn ctx k =
|
let neuterize_exn ctx k =
|
||||||
@ -162,7 +123,7 @@ module Key = struct
|
|||||||
| Some pk -> pk
|
| Some pk -> pk
|
||||||
|
|
||||||
let list_map_filter_opt ~f l =
|
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
|
match f e with
|
||||||
| None -> a
|
| None -> a
|
||||||
| Some r -> r :: a
|
| Some r -> r :: a
|
||||||
@ -172,7 +133,7 @@ module Key = struct
|
|||||||
let nb_pks = List.length pks in
|
let nb_pks = List.length pks in
|
||||||
if nb_pks = 0 || nb_pks > 1024 then None
|
if nb_pks = 0 || nb_pks > 1024 then None
|
||||||
else
|
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 ->
|
let pks = list_map_filter_opt ~f:begin fun k ->
|
||||||
match neuterize ctx k with
|
match neuterize ctx k with
|
||||||
| None -> None
|
| None -> None
|
||||||
@ -186,70 +147,64 @@ module Key = struct
|
|||||||
| None -> invalid_arg "Key.combine_exn: sum of pks is invalid"
|
| None -> invalid_arg "Key.combine_exn: sum of pks is invalid"
|
||||||
| Some pk -> pk
|
| Some pk -> pk
|
||||||
|
|
||||||
external verify_sk : Context.t -> buffer -> bool =
|
external verify_sk : Context.t -> Bigstring.t -> bool =
|
||||||
"ec_seckey_verify" [@@noalloc]
|
"caml_secp256k1_ec_seckey_verify" [@@noalloc]
|
||||||
|
|
||||||
let read_sk_exn ctx ?(pos=0) buf =
|
let read_sk_exn ctx buf =
|
||||||
let buflen = BA.length buf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0 || pos > buflen - secret_bytes then
|
if buflen < secret_bytes then
|
||||||
invalid_arg "Key.read_sk: pos < 0 or pos + 32 > buflen" ;
|
invalid_arg (Printf.sprintf "Key.read_sk: invalid buffer size %d" buflen) ;
|
||||||
let buf = BA.sub buf pos secret_bytes in
|
|
||||||
match verify_sk ctx buf with
|
match verify_sk ctx buf with
|
||||||
| true ->
|
| true -> Sk Bigstring.(copy (sub buf 0 secret_bytes))
|
||||||
let t = BA.create secret_bytes in
|
| false -> invalid_arg "Key.read_sk: secret key is invalid"
|
||||||
BA.blit buf t ;
|
|
||||||
Sk buf
|
|
||||||
| false -> invalid_arg "Key.read_sk_exn: secret key is invalid"
|
|
||||||
|
|
||||||
let read_sk ctx ?pos buf =
|
let read_sk ctx buf =
|
||||||
try Ok (read_sk_exn ctx ?pos buf) with
|
try Ok (read_sk_exn ctx buf) with
|
||||||
| Invalid_argument msg -> Error msg
|
| Invalid_argument msg -> Error msg
|
||||||
|
|
||||||
let read_pk_exn ctx ?(pos=0) inbuf =
|
let read_pk_exn ctx buf =
|
||||||
let pklen = BA.length inbuf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0 || pos > pklen - 33 then
|
if buflen < compressed_pk_bytes then
|
||||||
invalid_arg "Key.read_pk: pos < 0 or pos > buflen - 33" ;
|
invalid_arg (Printf.sprintf "Key.read_pk: invalid buffer size %d" buflen) ;
|
||||||
let inbuf = BA.(sub inbuf pos (length inbuf)) in
|
let outbuf = Bigstring.create public_bytes in
|
||||||
if BA.(length inbuf < 33) then
|
if pk_parse ctx outbuf buf then
|
||||||
invalid_arg "Key.read_pk: input must be at least 33 bytes long" ;
|
Pk outbuf
|
||||||
let outbuf = BA.create public_bytes in
|
else
|
||||||
if (pk_parse ctx outbuf inbuf) then Pk outbuf
|
invalid_arg "Key.read_pk_exn: public key is invalid"
|
||||||
else invalid_arg "Key.read_pk_exn: public key is invalid"
|
|
||||||
|
|
||||||
let read_pk ctx ?pos buf =
|
let read_pk ctx buf =
|
||||||
try Ok (read_pk_exn ctx ?pos buf) with
|
try Ok (read_pk_exn ctx buf) with
|
||||||
| Invalid_argument msg -> Error msg
|
| Invalid_argument msg -> Error msg
|
||||||
|
|
||||||
let write :
|
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
|
fun ?(compress=true) ctx ?(pos=0) buf -> function
|
||||||
| Sk sk ->
|
| Sk sk ->
|
||||||
let buflen = BA.length buf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0 || pos > buflen - secret_bytes then
|
if pos < 0 || pos > buflen - secret_bytes then
|
||||||
invalid_arg "Key.write (secret): pos < 0 or pos + 32 > buflen" ;
|
invalid_arg "Key.write (secret): pos < 0 or pos + 32 > buflen" ;
|
||||||
let buf = BA.sub buf pos secret_bytes in
|
Bigstring.blit sk 0 buf pos secret_bytes ;
|
||||||
BA.blit sk buf ;
|
|
||||||
secret_bytes
|
secret_bytes
|
||||||
| Pk pk ->
|
| Pk pk ->
|
||||||
let buflen = BA.length buf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0
|
if pos < 0
|
||||||
|| (compress && pos > buflen - 33)
|
|| (compress && pos > buflen - compressed_pk_bytes)
|
||||||
|| (not compress && pos > buflen - 65) then
|
|| (not compress && pos > buflen - uncompressed_pk_bytes) then
|
||||||
invalid_arg (Printf.sprintf "Key.write (public): pos=%d, buflen=%d" pos buflen) ;
|
invalid_arg (Printf.sprintf "Key.write (public): pos=%d, buflen=%d" pos buflen) ;
|
||||||
let len = if compress then 33 else 65 in
|
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
|
pk_serialize ctx buf pk
|
||||||
|
|
||||||
let to_bytes :
|
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
|
fun ?(compress=true) ctx -> function
|
||||||
| Sk _ as sk ->
|
| Sk _ as sk ->
|
||||||
let buf = BA.create secret_bytes in
|
let buf = Bigstring.create secret_bytes in
|
||||||
let _ = write ~compress ctx buf sk in
|
let _ = write ~compress ctx buf sk in
|
||||||
buf
|
buf
|
||||||
| Pk _ as pk ->
|
| Pk _ as pk ->
|
||||||
let buf =
|
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
|
let _ = write ~compress ctx buf pk in
|
||||||
buf
|
buf
|
||||||
end
|
end
|
||||||
@ -258,167 +213,199 @@ module Sign = struct
|
|||||||
type plain
|
type plain
|
||||||
type recoverable
|
type recoverable
|
||||||
type _ t =
|
type _ t =
|
||||||
| P : buffer -> plain t
|
| P : Bigstring.t -> plain t
|
||||||
| R : buffer -> recoverable 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 plain_bytes = 64
|
||||||
let recoverable_bytes = 65
|
let recoverable_bytes = 65
|
||||||
let msg_bytes = 32
|
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 ->
|
let equal : type a. a t -> a t -> bool = fun a b ->
|
||||||
match a, b with
|
match a, b with
|
||||||
| P a, P b -> BA.equal a b
|
| P a, P b -> Bigstring.equal a b
|
||||||
| R a, R b -> BA.equal a b
|
| R a, R b -> Bigstring.equal a b
|
||||||
|
|
||||||
external parse_compact : Context.t -> buffer -> buffer -> bool =
|
external parse_compact : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ecdsa_signature_parse_compact" [@@noalloc]
|
"caml_secp256k1_ecdsa_signature_parse_compact" [@@noalloc]
|
||||||
external parse_der : Context.t -> buffer -> buffer -> bool =
|
external parse_der : Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
"ecdsa_signature_parse_der" [@@noalloc]
|
"caml_secp256k1_ecdsa_signature_parse_der" [@@noalloc]
|
||||||
external serialize_compact : Context.t -> buffer -> buffer -> unit =
|
external serialize_compact : Context.t -> Bigstring.t -> Bigstring.t -> unit =
|
||||||
"ecdsa_signature_serialize_compact" [@@noalloc]
|
"caml_secp256k1_ecdsa_signature_serialize_compact" [@@noalloc]
|
||||||
external serialize_der : Context.t -> buffer -> buffer -> int =
|
external serialize_der : Context.t -> Bigstring.t -> Bigstring.t -> int =
|
||||||
"ecdsa_signature_serialize_der" [@@noalloc]
|
"caml_secp256k1_ecdsa_signature_serialize_der" [@@noalloc]
|
||||||
external parse_recoverable : Context.t -> buffer -> buffer -> int -> bool =
|
external parse_recoverable : Context.t -> Bigstring.t -> Bigstring.t -> int -> bool =
|
||||||
"ecdsa_recoverable_signature_parse_compact" [@@noalloc]
|
"caml_secp256k1_ecdsa_recoverable_signature_parse_compact" [@@noalloc]
|
||||||
external serialize_recoverable : Context.t -> buffer -> buffer -> int =
|
external serialize_recoverable : Context.t -> Bigstring.t -> Bigstring.t -> int =
|
||||||
"ecdsa_recoverable_signature_serialize_compact" [@@noalloc]
|
"caml_secp256k1_ecdsa_recoverable_signature_serialize_compact" [@@noalloc]
|
||||||
|
|
||||||
let read_exn ctx ?(pos=0) buf =
|
let read_exn ctx buf =
|
||||||
let buflen = BA.length buf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0 || pos > buflen - plain_bytes then
|
if buflen < plain_bytes then
|
||||||
invalid_arg "Sign.read_exn: pos < 0 or pos > buflen - 64" ;
|
invalid_arg (Printf.sprintf "Sign.read: invalid buffer size %d" buflen) ;
|
||||||
let signature = BA.create plain_bytes in
|
let signature = Bigstring.create plain_bytes in
|
||||||
if parse_compact ctx signature (BA.sub buf pos plain_bytes) then
|
if parse_compact ctx signature buf then
|
||||||
P signature
|
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 =
|
let read ctx buf =
|
||||||
try Ok (read_exn ctx ?pos buf) with
|
try Ok (read_exn ctx buf) with
|
||||||
| Invalid_argument msg -> Error msg
|
Invalid_argument msg -> Error msg
|
||||||
|
|
||||||
let read_der_exn ctx ?(pos=0) buf =
|
let read_der_exn ctx buf =
|
||||||
let buflen = BA.length buf in
|
let signature = Bigstring.create plain_bytes in
|
||||||
if pos < 0 || pos > buflen - plain_bytes then
|
if parse_der ctx signature buf 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
|
|
||||||
P signature
|
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 =
|
let read_der ctx buf =
|
||||||
try Ok (read_der_exn ctx ?pos buf) with
|
try Ok (read_der_exn ctx buf) with
|
||||||
| Invalid_argument msg -> Error msg
|
Invalid_argument msg -> Error msg
|
||||||
|
|
||||||
let read_recoverable_exn ctx ~recid ?(pos=0) buf =
|
let read_recoverable_exn ctx buf =
|
||||||
let buflen = BA.length buf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0 || pos > buflen - plain_bytes then
|
if buflen < recoverable_bytes then
|
||||||
invalid_arg "Sign.read_recoverable_exn: pos < 0 or pos > buflen - 64" ;
|
invalid_arg (Printf.sprintf "Sign.read_recoverable: invalid buffer size %d" buflen) ;
|
||||||
let signature = BA.create recoverable_bytes in
|
let signature = Bigstring.create recoverable_bytes in
|
||||||
if parse_recoverable ctx signature (BA.sub buf pos plain_bytes) recid then (R signature)
|
let recid = int_of_char (Bigstring.get buf 64) in
|
||||||
else invalid_arg "Sign.read_recoverable_exn: signature could not be parsed"
|
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 =
|
let read_recoverable ctx buf =
|
||||||
try Ok (read_recoverable_exn ctx ~recid ?pos buf) with
|
try Ok (read_recoverable_exn ctx buf) with
|
||||||
| Invalid_argument msg -> Error msg
|
| Invalid_argument msg -> Error msg
|
||||||
|
|
||||||
let write_exn :
|
let write_exn :
|
||||||
type a. ?der:bool -> Context.t -> ?pos:int -> buffer -> a t -> int =
|
type a. ?der:bool -> Context.t -> Bigstring.t -> a t -> int =
|
||||||
fun ?(der=false) ctx ?(pos=0) buf -> function
|
fun ?(der=false) ctx buf -> function
|
||||||
| P signature ->
|
| P signature ->
|
||||||
let buf = BA.(sub buf pos (length buf)) in
|
let buflen = Bigstring.length buf in
|
||||||
if der then serialize_der ctx buf signature
|
if not der then begin
|
||||||
else (serialize_compact ctx buf signature ; plain_bytes)
|
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 ->
|
| R signature ->
|
||||||
let buflen = BA.length buf in
|
let buflen = Bigstring.length buf in
|
||||||
if pos < 0 || pos > buflen - plain_bytes then
|
if buflen < recoverable_bytes then
|
||||||
invalid_arg "write: pos < 0 or pos > buflen - 64" ;
|
invalid_arg (Printf.sprintf "Sign.write: buffer length too small (%d)" buflen) ;
|
||||||
ignore (serialize_recoverable ctx (BA.sub buf pos plain_bytes) signature) ;
|
let recid = serialize_recoverable ctx buf signature in
|
||||||
plain_bytes
|
Bigstring.set buf 64 (char_of_int recid) ;
|
||||||
|
recoverable_bytes
|
||||||
|
|
||||||
let write ?der ctx ?pos buf signature =
|
let write ?der ctx buf signature =
|
||||||
try Ok (write_exn ?der ctx ?pos buf signature) with
|
try Ok (write_exn ?der ctx buf signature) with
|
||||||
| Invalid_argument msg -> Error msg
|
Invalid_argument msg -> Error msg
|
||||||
|
|
||||||
let to_bytes ?der ctx signature =
|
let to_bytes :
|
||||||
let buf = BA.create 72 in
|
type a. ?der:bool -> Context.t -> a t -> Bigstring.t =
|
||||||
let nb_written = write_exn ?der ctx buf signature in
|
fun ?(der=false) ctx -> function
|
||||||
BA.sub buf 0 nb_written
|
| 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) =
|
external normalize :
|
||||||
let buf = BA.create plain_bytes in
|
Context.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
let recid = serialize_recoverable ctx buf signature in
|
"caml_secp256k1_ecdsa_signature_normalize" [@@noalloc]
|
||||||
buf, recid
|
|
||||||
|
|
||||||
external sign : Context.t -> buffer -> buffer -> buffer -> bool =
|
let normalize ctx (P signature) =
|
||||||
"ecdsa_sign" [@@noalloc]
|
let normalized_sig = Bigstring.create plain_bytes in
|
||||||
external verify : Context.t -> buffer -> buffer -> buffer -> bool =
|
if normalize ctx normalized_sig signature then
|
||||||
"ecdsa_verify" [@@noalloc]
|
Some (P normalized_sig) else None
|
||||||
|
|
||||||
let write_sign_exn ctx ~sk ~msg ?(pos=0) buf =
|
(* [sign ctx signature msg sk] *)
|
||||||
let buflen = BA.length buf in
|
external sign :
|
||||||
if pos < 0 || pos > buflen - plain_bytes then
|
Context.t -> Bigstring.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
invalid_arg "Sign.write_sign: outpos < 0 or outpos > outbuf - 64" ;
|
"caml_secp256k1_ecdsa_sign" [@@noalloc]
|
||||||
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"
|
|
||||||
|
|
||||||
let write_sign ctx ~sk ~msg ?pos buf =
|
(* [verify ctx pk msg signature] *)
|
||||||
try Ok (write_sign_exn ctx ~sk ~msg ?pos buf) with
|
external verify :
|
||||||
| Invalid_argument msg -> Error msg
|
Context.t -> Bigstring.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
|
"caml_secp256k1_ecdsa_verify" [@@noalloc]
|
||||||
|
|
||||||
let sign ctx ~sk ~msg =
|
let check_msglen msg =
|
||||||
let signature = BA.create plain_bytes in
|
let msglen = Bigstring.length msg in
|
||||||
match write_sign ctx ~sk ~msg signature with
|
if msglen < msg_bytes
|
||||||
| Error msg -> Error msg
|
then invalid_arg
|
||||||
| Ok _nb_written -> Ok (P signature)
|
(Printf.sprintf "message is too small (%d < %d)" msglen msg_bytes)
|
||||||
|
|
||||||
let sign_exn ctx ~sk ~msg =
|
let sign_exn ctx buf ~sk ~msg =
|
||||||
match sign ctx ~sk ~msg with
|
check_msglen msg ;
|
||||||
| Error msg -> invalid_arg msg
|
let buflen = Bigstring.length buf in
|
||||||
| Ok signature -> signature
|
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 =
|
let write_sign_exn ctx buf ~sk ~msg =
|
||||||
"ecdsa_sign_recoverable" [@@noalloc]
|
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 write_sign ctx buf ~sk ~msg =
|
||||||
let buflen = BA.length buf in
|
try Ok (write_sign_exn ctx ~sk ~msg buf)
|
||||||
if pos < 0 || pos > buflen - recoverable_bytes then
|
with Invalid_argument msg -> Error msg
|
||||||
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_recoverable ctx ~sk ~msg ?pos buf =
|
let sign_exn ctx ~sk msg =
|
||||||
try Ok (write_sign_recoverable_exn ctx ~sk ~msg ?pos buf) with
|
let signature = Bigstring.create plain_bytes in
|
||||||
| Invalid_argument msg -> Error msg
|
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 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
|
match write_sign_recoverable ctx ~sk ~msg signature with
|
||||||
| Error error -> Error error
|
| Error error -> Error error
|
||||||
| Ok _nb_written -> Ok (R signature)
|
| Ok _nb_written -> Ok (R signature)
|
||||||
@ -428,42 +415,44 @@ module Sign = struct
|
|||||||
| Error msg -> invalid_arg msg
|
| Error msg -> invalid_arg msg
|
||||||
| Ok signature -> signature
|
| Ok signature -> signature
|
||||||
|
|
||||||
external to_plain : Context.t -> buffer -> buffer -> unit =
|
external to_plain : Context.t -> Bigstring.t -> Bigstring.t -> unit =
|
||||||
"ecdsa_recoverable_signature_convert" [@@noalloc]
|
"caml_secp256k1_ecdsa_recoverable_signature_convert" [@@noalloc]
|
||||||
|
|
||||||
let to_plain ctx (R recoverable) =
|
let to_plain : type a. Context.t -> a t -> plain t = fun ctx -> function
|
||||||
let plain = BA.create plain_bytes in
|
| P _ as signature -> signature
|
||||||
to_plain ctx plain recoverable ;
|
| R recoverable ->
|
||||||
P plain
|
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 verify_plain_exn ctx ~pk msg signature =
|
||||||
let msglen = BA.length msg in
|
check_msglen msg ;
|
||||||
if pos < 0 || pos > msglen - 32 then
|
let siglen = Bigstring.length signature in
|
||||||
invalid_arg "Sign.verify: msg must be at least 32 bytes long" ;
|
if siglen < plain_bytes then
|
||||||
verify ctx (Key.to_buffer pk) (BA.sub msg pos 32) signature
|
invalid_arg (Printf.sprintf "verify: signature too short (%d < %d)"
|
||||||
|
siglen plain_bytes) ;
|
||||||
|
verify ctx (Key.buffer pk) msg signature
|
||||||
|
|
||||||
let verify_exn :
|
let verify_exn ctx ~pk ~msg ~signature =
|
||||||
type a. Context.t -> pk:Key.public Key.t -> msg:msg -> signature:a t -> bool =
|
let P signature = to_plain ctx signature in
|
||||||
fun ctx ~pk ~msg ~signature -> match signature with
|
verify_plain_exn ctx ~pk msg signature
|
||||||
| 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 ctx ~pk ~msg ~signature =
|
let verify ctx ~pk ~msg ~signature =
|
||||||
try Ok (verify_exn ctx ~pk ~msg ~signature) with
|
try Ok (verify_exn ctx ~pk ~msg ~signature) with
|
||||||
| Invalid_argument msg -> Error msg
|
| Invalid_argument msg -> Error msg
|
||||||
|
|
||||||
external recover : Context.t -> buffer -> buffer -> buffer -> bool =
|
external recover :
|
||||||
"ecdsa_recover" [@@noalloc]
|
Context.t -> Bigstring.t -> Bigstring.t -> Bigstring.t -> bool =
|
||||||
|
"caml_secp256k1_ecdsa_recover" [@@noalloc]
|
||||||
|
|
||||||
let recover_exn ctx ~signature:(R signature) ~msg =
|
let recover_exn ctx ~signature:(R signature) msg =
|
||||||
let pk = BA.create Key.public_bytes in
|
check_msglen msg ;
|
||||||
|
let pk = Bigstring.create Key.public_bytes in
|
||||||
if recover ctx pk signature msg then Key.Pk pk
|
if recover ctx pk signature msg then Key.Pk pk
|
||||||
else
|
else
|
||||||
invalid_arg "Sign.recover: pk could not be recovered"
|
invalid_arg "Sign.recover: pk could not be recovered"
|
||||||
|
|
||||||
let recover ctx ~signature ~msg =
|
let recover ctx ~signature msg =
|
||||||
try Ok (recover_exn ctx ~signature ~msg) with
|
try Ok (recover_exn ctx ~signature msg) with
|
||||||
| Invalid_argument msg -> Error msg
|
Invalid_argument msg -> Error msg
|
||||||
end
|
end
|
||||||
|
184
vendors/ocaml-secp256k1/src/external.mli
vendored
184
vendors/ocaml-secp256k1/src/external.mli
vendored
@ -1,11 +1,4 @@
|
|||||||
type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
|
|
||||||
|
|
||||||
module Context : sig
|
module Context : sig
|
||||||
type flag =
|
|
||||||
| Verify
|
|
||||||
| Sign
|
|
||||||
(** which parts of the context to initialize. *)
|
|
||||||
|
|
||||||
type t
|
type t
|
||||||
(** Opaque data structure that holds context information
|
(** Opaque data structure that holds context information
|
||||||
(precomputed tables etc.).
|
(precomputed tables etc.).
|
||||||
@ -24,13 +17,13 @@ module Context : sig
|
|||||||
which case you do not need any locking for the other calls), or
|
which case you do not need any locking for the other calls), or
|
||||||
use a read-write lock. *)
|
use a read-write lock. *)
|
||||||
|
|
||||||
val create : flag list -> t
|
val create : ?sign:bool -> ?verify:bool -> unit -> t
|
||||||
(** Create a secp256k1 context object. *)
|
(** [create ?sign ?bool ()] is a freshly allocated [t]. *)
|
||||||
|
|
||||||
val clone : t -> 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
|
(** While secp256k1 code is written to be constant-time no matter
|
||||||
what secret values are, it's possible that a future compiler may
|
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
|
output code which isn't, and also that the CPU may not emit the
|
||||||
@ -52,20 +45,39 @@ end
|
|||||||
module Key : sig
|
module Key : sig
|
||||||
type secret
|
type secret
|
||||||
type public
|
type public
|
||||||
type _ t = private
|
type _ t
|
||||||
| Sk : buffer -> secret t
|
|
||||||
| Pk : buffer -> public 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 equal : 'a t -> 'a t -> bool
|
||||||
val copy : 'a t -> 'a t
|
val copy : 'a t -> 'a t
|
||||||
|
|
||||||
(** {2 Aritmetic operations } *)
|
(** {2 Aritmetic operations } *)
|
||||||
|
|
||||||
val negate : Context.t -> 'a t -> 'a t
|
val negate : Context.t -> 'a t -> 'a t
|
||||||
val add_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 -> ?pos:int -> buffer -> 'a t
|
val mul_tweak : Context.t -> 'a t -> Bigstring.t -> 'a t
|
||||||
val neuterize : Context.t -> _ t -> public t option
|
val neuterize : Context.t -> _ t -> public t option
|
||||||
val neuterize_exn : Context.t -> _ t -> public t
|
val neuterize_exn : Context.t -> _ t -> public t
|
||||||
val combine : Context.t -> _ t list -> public t option
|
val combine : Context.t -> _ t list -> public t option
|
||||||
@ -73,74 +85,122 @@ module Key : sig
|
|||||||
|
|
||||||
(** {2 Input/Output} *)
|
(** {2 Input/Output} *)
|
||||||
|
|
||||||
val read_sk : Context.t -> ?pos:int -> buffer -> (secret t, string) result
|
val read_sk : Context.t -> Bigstring.t -> (secret t, string) result
|
||||||
val read_sk_exn : Context.t -> ?pos:int -> buffer -> secret t
|
val read_sk_exn : Context.t -> Bigstring.t -> secret t
|
||||||
val read_pk : Context.t -> ?pos:int -> buffer -> (public t, string) result
|
val read_pk : Context.t -> Bigstring.t -> (public t, string) result
|
||||||
val read_pk_exn : Context.t -> ?pos:int -> buffer -> public t
|
val read_pk_exn : Context.t -> Bigstring.t -> public t
|
||||||
val write : ?compress:bool -> Context.t -> ?pos:int -> buffer -> _ t -> int
|
val write : ?compress:bool -> Context.t -> ?pos:int -> Bigstring.t -> _ t -> int
|
||||||
val to_bytes : ?compress:bool -> Context.t -> _ t -> buffer
|
val to_bytes : ?compress:bool -> Context.t -> _ t -> Bigstring.t
|
||||||
end
|
end
|
||||||
|
|
||||||
module Sign : sig
|
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} *)
|
(** {2 Signature} *)
|
||||||
|
|
||||||
type plain
|
type plain
|
||||||
type recoverable
|
type recoverable
|
||||||
type _ t = private
|
type _ t
|
||||||
| P : buffer -> plain t
|
|
||||||
| R : buffer -> recoverable 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 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} *)
|
(** {3 Input/Output} *)
|
||||||
|
|
||||||
val read : Context.t -> ?pos:int -> buffer -> (plain t, string) result
|
val read : Context.t -> Bigstring.t -> (plain t, string) result
|
||||||
val read_exn : Context.t -> ?pos:int -> buffer -> plain t
|
val read_exn : Context.t -> Bigstring.t -> plain t
|
||||||
val read_der : Context.t -> ?pos:int -> buffer -> (plain t, string) result
|
val read_der : Context.t -> Bigstring.t -> (plain t, string) result
|
||||||
val read_der_exn : Context.t -> ?pos:int -> buffer -> plain t
|
val read_der_exn : Context.t -> Bigstring.t -> 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 write_exn : ?der:bool -> Context.t -> ?pos:int -> buffer -> _ t -> int
|
val read_recoverable :
|
||||||
val write : ?der:bool -> Context.t -> ?pos:int -> buffer -> _ t -> (int, string) result
|
Context.t -> Bigstring.t -> (recoverable t, string) result
|
||||||
val to_bytes : ?der:bool -> Context.t -> _ t -> buffer
|
(** [read_recoverable_exn ctx buf] reads a recoverable signature in
|
||||||
val to_bytes_recid : Context.t -> recoverable t -> buffer * int
|
[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} *)
|
(** {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} *)
|
(** {4 Creation} *)
|
||||||
|
|
||||||
val sign : Context.t -> sk:Key.secret Key.t -> msg:msg -> (plain t, string) result
|
val sign : Context.t -> sk:Key.secret Key.t -> Bigstring.t -> (plain
|
||||||
val sign_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> plain t
|
t, string) result
|
||||||
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
|
|
||||||
|
|
||||||
(** {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 sign_recoverable : Context.t -> sk:Key.secret Key.t ->
|
||||||
val write_sign_exn : Context.t -> sk:Key.secret Key.t -> msg:msg -> ?pos:int -> buffer -> int
|
Bigstring.t -> (recoverable t, string) result
|
||||||
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_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} *)
|
(** {4 Verification} *)
|
||||||
|
|
||||||
val verify_exn : Context.t -> pk:Key.public Key.t -> msg:msg -> signature:_ t -> bool
|
val verify_exn : Context.t -> pk:Key.public Key.t -> msg:Bigstring.t
|
||||||
val verify : Context.t -> pk:Key.public Key.t -> msg:msg -> signature:_ t -> (bool, string) result
|
-> signature:_ t -> bool
|
||||||
|
|
||||||
|
val verify : Context.t -> pk:Key.public Key.t -> msg:Bigstring.t ->
|
||||||
|
signature:_ t -> (bool, string) result
|
||||||
|
|
||||||
(** {4 Recovery} *)
|
(** {4 Recovery} *)
|
||||||
|
|
||||||
val recover_exn : Context.t -> signature:recoverable t -> msg:msg -> Key.public Key.t
|
val recover_exn : Context.t -> signature:recoverable t ->
|
||||||
val recover : Context.t -> signature:recoverable t -> msg:msg -> (Key.public Key.t, string) result
|
Bigstring.t -> Key.public Key.t
|
||||||
end
|
|
||||||
|
val recover : Context.t -> signature:recoverable t -> Bigstring.t ->
|
||||||
|
(Key.public Key.t, string) result end
|
||||||
|
2
vendors/ocaml-secp256k1/src/jbuild
vendored
2
vendors/ocaml-secp256k1/src/jbuild
vendored
@ -4,7 +4,7 @@
|
|||||||
((name libsecp256k1)
|
((name libsecp256k1)
|
||||||
(public_name secp256k1)
|
(public_name secp256k1)
|
||||||
(modules (internal external))
|
(modules (internal external))
|
||||||
(libraries (cstruct))
|
(libraries (bigstring cstruct))
|
||||||
(c_names (secp256k1
|
(c_names (secp256k1
|
||||||
secp256k1_wrap))
|
secp256k1_wrap))
|
||||||
(c_flags (:include c_flags.sexp))
|
(c_flags (:include c_flags.sexp))
|
||||||
|
120
vendors/ocaml-secp256k1/src/secp256k1_wrap.c
vendored
120
vendors/ocaml-secp256k1/src/secp256k1_wrap.c
vendored
@ -1,18 +1,16 @@
|
|||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "secp256k1.h"
|
|
||||||
#include "secp256k1_recovery.h"
|
|
||||||
|
|
||||||
#include <caml/mlvalues.h>
|
#include <caml/mlvalues.h>
|
||||||
#include <caml/memory.h>
|
#include <caml/memory.h>
|
||||||
#include <caml/bigarray.h>
|
#include <caml/bigarray.h>
|
||||||
#include <caml/custom.h>
|
#include <caml/custom.h>
|
||||||
#include <caml/fail.h>
|
#include <caml/fail.h>
|
||||||
|
|
||||||
|
#include "secp256k1.h"
|
||||||
|
#include "secp256k1_recovery.h"
|
||||||
|
|
||||||
/* Accessing the secp256k1_context * part of an OCaml custom block */
|
/* Accessing the secp256k1_context * part of an OCaml custom block */
|
||||||
#define Context_val(v) (*((secp256k1_context **) Data_custom_val(v)))
|
#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));
|
secp256k1_context_destroy (Context_val(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,68 +30,60 @@ static value alloc_context (secp256k1_context *ctx) {
|
|||||||
return ml_ctx;
|
return ml_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value context_flags (value buf) {
|
CAMLprim value caml_secp256k1_context_create (value flags) {
|
||||||
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) {
|
|
||||||
CAMLparam1(flags);
|
CAMLparam1(flags);
|
||||||
secp256k1_context *ctx = secp256k1_context_create (Int_val(flags));
|
secp256k1_context *ctx = secp256k1_context_create (Int_val(flags));
|
||||||
if (!ctx) caml_failwith("context_create");
|
if (!ctx) caml_failwith("context_create");
|
||||||
CAMLreturn(alloc_context(ctx));
|
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),
|
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);
|
CAMLparam1(ctx);
|
||||||
secp256k1_context *new = secp256k1_context_clone (Context_val(ctx));
|
secp256k1_context *new = secp256k1_context_clone (Context_val(ctx));
|
||||||
if (!new) caml_failwith("context_clone");
|
if (!new) caml_failwith("context_clone");
|
||||||
CAMLreturn(alloc_context(new));
|
CAMLreturn(alloc_context(new));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_seckey_verify (value ctx, value sk) {
|
CAMLprim value caml_secp256k1_ec_seckey_verify (value ctx, value sk) {
|
||||||
return Val_bool(secp256k1_ec_seckey_verify(Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ec_seckey_verify(Context_val(ctx),
|
||||||
Caml_ba_data_val(sk)));
|
Caml_ba_data_val(sk)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_privkey_negate(value ctx, value sk) {
|
CAMLprim value caml_secp256k1_ec_privkey_negate(value ctx, value sk) {
|
||||||
int ret = secp256k1_ec_privkey_negate(Context_val (ctx),
|
int ret = secp256k1_ec_privkey_negate(Context_val(ctx),
|
||||||
Caml_ba_data_val(sk));
|
Caml_ba_data_val(sk));
|
||||||
return Val_unit;
|
return Val_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_privkey_tweak_add(value ctx, value sk, value tweak) {
|
CAMLprim value caml_secp256k1_ec_privkey_tweak_add(value ctx, value sk, value tweak) {
|
||||||
return Val_bool(secp256k1_ec_privkey_tweak_add(Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ec_privkey_tweak_add(Context_val(ctx),
|
||||||
Caml_ba_data_val(sk),
|
Caml_ba_data_val(sk),
|
||||||
Caml_ba_data_val(tweak)));
|
Caml_ba_data_val(tweak)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_privkey_tweak_mul(value ctx, value sk, value tweak) {
|
CAMLprim value caml_secp256k1_ec_privkey_tweak_mul(value ctx, value sk, value tweak) {
|
||||||
return Val_bool(secp256k1_ec_privkey_tweak_mul(Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ec_privkey_tweak_mul(Context_val(ctx),
|
||||||
Caml_ba_data_val(sk),
|
Caml_ba_data_val(sk),
|
||||||
Caml_ba_data_val(tweak)));
|
Caml_ba_data_val(tweak)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_pubkey_create (value ctx, value buf, value sk) {
|
CAMLprim value caml_secp256k1_ec_pubkey_create (value ctx, value buf, value sk) {
|
||||||
return Val_bool(secp256k1_ec_pubkey_create (Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ec_pubkey_create (Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(sk)));
|
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];
|
size_t size = Caml_ba_array_val(buf)->dim[0];
|
||||||
unsigned int flags =
|
unsigned int flags =
|
||||||
size == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED;
|
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),
|
Caml_ba_data_val(buf),
|
||||||
&size,
|
&size,
|
||||||
Caml_ba_data_val(pk),
|
Caml_ba_data_val(pk),
|
||||||
@ -102,32 +92,32 @@ CAMLprim value ec_pubkey_serialize (value ctx, value buf, value pk) {
|
|||||||
return Val_int(size);
|
return Val_int(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_pubkey_parse(value ctx, value buf, value pk) {
|
CAMLprim value caml_secp256k1_ec_pubkey_parse(value ctx, value buf, value pk) {
|
||||||
return Val_bool(secp256k1_ec_pubkey_parse(Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ec_pubkey_parse(Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(pk),
|
Caml_ba_data_val(pk),
|
||||||
Caml_ba_array_val(pk)->dim[0]));
|
Caml_ba_array_val(pk)->dim[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_pubkey_negate(value ctx, value pk) {
|
CAMLprim value caml_secp256k1_ec_pubkey_negate(value ctx, value pk) {
|
||||||
int ret = secp256k1_ec_pubkey_negate(Caml_ba_data_val(ctx),
|
int ret = secp256k1_ec_pubkey_negate(Context_val(ctx),
|
||||||
Caml_ba_data_val(pk));
|
Caml_ba_data_val(pk));
|
||||||
return Val_unit;
|
return Val_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_pubkey_tweak_add(value ctx, value pk, value tweak) {
|
CAMLprim value caml_secp256k1_ec_pubkey_tweak_add(value ctx, value pk, value tweak) {
|
||||||
return Val_bool(secp256k1_ec_pubkey_tweak_add(Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ec_pubkey_tweak_add(Context_val(ctx),
|
||||||
Caml_ba_data_val(pk),
|
Caml_ba_data_val(pk),
|
||||||
Caml_ba_data_val(tweak)));
|
Caml_ba_data_val(tweak)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ec_pubkey_tweak_mul(value ctx, value pk, value tweak) {
|
CAMLprim value caml_secp256k1_ec_pubkey_tweak_mul(value ctx, value pk, value tweak) {
|
||||||
return Val_bool(secp256k1_ec_pubkey_tweak_mul(Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ec_pubkey_tweak_mul(Context_val(ctx),
|
||||||
Caml_ba_data_val(pk),
|
Caml_ba_data_val(pk),
|
||||||
Caml_ba_data_val(tweak)));
|
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;
|
int size = 0;
|
||||||
const secp256k1_pubkey* cpks[1024] = {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);
|
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),
|
Caml_ba_data_val(out),
|
||||||
cpks,
|
cpks,
|
||||||
size));
|
size));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_signature_parse_compact (value ctx, value buf, value sig) {
|
CAMLprim value caml_secp256k1_ecdsa_signature_parse_compact (value ctx, value buf, value sig) {
|
||||||
return Val_bool(secp256k1_ecdsa_signature_parse_compact (Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ecdsa_signature_parse_compact (Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(sig)));
|
Caml_ba_data_val(sig)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_signature_parse_der (value ctx, value buf, value sig) {
|
CAMLprim value caml_secp256k1_ecdsa_signature_parse_der (value ctx, value buf, value sig) {
|
||||||
return Val_bool(secp256k1_ecdsa_signature_parse_der (Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ecdsa_signature_parse_der (Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(sig),
|
Caml_ba_data_val(sig),
|
||||||
Caml_ba_array_val(sig)->dim[0]));
|
Caml_ba_array_val(sig)->dim[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_verify (value ctx, value pubkey, value msg, value signature) {
|
CAMLprim value caml_secp256k1_ecdsa_signature_normalize(value ctx, value buf, value sig) {
|
||||||
return Val_bool(secp256k1_ecdsa_verify (Caml_ba_data_val(ctx),
|
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(signature),
|
||||||
Caml_ba_data_val(msg),
|
Caml_ba_data_val(msg),
|
||||||
Caml_ba_data_val(pubkey)));
|
Caml_ba_data_val(pubkey)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CAMLprim value ecdsa_sign (value ctx, value buf, value seckey, value msg) {
|
CAMLprim value caml_secp256k1_ecdsa_sign (value ctx, value buf, value seckey, value msg) {
|
||||||
return Val_bool(secp256k1_ecdsa_sign (Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ecdsa_sign (Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(msg),
|
Caml_ba_data_val(msg),
|
||||||
Caml_ba_data_val(seckey),
|
Caml_ba_data_val(seckey),
|
||||||
NULL, NULL));
|
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];
|
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),
|
Caml_ba_data_val(buf),
|
||||||
&size,
|
&size,
|
||||||
Caml_ba_data_val(signature));
|
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));
|
return (ret == 0 ? Val_int(ret) : Val_int(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_signature_serialize_compact(value ctx, value buf, value signature) {
|
CAMLprim value caml_secp256k1_ecdsa_signature_serialize_compact(value ctx, value buf, value signature) {
|
||||||
secp256k1_ecdsa_signature_serialize_compact(Caml_ba_data_val(ctx),
|
secp256k1_ecdsa_signature_serialize_compact(Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(signature));
|
Caml_ba_data_val(signature));
|
||||||
return Val_unit;
|
return Val_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_recoverable_signature_parse_compact (value ctx, value buf, value signature, value recid) {
|
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 (Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ecdsa_recoverable_signature_parse_compact (Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(signature),
|
Caml_ba_data_val(signature),
|
||||||
Int_val(recid)));
|
Int_val(recid)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_sign_recoverable (value ctx, value buf, value seckey, value msg) {
|
CAMLprim value caml_secp256k1_ecdsa_sign_recoverable (value ctx, value buf, value seckey, value msg) {
|
||||||
return Val_bool(secp256k1_ecdsa_sign_recoverable (Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ecdsa_sign_recoverable (Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(msg),
|
Caml_ba_data_val(msg),
|
||||||
Caml_ba_data_val(seckey),
|
Caml_ba_data_val(seckey),
|
||||||
NULL, NULL));
|
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;
|
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),
|
Caml_ba_data_val(buf),
|
||||||
&recid,
|
&recid,
|
||||||
Caml_ba_data_val(signature));
|
Caml_ba_data_val(signature));
|
||||||
return Val_int(recid);
|
return Val_int(recid);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_recoverable_signature_convert(value ctx, value buf, value signature) {
|
CAMLprim value caml_secp256k1_ecdsa_recoverable_signature_convert(value ctx, value buf, value signature) {
|
||||||
secp256k1_ecdsa_recoverable_signature_convert(Caml_ba_data_val(ctx),
|
secp256k1_ecdsa_recoverable_signature_convert(Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(signature));
|
Caml_ba_data_val(signature));
|
||||||
return Val_unit;
|
return Val_unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAMLprim value ecdsa_recover(value ctx, value buf, value signature, value msg) {
|
CAMLprim value caml_secp256k1_ecdsa_recover(value ctx, value buf, value signature, value msg) {
|
||||||
return Val_bool(secp256k1_ecdsa_recover(Caml_ba_data_val(ctx),
|
return Val_bool(secp256k1_ecdsa_recover(Context_val(ctx),
|
||||||
Caml_ba_data_val(buf),
|
Caml_ba_data_val(buf),
|
||||||
Caml_ba_data_val(signature),
|
Caml_ba_data_val(signature),
|
||||||
Caml_ba_data_val(msg)));
|
Caml_ba_data_val(msg)));
|
||||||
|
6
vendors/ocaml-secp256k1/test/jbuild
vendored
6
vendors/ocaml-secp256k1/test/jbuild
vendored
@ -5,6 +5,10 @@
|
|||||||
(libraries (hex libsecp256k1 alcotest))))
|
(libraries (hex libsecp256k1 alcotest))))
|
||||||
|
|
||||||
(alias
|
(alias
|
||||||
((name runtest)
|
((name runtest-secp256k1)
|
||||||
(deps (test.exe))
|
(deps (test.exe))
|
||||||
(action (run ${<}))))
|
(action (run ${<}))))
|
||||||
|
|
||||||
|
(alias
|
||||||
|
((name runtest)
|
||||||
|
(deps ((alias runtest-secp256k1)))))
|
||||||
|
41
vendors/ocaml-secp256k1/test/test.ml
vendored
41
vendors/ocaml-secp256k1/test/test.ml
vendored
@ -1,13 +1,11 @@
|
|||||||
open Libsecp256k1
|
open Libsecp256k1
|
||||||
|
|
||||||
let assert_equal a b = assert (a = b)
|
|
||||||
|
|
||||||
module Num = struct
|
module Num = struct
|
||||||
open Internal
|
open Internal
|
||||||
open Num
|
open Num
|
||||||
let basic () =
|
let basic () =
|
||||||
let z = zero () in
|
let z = zero () in
|
||||||
assert_equal true (is_zero z)
|
Alcotest.(check bool "Num.is_zero" true (is_zero z))
|
||||||
|
|
||||||
let runtest =
|
let runtest =
|
||||||
[ "basic", `Quick, basic ;
|
[ "basic", `Quick, basic ;
|
||||||
@ -19,12 +17,12 @@ module Scalar = struct
|
|||||||
open Scalar
|
open Scalar
|
||||||
let basic () =
|
let basic () =
|
||||||
let z = zero () in
|
let z = zero () in
|
||||||
assert_equal true (is_zero z) ;
|
Alcotest.(check bool "Scalar.is_zero" true (is_zero z)) ;
|
||||||
(* set_int z 1 ; *)
|
(* set_int z 1 ; *)
|
||||||
let z = const ~d0:1L () in
|
let z = const ~d0:1L () in
|
||||||
assert_equal false (is_zero z) ;
|
Alcotest.(check bool "Scalar.is_zero" false (is_zero z)) ;
|
||||||
assert_equal false (is_even z) ;
|
Alcotest.(check bool "Scalar.is_even" false (is_even z)) ;
|
||||||
assert_equal true (is_one z)
|
Alcotest.(check bool "Scalar.is_one" true (is_one z))
|
||||||
|
|
||||||
let runtest =
|
let runtest =
|
||||||
[ "basic", `Quick, basic ;
|
[ "basic", `Quick, basic ;
|
||||||
@ -34,10 +32,9 @@ end
|
|||||||
module External = struct
|
module External = struct
|
||||||
open External
|
open External
|
||||||
let buffer_of_hex s =
|
let buffer_of_hex s =
|
||||||
let { Cstruct.buffer; off = _ ; len = _ } = Hex.to_cstruct (`Hex s) in
|
Cstruct.to_bigarray (Hex.to_cstruct (`Hex s))
|
||||||
buffer
|
|
||||||
|
|
||||||
let ctx = Context.create [ Sign ; Verify ]
|
let ctx = Context.create ()
|
||||||
|
|
||||||
let cstruct_testable =
|
let cstruct_testable =
|
||||||
Alcotest.testable Cstruct.hexdump_pp Cstruct.equal
|
Alcotest.testable Cstruct.hexdump_pp Cstruct.equal
|
||||||
@ -55,8 +52,7 @@ module External = struct
|
|||||||
assert_eq_cstruct sign_orig sign
|
assert_eq_cstruct sign_orig sign
|
||||||
|
|
||||||
let test_valid_signature _ =
|
let test_valid_signature _ =
|
||||||
let ctx = Context.create [Verify] in
|
let msg = buffer_of_hex
|
||||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex
|
|
||||||
"CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
"CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
||||||
let signature = Sign.read_der_exn ctx
|
let signature = Sign.read_der_exn ctx
|
||||||
(buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in
|
(buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in
|
||||||
@ -65,8 +61,7 @@ module External = struct
|
|||||||
assert (Sign.verify_exn ctx ~signature ~pk ~msg)
|
assert (Sign.verify_exn ctx ~signature ~pk ~msg)
|
||||||
|
|
||||||
let test_invalid_signature _ =
|
let test_invalid_signature _ =
|
||||||
let ctx = Context.create [Verify] in
|
let msg = buffer_of_hex
|
||||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex
|
|
||||||
"CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91" in
|
"CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91" in
|
||||||
let signature = Sign.read_der_exn ctx
|
let signature = Sign.read_der_exn ctx
|
||||||
(buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in
|
(buffer_of_hex "3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589") in
|
||||||
@ -98,27 +93,25 @@ module External = struct
|
|||||||
assert_eq_cstruct pubtrue pubkey_serialized
|
assert_eq_cstruct pubtrue pubkey_serialized
|
||||||
|
|
||||||
let test_sign _ =
|
let test_sign _ =
|
||||||
let ctx = Context.create [Sign] in
|
let msg = buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
||||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
|
||||||
let sk = Key.read_sk_exn ctx (buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530") 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 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)
|
assert (Sign.equal sign validsign)
|
||||||
|
|
||||||
let test_recover _ =
|
let test_recover _ =
|
||||||
let ctx = Context.create [Sign; Verify] in
|
let msg = buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
||||||
let msg = Sign.msg_of_bytes_exn @@ buffer_of_hex "CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90" in
|
|
||||||
let seckey = Key.read_sk_exn ctx (buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530") in
|
let seckey = Key.read_sk_exn ctx (buffer_of_hex "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530") in
|
||||||
let pubkey = Key.neuterize_exn ctx seckey in
|
let pubkey = Key.neuterize_exn ctx seckey in
|
||||||
let recoverable_sign = Sign.sign_recoverable_exn ctx ~sk:seckey msg in
|
let recoverable_sign = Sign.sign_recoverable_exn ctx ~sk:seckey msg in
|
||||||
let usual_sign = Sign.to_plain ctx recoverable_sign in
|
let usual_sign = Sign.to_plain ctx recoverable_sign in
|
||||||
assert (Sign.verify_exn ctx ~pk:pubkey ~signature:usual_sign ~msg);
|
assert (Sign.verify_exn ctx ~pk:pubkey ~signature:usual_sign ~msg);
|
||||||
let compact, recid = Sign.to_bytes_recid ctx recoverable_sign in
|
let recoverable_bytes = Sign.to_bytes ctx recoverable_sign in
|
||||||
let usual_sign' = Sign.read_exn ctx compact in
|
let usual_sign' = Sign.read_exn ctx recoverable_bytes in
|
||||||
assert (Sign.equal usual_sign' usual_sign) ;
|
assert (Sign.equal usual_sign' usual_sign) ;
|
||||||
let parsed = Sign.read_recoverable_exn ctx compact ~recid in
|
let recoverable_sign' = Sign.read_recoverable_exn ctx recoverable_bytes in
|
||||||
assert (Sign.equal parsed recoverable_sign);
|
assert (Sign.equal recoverable_sign' recoverable_sign);
|
||||||
match Sign.recover ctx ~signature:recoverable_sign ~msg with
|
match Sign.recover ctx ~signature:recoverable_sign msg with
|
||||||
| Error _ -> assert false
|
| Error _ -> assert false
|
||||||
| Ok recovered -> assert (Key.equal recovered pubkey)
|
| Ok recovered -> assert (Key.equal recovered pubkey)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user