Crate tandem

source ·
Expand description

Secure Multi-Party Computation (SMPC) using Garbled Circuits for 2 parties.

This crate can be used to securely compute functions specified as boolean circuits (using AND, XOR and NOT gates) without revealing the inputs of either party to the other party.

The core protocol implemented in this crate is WRK17, with an OT extension and optimizations based on ALSZ13 and a base OT implementation based on ABKLX21.

Communication channels are deliberately not part of this crate. The sending and receiving of messages needs to be handled by the user of this crate, which allows the MPC protocol to be used both in sync and async environments.

Examples

use tandem::{
    states::{Contributor, Evaluator, Msg},
    Circuit, Error, Gate,
};
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
use std::{
    sync::{mpsc::channel, Arc},
    thread,
};

fn main() -> Result<(), Error> {
    // Create a simple circuit with 2 input bits, calculate their AND and output it:
    let simple_circuit = Circuit::new(
        vec![Gate::InContrib, Gate::InEval, Gate::And(0, 1)],
        vec![2],
    );

    let (to_eval, from_contrib) = channel::<Msg>();
    let (to_contrib, from_eval) = channel::<Msg>();

    // Spawn a contributor as a new thread, with the evaluator remaining on the main thread:
    let circuit_for_contrib_thread = simple_circuit.clone();
    thread::spawn(move || -> Result<(), Error> {
        let contributor_input = vec![true];

        // Create a contributor and the initial message for the evaluator:
        let (mut contributor, msg) = Contributor::new(
            &circuit_for_contrib_thread,
            contributor_input,
            ChaCha20Rng::from_entropy(),
        )?;

        // Send initial message to start MPC protocol:
        to_eval.send(msg).unwrap();

        for _ in 0..contributor.steps() {
            let msg = from_eval.recv().expect("failed to get msg");

            // Based on the message from the evaluator, the contributor transitions to a new state:
            let (next_state, reply) = contributor.run(&msg)?;
            to_eval.send(reply).expect("failed to send reply");
            contributor = next_state;
        }
        Ok(())
    });

    let evaluator_input = vec![false];

    let mut evaluator = Evaluator::new(
        &simple_circuit,
        evaluator_input,
        ChaCha20Rng::from_entropy(),
    )?;

    for _ in 0..evaluator.steps() {
        let msg = from_contrib.recv().expect("failed to get msg");

        // Based on the message from the contributor, the evaluator transitions to a new state:
        let (next_state, reply) = evaluator.run(&msg)?;
        to_contrib.send(reply).expect("failed to send reply");
        evaluator = next_state
    }

    // The final message from the contributor allows the evaluator to decrypt the output:
    let final_msg = from_contrib.recv().expect("failed to get final msg");
    let output = evaluator.output(&final_msg)?;
    assert_eq!(output, vec![false]);

    Ok(())
}

Modules

The different states in the MPC protocol.

Structs

A circuit of AND, XOR and NOT gates that can be executed using MPC.

Enums

Errors occurring during the validation or the execution of the MPC protocol.
A single gate in a larger Circuit.

Functions

Simulates the local execution of the circuit using a 2 Party MPC protocol.

Type Definitions

A blake3 hash that can be used to compare circuits for equality.
The index of the gate in the circuit, representing its output wire.