Verified Commit 7a8fadb2 authored by Arthur B.'s avatar Arthur B. 🐻 Committed by Grégoire Henry

Crypto: add PVSS support

parent 7206ccd5
Pipeline #30295451 passed with stages
in 20 minutes and 26 seconds
......@@ -344,6 +344,8 @@ module Prefix = struct
(* 33 *)
let secp256k1_public_key = "\003\254\226\086" (* sppk(55) *)
let p256_public_key = "\003\178\139\127" (* p2pk(55) *)
let secp256k1_scalar = "\038\248\136" (* SSp(53) *)
let secp256k1_element = "\005\092\000" (* GSp(54) *)
(* 64 *)
let ed25519_secret_key = "\043\246\078\007" (* edsk(98) *)
......
......@@ -53,6 +53,8 @@ module Prefix : sig
val generic_signature: string
val chain_id: string
val secp256k1_element: string
val secp256k1_scalar: string
end
......
This diff is collapsed.
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
(** PVSS protocol, following
@see Schoenmakers, B., 1999:
A simple publicly verifiable secret sharing scheme
and its application to electronic voting. Lecture Notes in Computer Science,
pp.148-164.
@see https://www.win.tue.nl/~berry/papers/crypto99.pdf
The protocol is expressed as a functor parametrized by a cyclic group
of prime order. Algebraic properties are enforced at the type level,
whenever reasonably possible.
*)
module type CYCLIC_GROUP = sig
type t
include S.B58_DATA with type t := t
include S.ENCODER with type t := t
val name : string
module Z_m : Znz.ZN
val e : t
val g1 : t
val g2 : t
val ( * ) : t -> t -> t
val (=) : t -> t -> bool
val pow : t -> Z_m.t -> t
(** Binary representation *)
val to_bits : t -> String.t
val of_bits : String.t -> t option
end
(** PVSS construction, based on a cyclic group G of prime order *)
module type PVSS = sig
module type ENCODED = sig
type t
include S.B58_DATA with type t := t
include S.ENCODER with type t := t
end
module Commitment : ENCODED
module Encrypted_share : ENCODED
module Clear_share : ENCODED
module Public_key : ENCODED
module Secret_key : sig
include ENCODED
val to_public_key : t -> Public_key.t
end
type proof
val proof_encoding : proof Data_encoding.t
val dealer_shares_and_proof:
secret:Secret_key.t -> t:int -> public_keys:Public_key.t list ->
(Encrypted_share.t list * Commitment.t list * proof)
(** Lets a dealer share a secret with a set of participant by breaking it into
pieces, encrypting it with the participant's public keys, and publishing
these encrypted shares. Any t participants can reconstruct the secret. A
zero-knowledge proof is produced showing that the dealer correctly
followed the protocol, making the protocol publicly verifiable. *)
val check_dealer_proof:
Encrypted_share.t list -> Commitment.t list -> proof:proof ->
public_keys:Public_key.t list -> bool
(** Checks the proof produced by the dealer, given the encrypted shares,
the commitment list, the proof, and the participant's public keys. *)
val reveal_share : Encrypted_share.t -> secret_key:Secret_key.t
-> public_key:Public_key.t -> Clear_share.t * proof
(** Lets a participant provably decrypt an encrypted share. *)
val check_revealed_share:
Encrypted_share.t -> Clear_share.t -> public_key:Public_key.t -> proof
-> bool
(** Checks that the participant honestly decrypted its share. *)
val reconstruct: Clear_share.t list -> int list -> Public_key.t
end
module MakePvss : functor (G: CYCLIC_GROUP) -> PVSS
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
open Secp256k1_group
module G : Pvss.CYCLIC_GROUP = struct
module Z_m = struct
include Group.Scalar
let n = Group.order
let ( + ) = Group.Scalar.add
let ( * ) = Group.Scalar.mul
let ( - ) = Group.Scalar.sub
let ( = ) = Group.Scalar.equal
let inv = Group.Scalar.inverse
end
include Group
let name = "secp256k1"
(* This pvss algorithm assumes the public keys of the participants receiving
shares are based on g2, so we set g2 to Group.g to match regular Secp256k1
public keys.
*)
let g1 = Group.h
let g2 = Group.g
(* We use a multiplicative notation in the pvss module, but
secp256k1 usually uses an additive notation. *)
let ( * ) = Group.(( + ))
let pow x n = Group.mul n x
let of_bits b =
try
Some (Group.of_bits_exn b)
with _ -> None
end
include Pvss.MakePvss (G)
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
include Pvss.PVSS
......@@ -107,6 +107,22 @@ module type ENCODER = sig
end
module type PVSS = sig
type proof
module Clear_share : sig type t end
module Commitment : sig type t end
module Encrypted_share : sig type t end
module Public_key : sig
type t
include B58_DATA with type t := t
include ENCODER with type t := t
end
end
module type INDEXES = sig
type t
......
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
module Sp = Libsecp256k1.Internal
module type SCALAR_SIG = sig
type t
include S.B58_DATA with type t := t
include S.ENCODER with type t := t
val zero : t
val one : t
val of_Z : Z.t -> t
val to_Z : t -> Z.t
val of_int : int -> t
val add: t -> t -> t
val mul: t -> t -> t
val negate: t -> t
val sub : t -> t -> t
val of_bits_exn: string -> t
val to_bits: t -> string
val inverse: t -> t option
val pow: t -> Z.t -> t
val equal : t -> t -> bool
end
module Group : sig
val order: Z.t
module Scalar : SCALAR_SIG
type t
include S.B58_DATA with type t := t
include S.ENCODER with type t := t
val e: t
val g: t
val h: t
val of_coordinates: x:Z.t -> y:Z.t -> t
val of_bits_exn: string -> t
val to_bits: t -> string
val mul: Scalar.t -> t -> t
val (+): t -> t -> t
val (-): t -> t -> t
val (=): t -> t -> bool
end = struct
let order = Z.of_string_base 16 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
let string_rev s =
let len = String.length s in
String.init len (fun i -> s.[len - 1 - i])
let b32_of_Z z =
let cs = Cstruct.create 32 in
let bits = Z.to_bits z in
let length = (min 32 (String.length bits)) in
let bits = String.sub bits 0 length in
let bits = string_rev bits in
Cstruct.blit_from_string bits 0 cs (32 - length) length;
cs
let z_of_b32 b =
b |> Cstruct.to_string |> string_rev |> Z.of_bits
module Scalar : SCALAR_SIG with type t = Sp.Scalar.t = struct
type t = Sp.Scalar.t
let zero = Sp.Scalar.zero ()
let one = Sp.Scalar.one ()
let equal x y = Sp.Scalar.equal x y
let of_Z z =
let z = Z.erem z order in
let r = Sp.Scalar.const () in
let cs = b32_of_Z z in
let _ = Sp.Scalar.set_b32 r cs in r
let to_Z s =
let cs = Cstruct.create 32 in
Sp.Scalar.get_b32 cs s; cs |> z_of_b32
let of_int i = i |> Z.of_int |> of_Z
let pow t n =
Z.powm (to_Z t) n order |> of_Z
let add x y =
let r = Sp.Scalar.const () in
let _ = Sp.Scalar.add r x y in r
let mul x y =
let r = Sp.Scalar.const () in
Sp.Scalar.mul r x y; r
let negate x =
let r = Sp.Scalar.const () in
Sp.Scalar.negate r x; r
let sub x y =
add x (negate y)
let of_bits_exn bits =
let r = Sp.Scalar.const () in
(* trim to 32 bytes *)
let cs = Cstruct.create 32 in
Cstruct.blit_from_string bits 0 cs 0 (min (String.length bits) 32);
(* ignore overflow condition, it's always 0 based on the c-code *)
let _ = Sp.Scalar.set_b32 r cs in r
(* TODO, check that we are less than the order *)
let to_bits x =
let c = Cstruct.create 32 in
Sp.Scalar.get_b32 c x; Cstruct.to_string c
let inverse x =
if x = zero then
None else
let r = Sp.Scalar.const () in
Sp.Scalar.inverse r x; Some r
type Base58.data +=
| Data of t
let b58check_encoding =
Base58.register_encoding
~prefix: Base58.Prefix.secp256k1_scalar
~length: 32
~to_raw: to_bits
~of_raw: (fun s -> try Some (of_bits_exn s) with _ -> None)
~wrap: (fun x -> Data x)
let title = "Secp256k1_group.Scalar"
let name = "Anscalar for the secp256k1 group"
include Helpers.MakeB58(struct
type nonrec t = t
let title = title
let name = name
let b58check_encoding = b58check_encoding
end)
include Helpers.MakeEncoder(struct
type nonrec t = t
let name = name
let title = title
let raw_encoding = Data_encoding.(conv to_bits of_bits_exn string)
let to_b58check = to_b58check
let to_short_b58check = to_short_b58check
let of_b58check = of_b58check
let of_b58check_opt = of_b58check_opt
let of_b58check_exn = of_b58check_exn
end)
end
type t = Sp.Group.Jacobian.t
(* type ge = Sp.Group.ge *)
let field_of_Z z =
let fe = Sp.Field.const () in
let cs = b32_of_Z z in
let _ = Sp.Field.set_b32 fe cs in fe
let group_of_jacobian j =
let r = Sp.Group.of_fields () in
Sp.Group.Jacobian.get_ge r j; r
let jacobian_of_group g =
let j = Sp.Group.Jacobian.of_fields () in
Sp.Group.Jacobian.set_ge j g; j
let of_coordinates ~x ~y =
Sp.Group.of_fields
~x:(field_of_Z x) ~y:(field_of_Z y) () |> jacobian_of_group
let e =
Sp.Group.Jacobian.of_fields ~infinity:true ()
let g =
let gx = Z.of_string "55066263022277343669578718895168534326250603453777594175500187360389116729240"
and gy = Z.of_string "32670510020758816978083085130507043184471273380659243275938904335757337482424" in
of_coordinates ~x:gx ~y:gy
(* To obtain the second generator, take the sha256 hash of the decimal representation of g1_y
python -c "import hashlib;print int(hashlib.sha256('32670510020758816978083085130507043184471273380659243275938904335757337482424').hexdigest(),16)"
*)
let h =
let hx = Z.of_string "54850469061264194188802857211425616972714231399857248865148107587305936171824"
and hy = Z.of_string "6558914719042992724977242403721980463337660510165027616783569279181206179101" in
of_coordinates ~x:hx ~y:hy
let (+) x y =
let r = Sp.Group.Jacobian.of_fields () in
Sp.Group.Jacobian.add_var r x y; r
let (-) x y =
let neg_y = Sp.Group.Jacobian.of_fields () in
Sp.Group.Jacobian.neg neg_y y; x + neg_y
let (=) x y = Sp.Group.Jacobian.is_infinity (x - y)
let mul s g =
let r = Sp.Group.Jacobian.of_fields () in
Sp.Group.Jacobian.mul r (group_of_jacobian g) s; r
let to_bits j =
let x = group_of_jacobian j
and buf = Cstruct.create 33 in
let cs = (Sp.Group.to_pubkey ~compress:true buf x) in
Cstruct.to_string cs
let of_bits_exn bits =
let buf = Cstruct.of_string bits
and x = Sp.Group.of_fields () in
Sp.Group.from_pubkey x buf;
x |> jacobian_of_group
module Encoding = struct
type Base58.data +=
| Data of t
let title = "Secp256k1_group.Group"
let name = "An element of secp256k1"
let b58check_encoding =
Base58.register_encoding
~prefix: Base58.Prefix.secp256k1_element
~length: 33
~to_raw: to_bits
~of_raw: (fun s -> try Some (of_bits_exn s) with _ -> None)
~wrap: (fun x -> Data x)
include Helpers.MakeB58(
struct
type nonrec t = t
let title = title
let name = name
let b58check_encoding = b58check_encoding
end)
include Helpers.MakeEncoder(
struct
type nonrec t = t
let name = name
let title = title
let raw_encoding = Data_encoding.(conv to_bits of_bits_exn string)
let to_b58check = to_b58check
let to_short_b58check = to_short_b58check
let of_b58check = of_b58check
let of_b58check_opt = of_b58check_opt
let of_b58check_exn = of_b58check_exn
end
)
end
include Encoding
end
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
(** Type for the group of integers modulo the order of the curve ℤ/pℤ *)
module type SCALAR_SIG = sig
(** Element of the scalar group *)
type t
include S.B58_DATA with type t := t
include S.ENCODER with type t := t
val zero : t
val one : t
val of_Z : Z.t -> t
val to_Z : t -> Z.t
val of_int : int -> t
val add: t -> t -> t
val mul: t -> t -> t
val negate: t -> t
val sub: t -> t -> t
val of_bits_exn: string -> t
val to_bits: t -> string
val inverse: t -> t option
(** Modular exponentiation*)
val pow: t -> Z.t -> t
val equal: t -> t -> bool
end
module Group : sig
type t
include S.B58_DATA with type t := t
include S.ENCODER with type t := t
val order: Z.t
module Scalar : SCALAR_SIG
val e: t
val g : t
val h : t
val of_coordinates: x:Z.t -> y:Z.t -> t
val of_bits_exn: string -> t
val to_bits: t -> string
val mul: Scalar.t -> t -> t
val (+): t -> t -> t
val (-): t -> t -> t
val (=): t -> t -> bool
end
......@@ -2,21 +2,25 @@
(names test_merkle
test_base58
test_ed25519
test_blake2b)
test_blake2b
test_pvss)
(libraries tezos-stdlib
tezos-crypto
tezos-data-encoding
alcotest)
(flags (:standard -w -9-32
-safe-string
-open Tezos_stdlib
-open Tezos_crypto)))
-open Tezos_crypto
-open Tezos_data_encoding)))
(alias
(name buildtest)
(deps test_merkle.exe
test_base58.exe
test_ed25519.exe
test_blake2b.exe))
test_blake2b.exe
test_pvss.exe))
(alias
(name runtest_merkle)
......@@ -34,12 +38,17 @@
(name runtest_blake2b)
(action (run %{exe:test_blake2b.exe})))
(alias
(name runtest_pvss)
(action (run %{exe:test_pvss.exe})))
(alias
(name runtest)
(deps (alias runtest_merkle)
(alias runtest_base58)
(alias runtest_ed25519)
(alias runtest_blake2b)))
(alias runtest_blake2b)
(alias runtest_pvss)))
(alias
(name runtest_indent)
......
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
(* pvss tests here *)
module Pvss = Pvss_secp256k1
module Sp = Secp256k1_group
module Setup : sig
val shares : Pvss.Encrypted_share.t list
val commitments: Pvss.Commitment.t list
val proof: Pvss.proof
val secret_scalar : Sp.Group.Scalar.t
val secret: Pvss.Secret_key.t
val public_secret: Pvss.Public_key.t
val other_shares : Pvss.Encrypted_share.t list
val other_commitments: Pvss.Commitment.t list
val other_proof: Pvss.proof
val other_secret: Pvss.Secret_key.t
type keypair = {secret_key: Pvss.Secret_key.t; public_key: Pvss.Public_key.t}
val public_keys : Pvss.Public_key.t list
val keypairs : keypair list
val reveals : (Pvss.Encrypted_share.t * (Pvss.Clear_share.t * Pvss.proof)) list
val convert_encoding : 'a Data_encoding.t -> 'b Data_encoding.t -> 'a -> 'b
val group_encoding : Sp.Group.t Data_encoding.t
end = struct
type keypair = {secret_key: Pvss.Secret_key.t; public_key: Pvss.Public_key.t}
let group_encoding = Data_encoding.(conv Sp.Group.to_bits Sp.Group.of_bits_exn string)
let scalar_encoding = Data_encoding.(conv Sp.Group.Scalar.to_bits Sp.Group.Scalar.of_bits_exn string)
let convert_encoding de1 de2 x =
Data_encoding.Binary.of_bytes_exn de2
(Data_encoding.Binary.to_bytes_exn de1 x)