diff --git a/lib/crypto.ml b/lib/crypto.ml index f1605517f9839e763cf0686def99bbe5bf918a62..012197da0b2eff5cbe0d2219d60f7ef1101292b2 100644 --- a/lib/crypto.ml +++ b/lib/crypto.ml @@ -42,6 +42,7 @@ let finite_field ~p ~q ~g = let ( =~ ) = equal let check x = check_modulo p x && x **~ q =~ one let hash xs = hashZ (map_and_concat_with_commas Z.to_string xs) + let compare = Z.compare end in (module G : Crypto_sigs.GROUP with type t = Z.t) else invalid_arg "Invalid parameters for a multiplicative subgroup of finite field" @@ -227,9 +228,32 @@ module MakeHomomorphicElection (P : Crypto_sigs.ELECTION_PARAMS) = struct type result = public_key Serializable_t.result - let combine_factors nb_tallied c fs = assert false + let combine_factors nb_tallied encrypted_tally partial_decryptions = + let dummy = Array.mmap (fun _ -> G.one) encrypted_tally in + let factors = Array.fold_left (fun a b -> + Array.mmap2 ( *~ ) a b.decryption_factors + ) dummy partial_decryptions in + let exp_results = Array.mmap2 (fun {beta; _} f -> + beta / f + ) encrypted_tally factors in + let log = + let module GMap = Map.Make(G) in + let rec loop i cur accu = + if i < nb_tallied + then loop (succ i) (cur *~ g) (GMap.add cur i accu) + else accu + in + let map = loop 0 G.one GMap.empty in + fun x -> + try + GMap.find x map + with Not_found -> + invalid_arg "Cannot compute result" + in + let result = Array.mmap log exp_results in + {nb_tallied; encrypted_tally; partial_decryptions; result} let check_result r = assert false - let extract_tally r = assert false + let extract_tally r = r.result end diff --git a/lib/crypto_sigs.mli b/lib/crypto_sigs.mli index 0a7000fc36a6083a3f9d74e8d7e13fd03e99efe5..d91c13b163d9803bb8b5689bc522b03ca8c98dc9 100644 --- a/lib/crypto_sigs.mli +++ b/lib/crypto_sigs.mli @@ -35,6 +35,9 @@ module type GROUP = sig val hash : t array -> Z.t (** Hash an array of elements into an integer mod [q]. *) + + val compare : t -> t -> int + (** A total ordering over the elements of the group. *) end (** Parameters for an election. *) @@ -126,8 +129,8 @@ module type HOMOMORPHIC = sig val combine_factors : int -> ciphertext -> factor array -> result (** Combine the encrypted tally and the factors from all trustees to - produce the election result. This first argument is the number - of tallied ballots. *) + produce the election result. The first argument is the number of + tallied ballots. May raise [Invalid_argument]. *) val check_result : result -> bool diff --git a/lib/serializable.atd b/lib/serializable.atd index 97f10d7514a2179dce42b88c4af18cee65b481d9..3715746555a1d1434fbd953652c4bcf18d4c729f 100644 --- a/lib/serializable.atd +++ b/lib/serializable.atd @@ -62,6 +62,7 @@ type 'a partial_decryption = { } type 'a result = { + nb_tallied : int; encrypted_tally : 'a ciphertext list list ; partial_decryptions : 'a partial_decryption list ; result : int list list ; diff --git a/lib/serializable_compat.ml b/lib/serializable_compat.ml index cb85c81b30bb15f644e98a4a91af782d01b640c0..3bfe73a57b96aae143d731b23c2d2d8603e568aa 100644 --- a/lib/serializable_compat.ml +++ b/lib/serializable_compat.ml @@ -50,6 +50,16 @@ let of_partial_decryption p = let open Serializable_t in {decryption_factors; decryption_proofs} +let of_result r = + let {encrypted_tally; partial_decryptions; result} = r in + let nb_tallied = encrypted_tally.num_tallied in + let encrypted_tally = encrypted_tally.tally in + let partial_decryptions = + Array.map of_partial_decryption partial_decryptions + in + let open Serializable_t in + {nb_tallied; encrypted_tally; partial_decryptions; result} + module type COMPAT = sig type t val to_ballot : t Serializable_t.ballot -> t ballot diff --git a/lib/serializable_compat.mli b/lib/serializable_compat.mli index 527008cfb1c9a8602bbc8df330acced7b7865d2c..44c3aef28e5c8b8608a6452abec31a554f4e3983 100644 --- a/lib/serializable_compat.mli +++ b/lib/serializable_compat.mli @@ -6,6 +6,7 @@ val of_election : 'a election -> 'a Serializable_t.election val of_ballot : 'a ballot -> 'a Serializable_t.ballot val of_partial_decryption : 'a partial_decryption -> 'a Serializable_t.partial_decryption +val of_result : 'a result -> 'a Serializable_t.result module type COMPAT = sig type t