pub struct EncryptedChoice<G: Group, S: ProveSum<G>> { /* private fields */ }
Expand description

Zero or more encrypted choices from n options (n >= 1) together with zero-knowledge proofs of correctness.

§Construction

The choice is represented as a vector of n choice ciphertexts of Boolean values (0 or 1), where the ciphertexts for the chosen options encrypt 1 and the other ciphertexts encrypt 0. This ensures that multiple EncryptedChoices can be added (e.g., within a voting protocol).

Zero-knowledge proofs are:

  • A RingProof attesting that all n ciphertexts encrypt 0 or 1. This proof can be obtained via Self::range_proof().
  • A LogEqualityProof attesting that the encrypted values sum up to 1. Combined with the range proof, this means that exactly one of encrypted values is 1, and all others are 0. This proof can be obtained via Self::sum_proof(). This proof is absent for a MultiChoice setup (sum_proof() just returns ()).

§Examples

§Single-choice setup

let mut rng = thread_rng();
let (pk, sk) = Keypair::<Ristretto>::generate(&mut rng).into_tuple();
let choice_params = ChoiceParams::single(pk, 5);

let choice = 2;
let enc = EncryptedChoice::single(&choice_params, choice, &mut rng);
let choices = enc.verify(&choice_params)?;

// `choices` is a slice of 5 Boolean value ciphertexts
assert_eq!(choices.len(), 5);
let lookup_table = DiscreteLogTable::new(0..=1);
for (idx, &v) in choices.iter().enumerate() {
    assert_eq!(
        sk.decrypt(v, &lookup_table),
        Some((idx == choice) as u64)
    );
}

§Multi-choice setup

let mut rng = thread_rng();
let (pk, sk) = Keypair::<Ristretto>::generate(&mut rng).into_tuple();
let choice_params = ChoiceParams::multi(pk, 5);

let choices = [true, false, true, true, false];
let enc = EncryptedChoice::new(&choice_params, &choices, &mut rng);
let recovered_choices = enc.verify(&choice_params)?;

let lookup_table = DiscreteLogTable::new(0..=1);
for (idx, &v) in recovered_choices.iter().enumerate() {
    assert_eq!(sk.decrypt(v, &lookup_table), Some(choices[idx] as u64));
}

Implementations§

source§

impl<G: Group> EncryptedChoice<G, SingleChoice>

source

pub fn single<R: CryptoRng + RngCore>( params: &ChoiceParams<G, SingleChoice>, choice: usize, rng: &mut R ) -> Self

Creates a new encrypted choice.

§Panics

Panics if choice exceeds the maximum index allowed by params.

source§

impl<G: Group, S: ProveSum<G>> EncryptedChoice<G, S>

source

pub fn new<R: CryptoRng + RngCore>( params: &ChoiceParams<G, S>, choices: &[bool], rng: &mut R ) -> Self

Creates an encrypted multi-choice.

For a SingleChoice polling, it is caller’s responsibility to ensure that choices contains exactly one true value; otherwise, the produced proof will not verify.

§Panics

Panics if the length of choices differs from the number of options specified in params.

source

pub fn verify( &self, params: &ChoiceParams<G, S> ) -> Result<&[Ciphertext<G>], ChoiceVerificationError>

Verifies the zero-knowledge proofs in this choice and returns Boolean ciphertexts for all options.

§Errors

Returns an error if the choice is malformed or its proofs fail verification.

source

pub fn len(&self) -> usize

Returns the number of encrypted choices. This value is equal to ChoiceParams::options_count() with which the encryption was created.

source

pub fn choices_unchecked(&self) -> &[Ciphertext<G>]

Returns ciphertexts for all options without checking the validity of this choice.

source

pub fn range_proof(&self) -> &RingProof<G>

Returns the range proof for the choice ciphertexts.

source

pub fn sum_proof(&self) -> &S::Proof

Returns the sum proof for the choice ciphertexts.

Trait Implementations§

source§

impl<G: Clone + Group, S: Clone + ProveSum<G>> Clone for EncryptedChoice<G, S>
where S::Proof: Clone,

source§

fn clone(&self) -> EncryptedChoice<G, S>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<G: Debug + Group, S: Debug + ProveSum<G>> Debug for EncryptedChoice<G, S>
where S::Proof: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de, G: Group, S: ProveSum<G>> Deserialize<'de> for EncryptedChoice<G, S>

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl<G: Group, S: ProveSum<G>> Serialize for EncryptedChoice<G, S>

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<G, S> Freeze for EncryptedChoice<G, S>
where <S as ProveSum<G>>::Proof: Freeze, <G as ScalarOps>::Scalar: Freeze,

§

impl<G, S> RefUnwindSafe for EncryptedChoice<G, S>

§

impl<G, S> Send for EncryptedChoice<G, S>
where <G as ElementOps>::Element: Send, <S as ProveSum<G>>::Proof: Send, <G as ScalarOps>::Scalar: Send,

§

impl<G, S> Sync for EncryptedChoice<G, S>
where <G as ElementOps>::Element: Sync, <S as ProveSum<G>>::Proof: Sync, <G as ScalarOps>::Scalar: Sync,

§

impl<G, S> Unpin for EncryptedChoice<G, S>
where <G as ElementOps>::Element: Unpin, <S as ProveSum<G>>::Proof: Unpin, <G as ScalarOps>::Scalar: Unpin,

§

impl<G, S> UnwindSafe for EncryptedChoice<G, S>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,