Skip to content

Commit

Permalink
Merge pull request #2624 from danielSanchezQ/jcli-tally-decrypt
Browse files Browse the repository at this point in the history
Jcli tally decrypt with shares tool
  • Loading branch information
Daniel Sanchez committed Oct 26, 2020
2 parents 149a32c + ddd454d commit d0c1137
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 7 deletions.
8 changes: 5 additions & 3 deletions jcli/src/jcli_app/vote/mod.rs
@@ -1,8 +1,8 @@
use crate::jcli_app::utils::output_file::{self, OutputFile};
mod committee;
mod common_reference_string;
mod decryption_share;
mod encrypting_vote_key;
mod tally;

use structopt::StructOpt;
use thiserror::Error;
Expand Down Expand Up @@ -36,6 +36,8 @@ pub enum Error {
EncryptedTallyRead,
#[error("failed to read decryption key bytes")]
DecryptionKeyRead,
#[error("failed to read share bytes")]
DecryptionShareRead,
#[error(transparent)]
FormatError(#[from] crate::jcli_app::utils::output_format::Error),
#[error(transparent)]
Expand All @@ -52,7 +54,7 @@ pub enum Vote {
/// Build an encryption vote key
CRS(common_reference_string::CRS),
/// Create decryption share for private voting tally.
TallyDecryptionShare(decryption_share::TallyDecryptionShare),
Tally(tally::Tally),
}

impl Vote {
Expand All @@ -61,7 +63,7 @@ impl Vote {
Vote::Committee(cmd) => cmd.exec(),
Vote::EncryptingVoteKey(cmd) => cmd.exec(),
Vote::CRS(cmd) => cmd.exec(),
Vote::TallyDecryptionShare(cmd) => cmd.exec(),
Vote::Tally(cmd) => cmd.exec(),
}
}
}
Expand Down
71 changes: 71 additions & 0 deletions jcli/src/jcli_app/vote/tally/decrypt_shares.rs
@@ -0,0 +1,71 @@
use super::Error;
use crate::jcli_app::utils::{io, OutputFormat};
use chain_vote::EncryptedTally;
use serde::Serialize;
use std::io::BufRead;
use std::path::PathBuf;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct TallyDecryptWithAllShares {
/// The path to hex-encoded encrypted tally state. If this parameter is not
/// specified, the encrypted tally state will be read from the standard
/// input.
#[structopt(long = "tally")]
encrypted_tally: Option<PathBuf>,
/// The minimum number of shares needed for decryption
#[structopt(long = "threshold", default_value = "3")]
threshold: usize,
/// Maximum supported number of votes
#[structopt(long = "maxvotes")]
max_votes: u64,
/// Computing table cache size, usually total_votes/number_of_options
#[structopt(long = "table_size")]
table_size: usize,
/// The path to encoded necessary shares. If this parameter is not
/// specified, the shares will be read from the standard input.
#[structopt(long = "shares")]
shares: Option<PathBuf>,
#[structopt(flatten)]
output_format: OutputFormat,
}

#[derive(Serialize)]
struct Output {
result: Vec<Option<u64>>,
}

impl TallyDecryptWithAllShares {
pub fn exec(&self) -> Result<(), Error> {
let encrypted_tally_hex = io::read_line(&self.encrypted_tally)?;
let encrypted_tally_bytes = hex::decode(encrypted_tally_hex)?;
let encrypted_tally =
EncryptedTally::from_bytes(&encrypted_tally_bytes).ok_or(Error::EncryptedTallyRead)?;

let mut shares_file = io::open_file_read(&self.shares)?;

let shares: Vec<chain_vote::TallyDecryptShare> = {
let mut shares = Vec::with_capacity(self.threshold);
for _ in 0..self.threshold {
let mut buff = String::new();
&shares_file.read_line(&mut buff);
chain_vote::TallyDecryptShare::from_bytes(&hex::decode(buff)?)
.ok_or(Error::DecryptionShareRead)?;
}
shares
};

let state = encrypted_tally.state();
let result = chain_vote::result(self.max_votes, self.table_size, &state, &shares);
let output = self
.output_format
.format_json(serde_json::to_value(Output {
result: result.votes,
})?)?;

println!("{}", output);

Ok(())
}
}
Expand Up @@ -9,7 +9,7 @@ use structopt::StructOpt;
/// The outputs are provided as hex-encoded byte sequences.
#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub struct TallyDecryptionShare {
pub struct TallyGenerateDecryptionShare {
/// The path to hex-encoded encrypted tally state. If this parameter is not
/// specified, the encrypted tally state will be read from the standard
/// input.
Expand All @@ -28,7 +28,7 @@ struct Output {
share: String,
}

impl TallyDecryptionShare {
impl TallyGenerateDecryptionShare {
pub fn exec(&self) -> Result<(), Error> {
let encrypted_tally_hex = io::read_line(&self.encrypted_tally)?;
let encrypted_tally_bytes = hex::decode(encrypted_tally_hex)?;
Expand All @@ -43,14 +43,12 @@ impl TallyDecryptionShare {
};

let (state, share) = encrypted_tally.finish(&decryption_key);

let output = self
.output_format
.format_json(serde_json::to_value(Output {
state: hex::encode(state.to_bytes()),
share: hex::encode(share.to_bytes()),
})?)?;

println!("{}", output);

Ok(())
Expand Down
23 changes: 23 additions & 0 deletions jcli/src/jcli_app/vote/tally/mod.rs
@@ -0,0 +1,23 @@
mod decrypt_shares;
mod decryption_tally;

use super::Error;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub enum Tally {
/// Create decryption share for private voting tally.
GenerateDecryptionShare(decryption_tally::TallyGenerateDecryptionShare),
/// Decrypt a tally with shares
DecryptWithShares(decrypt_shares::TallyDecryptWithAllShares),
}

impl Tally {
pub fn exec(self) -> Result<(), Error> {
match self {
Tally::GenerateDecryptionShare(cmd) => cmd.exec(),
Tally::DecryptWithShares(cmd) => cmd.exec(),
}
}
}

0 comments on commit d0c1137

Please sign in to comment.