Commit 86b06ce9 authored by Stephane Glondu's avatar Stephane Glondu
Browse files

election-tool

parent 93ae399f
minimal.otarget
src/lib/lib.cma
src/web/server.cma
api.docdir/index.html
tests/legacy/README.html
README.html
src/bin/trustee-keygen.native
src/bin/credgen.native
stuff/template.native
src/bin/trustee-keygen.native
src/bin/credgen.native
src/bin/election-tool.native
......@@ -31,10 +31,6 @@ let public_key_of_token uuid x =
let y = G.(g **~ x) in
Z.to_string y
let option_map f = function
| Some x -> Some (f x)
| None -> None
(* Argument parsing *)
let dir = ref (Sys.getcwd ())
......
open Util
open Serializable_t
(* Command-line arguments *)
let dir = ref (Sys.getcwd ())
let sk_file = ref None
let speclist = Arg.([
"--dir", String (fun s -> dir := s), "chdir to that directory first";
"--decrypt", String (fun s -> sk_file := Some s), "do partial decryption";
])
let usage_msg =
Printf.sprintf "Usage: %s [--dir <dir>] [--decrypt <privkey>]" Sys.argv.(0)
let anon_fun x =
Printf.eprintf "I do not know what to do with %s!\n" x;
exit 1
let () = Arg.parse speclist anon_fun usage_msg
(* Helpers *)
let load_from_file of_string filename =
if Sys.file_exists filename then (
Printf.eprintf "Loading %s...\n%!" filename;
let ic = open_in filename in
let lines =
let rec loop lines =
match (try Some (input_line ic) with End_of_file -> None) with
| Some "" -> loop lines
| Some line -> loop (line::lines)
| None -> lines
in loop []
in
close_in ic;
Some (List.rev_map of_string lines)
) else None
let read_number = Serializable_builtin_j.read_number
let save_to filename writer x =
let oc = open_out filename in
let ob = Bi_outbuf.create_channel_writer oc in
writer ob x;
Bi_outbuf.flush_channel_writer ob;
close_out oc;;
let () = Sys.chdir !dir
(* Load and check election *)
let election, election_fingerprint =
match (load_from_file (fun l ->
Serializable_j.(election_of_string read_ff_pubkey l),
sha256_b64 l
) "election.json") with
| Some [e] -> e
| _ -> failwith "invalid election file"
let {g; p; q; y} = election.e_public_key
let () = assert (Election.check_finite_field ~p ~q ~g)
module G = (
val Election.finite_field ~g ~p ~q : Signatures.GROUP with type t = Z.t
)
module M = Election.MakeSimpleMonad(G)
(* Load and check trustee keys, if present *)
module KG = Election.MakeSimpleDistKeyGen(G)(M);;
let public_keys_with_pok =
load_from_file (
Serializable_j.trustee_public_key_of_string read_number
) "public_keys.jsons" |> option_map Array.of_list
let () =
match public_keys_with_pok with
| Some pks ->
assert (Array.forall KG.check pks);
let y' = KG.combine pks in
assert (y =% y')
| None -> ()
let public_keys =
option_map (
Array.map (fun pk -> pk.trustee_public_key)
) public_keys_with_pok
(* Finish setting up the election *)
let metadata =
match (load_from_file Serializable_j.metadata_of_string "metadata.json") with
| Some [m] -> Some m
| Some _ -> failwith "invalid metadata.json"
| None -> None
module P = struct
module G = G
let params = { election with e_public_key = y }
let metadata = metadata
let public_keys = lazy (
match public_keys with
| Some pks -> pks
| None -> failwith "missing public keys"
)
let fingerprint = election_fingerprint
end
module E = Election.MakeElection(P)(M);;
(* Load ballots, if present *)
module ZSet = Set.Make(Z)
let public_creds =
load_from_file Z.of_string "public_creds.txt" |>
option_map (fun xs ->
List.fold_left (fun accu x ->
ZSet.add x accu
) ZSet.empty xs
)
let ballots =
load_from_file (fun line ->
Serializable_j.ballot_of_string read_number line,
sha256_b64 line
) "ballots.jsons"
let check_signature_present =
match public_creds with
| Some creds -> (fun b ->
match b.signature with
| Some s -> ZSet.mem s.s_commitment creds
| None -> false
)
| None -> (fun _ -> true)
let vote (b, hash) =
if check_signature_present b && E.check_ballot b
then M.cast b "anonymous" ()
else Printf.ksprintf failwith "ballot %s failed tests" hash
let () = ballots |> option_map (List.iter vote) |> ignore
let encrypted_tally = lazy (
match ballots with
| None -> failwith "ballots.jsons is missing"
| Some _ ->
M.fold_ballots (fun b t ->
M.return (E.combine_ciphertexts (E.extract_ciphertext b) t)
) E.neutral_ciphertext ()
)
let () =
match !sk_file with
| Some fn ->
(match load_from_file (Serializable_builtin_j.number_of_string) fn with
| Some [sk] ->
let pk = G.(g **~ sk) in
let () =
match public_keys with
| Some pks ->
if Array.forall (fun x -> not (x =% pk)) pks then (
Printf.eprintf "Warning: your key is not present in public_keys.jsons!\n";
)
| None -> ()
in
let tally = Lazy.force encrypted_tally in
let factor =
E.compute_factor tally sk ()
in
assert (E.check_factor tally pk factor);
print_endline (
Serializable_j.string_of_partial_decryption
Serializable_builtin_j.write_number
factor
)
| _ -> failwith "invalid private key file"
)
| None -> ()
(* Load or compute result, and check it *)
let result =
load_from_file (
Serializable_j.result_of_string read_number
) "result.json"
let () =
match result with
| Some [result] ->
assert (E.check_result result)
| Some _ ->
failwith "invalid result file"
| None ->
let factors = load_from_file (
Serializable_j.partial_decryption_of_string read_number
) "partial_decryptions.jsons" |> option_map Array.of_list in
match factors with
| Some factors ->
let tally = Lazy.force encrypted_tally in
assert (Array.forall2 (E.check_factor tally) (Lazy.force P.public_keys) factors);
let result = E.combine_factors (M.turnout ()) tally factors in
assert (E.check_result result);
save_to "result.json" (
Serializable_j.write_result Serializable_builtin_j.write_number
) result;
Printf.eprintf "result.json written\n%!"
| None -> ()
(* The end *)
let () = Printf.eprintf "All checks passed!\n%!"
......@@ -126,3 +126,7 @@ let sha256_b64 x = Cryptokit.(x |>
hash_string (Hash.sha256 ()) |>
transform_string (Base64.encode_compact ())
)
let option_map f = function
| Some x -> Some (f x)
| None -> None
......@@ -31,3 +31,5 @@ val list_join : 'a -> 'a list -> 'a list
val sha256_hex : string -> string
val sha256_b64 : string -> string
val option_map : ('a -> 'b) -> 'a option -> 'b option
#!/bin/sh
set -e
ocamlbuild -quiet src/bin/election-tool.native
exec _build/src/bin/election-tool.native "$@"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment