Benaloh Challenge

Build Status codecov

Implements the Benaloh Challenge (also known as an Interactive Device Challenge), a crytographic technique to ensure the honesty of an untrusted device. While orignially conceived in the context of voting using an electronic device, it is useful for all untrusted computations that are deterministic with the exception of using an RNG. Most cryptography fits in this category.

More details on the protocol can be found here: - Ballot Casting Assurance via Voter-Initiated Poll Station Auditing by Josh Benaloh, 2007 [pdf] - Proof of Vote: An end-to-end verifiable digital voting protocol using distributed ledger technology by Becker et al, 2018 - section 3.2.7 [[pdf](https://github.com/votem/proof-of-vote/raw/master/proof-of-vote-whitepaper.pdf)]

Example

```rust use benaloh_challenge; use rand::Rng; use sha2::Sha256; use rsa::padding::PaddingScheme; use rsa::{PublicKey, RSAPrivateKey, RSAPublicKey};

// Untrusted computation that is deterministic with the exception of an RNG // For this example we encrypt a vote for an election using RSA. fn untrusted_computation(rng: &mut R, key: &RSAPublicKey, message: &[u8]) -> Vec { let ciphertext = key.encrypt(rng, PaddingScheme::PKCS1v15, message).unwrap(); return ciphertext; };

let mut rng = rand::threadrng(); let mut hasher = Sha256::new(); let publickey = RSAPrivateKey::new(&mut rng, 512).unwrap().extract_public(); let vote = b"Barak Obama";

let mut challenge = benalohchallenge::Challenge::new(&mut rng, |rng: _| { untrustedcomputation(rng, &public_key, vote) });

// Get the commitment let commitment = challenge.commit(&mut hasher);

// Reveal the secret random factors used in the encryption. This also invalidates the results. let revealed = challenge.challenge();

// Check the commitment on a different (trusted) device. benalohchallenge::checkcommitment(&mut hasher, &commitment, &revealed, |rng: | { untrustedcomputation(rng, &public_key, vote) })?;

// In a real voting application, the user would be given the choice to change their vote here.

// Get another commitment challenge.commit(&mut hasher);

// We could challenge here again if we wanted // but instead we get the results, discarding the random factors. let ciphertext = challenge.into_results(); ```