garbled separating sender and eval

This commit is contained in:
h 2023-12-05 03:18:14 -05:00
parent 244c4df28e
commit 1d09d1ef39

View File

@ -38,24 +38,49 @@ fn decrypt(key_a: [u8; 16], key_b: [u8; 16], encrypted: [u8; 32]) -> Option<[u8;
struct Wire { struct Wire {
sym: Option<String>, sym: Option<String>,
keys: [[u8; 16]; 2], keys: [[u8; 16]; 2],
secret: bool, evaluator: bool,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Circuit { struct Gate {
left: Box<CircOption>, left: Box<Circuit>,
right: Box<CircOption>, right: Box<Circuit>,
out: Wire, out: Wire,
table: [[[u8; 32]; 2]; 2], table: [[[u8; 32]; 2]; 2],
sym: String, sym: String,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum CircOption { enum Circuit {
Circuit(Circuit), Gate(Gate),
Wire(Wire), Wire(Wire),
} }
#[derive(Clone, Debug)]
struct HiddenWire {
sym: Option<String>,
}
#[derive(Clone, Debug)]
struct HiddenGate {
left: Box<HiddenCircuit>,
right: Box<HiddenCircuit>,
table: [[[u8; 32]; 2]; 2],
sym: String,
}
#[derive(Clone, Debug)]
enum HiddenCircuit {
Gate(HiddenGate),
Wire(HiddenWire),
}
#[derive(Clone, Debug)]
struct FullyHiddenCircuit {
table: [[u8; 32]; 2],
circuit: HiddenCircuit,
}
impl Display for Wire { impl Display for Wire {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.sym { match &self.sym {
@ -65,39 +90,39 @@ impl Display for Wire {
} }
} }
impl Display for CircOption { impl Display for Circuit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
CircOption::Wire(w) => write!(f, "{}", w), Circuit::Wire(w) => write!(f, "{}", w),
CircOption::Circuit(c) => write!(f, "{}", c), Circuit::Gate(c) => write!(f, "{}", c),
} }
} }
} }
impl Display for Circuit { impl Display for Gate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {} {}", self.left, self.sym, self.right) write!(f, "{} {} {}", self.left, self.sym, self.right)
} }
} }
impl Wire { impl Wire {
fn new_rng(sym: String, secret: bool, rng: &mut (impl RngCore + CryptoRng)) -> Self { fn new_rng(sym: String, evaluator: bool, rng: &mut (impl RngCore + CryptoRng)) -> Self {
let mut keys = [[0; 16]; 2]; let mut keys = [[0; 16]; 2];
rng.fill_bytes(&mut keys[0]); rng.fill_bytes(&mut keys[0]);
rng.fill_bytes(&mut keys[1]); rng.fill_bytes(&mut keys[1]);
Self { Self {
sym: Some(sym), sym: Some(sym),
keys, keys,
secret, evaluator,
} }
} }
fn new(sym: String, secret: bool) -> Self { fn new(sym: String, evaluator: bool) -> Self {
Self::new_rng(sym, secret, &mut OsRng) Self::new_rng(sym, evaluator, &mut OsRng)
} }
fn to_circ(&self) -> CircOption { fn to_circ(&self) -> Circuit {
CircOption::Wire(self.clone()) Circuit::Wire(self.clone())
} }
fn empty(rng: &mut (impl RngCore + CryptoRng)) -> Self { fn empty(rng: &mut (impl RngCore + CryptoRng)) -> Self {
@ -107,27 +132,27 @@ impl Wire {
Self { Self {
sym: None, sym: None,
keys, keys,
secret: false, evaluator: false,
} }
} }
} }
impl Circuit { impl Gate {
fn new( fn new(
left: CircOption, left: Circuit,
right: CircOption, right: Circuit,
value: [[bool; 2]; 2], value: [[bool; 2]; 2],
sym: String, sym: String,
rng: &mut (impl RngCore + CryptoRng), rng: &mut (impl RngCore + CryptoRng),
) -> Self { ) -> Self {
let linp_keys = match left { let linp_keys = match left {
CircOption::Wire(ref w) => w.keys, Circuit::Wire(ref w) => w.keys,
CircOption::Circuit(ref c) => c.out.keys, Circuit::Gate(ref c) => c.out.keys,
}; };
let rinp_keys = match right { let rinp_keys = match right {
CircOption::Wire(ref w) => w.keys, Circuit::Wire(ref w) => w.keys,
CircOption::Circuit(ref c) => c.out.keys, Circuit::Gate(ref c) => c.out.keys,
}; };
let out = Wire::empty(rng); let out = Wire::empty(rng);
@ -157,15 +182,15 @@ impl Circuit {
} }
} }
fn to_circ(&self) -> CircOption { fn to_circ(&self) -> Circuit {
CircOption::Circuit(self.clone()) Circuit::Gate(self.clone())
} }
} }
impl CircOption { impl Circuit {
fn evaluate_re(&self, vals: HashMap<String, bool>) -> [u8; 16] { fn evaluate_re(&self, vals: HashMap<String, bool>) -> [u8; 16] {
match self { match self {
CircOption::Circuit(c) => { Circuit::Gate(c) => {
let lv = c.left.evaluate_re(vals.clone()); let lv = c.left.evaluate_re(vals.clone());
let rv = c.right.evaluate_re(vals); let rv = c.right.evaluate_re(vals);
let mut out = [0; 16]; let mut out = [0; 16];
@ -178,8 +203,8 @@ impl CircOption {
} }
out out
} }
CircOption::Wire(w) => match &w.sym { Circuit::Wire(w) => match &w.sym {
// Errr OT? hello? // No OT
Some(c) => w.keys[(vals[c]) as usize], Some(c) => w.keys[(vals[c]) as usize],
None => panic!("This should not happen."), None => panic!("This should not happen."),
}, },
@ -190,7 +215,7 @@ impl CircOption {
let out_label = self.evaluate_re(vals); let out_label = self.evaluate_re(vals);
match self { match self {
CircOption::Circuit(c) => { Circuit::Gate(c) => {
if out_label == c.out.keys[0] { if out_label == c.out.keys[0] {
false false
} else if out_label == c.out.keys[1] { } else if out_label == c.out.keys[1] {
@ -199,7 +224,7 @@ impl CircOption {
panic!("Error!"); panic!("Error!");
} }
} }
CircOption::Wire(w) => { Circuit::Wire(w) => {
if out_label == w.keys[0] { if out_label == w.keys[0] {
false false
} else if out_label == w.keys[1] { } else if out_label == w.keys[1] {
@ -210,13 +235,111 @@ impl CircOption {
} }
} }
} }
pub fn to_hidden(
&self,
) -> (
FullyHiddenCircuit,
HashMap<String, [[u8; 16]; 2]>,
HashMap<String, [[u8; 16]; 2]>,
) {
let (circ, map1, map2) = self.to_hidden_re();
match self {
Circuit::Gate(c) => {
let out_keys = c.out.keys;
let mut table = [[0; 32]; 2];
let i = OsRng.gen::<bool>() as usize;
for bit in [i, 1 - i] {
let enc = encrypt(out_keys[bit], [0; 16], [bit as u8; 16]);
table[bit] = enc;
}
(
FullyHiddenCircuit {
table,
circuit: circ,
},
map1,
map2,
)
}
Circuit::Wire(w) => {
let out_keys = w.keys;
let mut table = [[0; 32]; 2];
let i = OsRng.gen::<bool>() as usize;
for bit in [i, 1 - i] {
let enc = encrypt(out_keys[bit], [0; 16], [bit as u8; 16]);
table[bit] = enc;
}
(
FullyHiddenCircuit {
table,
circuit: circ,
},
map1,
map2,
)
}
}
} }
impl BitAnd for CircOption { fn to_hidden_re(
type Output = CircOption; &self,
) -> (
HiddenCircuit,
HashMap<String, [[u8; 16]; 2]>,
HashMap<String, [[u8; 16]; 2]>,
) {
match self {
Circuit::Gate(c) => {
let (c1, sender1, eval1) = c.left.to_hidden_re();
let (c2, sender2, eval2) = c.right.to_hidden_re();
(
HiddenCircuit::Gate(HiddenGate {
left: Box::new(c1),
right: Box::new(c2),
table: c.table,
sym: c.sym.clone(),
}),
sender1.into_iter().chain(sender2).collect(),
eval1.into_iter().chain(eval2).collect(),
)
}
Circuit::Wire(w) => {
let out = match w.sym.clone() {
Some(s) => s,
None => panic!("Need wire description."),
};
if w.evaluator {
let sender = HashMap::new();
let mut eval = HashMap::new();
eval.insert(out, w.keys);
(
HiddenCircuit::Wire(HiddenWire { sym: w.sym.clone() }),
sender,
eval,
)
} else {
let mut sender = HashMap::new();
let eval = HashMap::new();
sender.insert(out, w.keys);
(
HiddenCircuit::Wire(HiddenWire { sym: w.sym.clone() }),
sender,
eval,
)
}
}
}
}
}
impl BitAnd for Circuit {
type Output = Circuit;
fn bitand(self, rhs: Self) -> Self::Output { fn bitand(self, rhs: Self) -> Self::Output {
CircOption::Circuit(Circuit::new( Circuit::Gate(Gate::new(
self, self,
rhs, rhs,
[[false, false], [false, true]], [[false, false], [false, true]],
@ -226,11 +349,11 @@ impl BitAnd for CircOption {
} }
} }
impl BitOr for CircOption { impl BitOr for Circuit {
type Output = CircOption; type Output = Circuit;
fn bitor(self, rhs: Self) -> Self::Output { fn bitor(self, rhs: Self) -> Self::Output {
CircOption::Circuit(Circuit::new( Circuit::Gate(Gate::new(
self, self,
rhs, rhs,
[[false, true], [true, true]], [[false, true], [true, true]],
@ -240,11 +363,11 @@ impl BitOr for CircOption {
} }
} }
impl BitXor for CircOption { impl BitXor for Circuit {
type Output = CircOption; type Output = Circuit;
fn bitxor(self, rhs: Self) -> Self::Output { fn bitxor(self, rhs: Self) -> Self::Output {
CircOption::Circuit(Circuit::new( Circuit::Gate(Gate::new(
self, self,
rhs, rhs,
[[false, true], [true, false]], [[false, true], [true, false]],
@ -254,11 +377,95 @@ impl BitXor for CircOption {
} }
} }
impl From<Wire> for HiddenWire {
fn from(value: Wire) -> Self {
Self { sym: value.sym }
}
}
impl From<Gate> for HiddenGate {
fn from(value: Gate) -> Self {
Self {
left: Box::new((*value.left).into()),
right: Box::new((*value.right).into()),
table: value.table,
sym: value.sym,
}
}
}
impl From<Circuit> for HiddenCircuit {
fn from(value: Circuit) -> Self {
match value {
Circuit::Gate(c) => Self::Gate(c.into()),
Circuit::Wire(w) => Self::Wire(w.into()),
}
}
}
impl HiddenCircuit {
fn evaluate_re(&self, vals: HashMap<String, [u8; 16]>) -> [u8; 16] {
match self {
HiddenCircuit::Gate(c) => {
let lv = c.left.evaluate_re(vals.clone());
let rv = c.right.evaluate_re(vals);
let mut out = [0; 16];
for i in [0, 1] {
for j in [0, 1] {
if let Some(x) = decrypt(lv, rv, c.table[i][j]) {
out = x;
}
}
}
out
}
HiddenCircuit::Wire(w) => match &w.sym {
Some(c) => vals[c],
None => panic!("This should not happen."),
},
}
}
}
impl FullyHiddenCircuit {
pub fn evaluate(
&self,
sender: HashMap<String, [u8; 16]>,
eval: HashMap<String, [u8; 16]>,
) -> bool {
let out_label = self
.circuit
.evaluate_re(sender.into_iter().chain(eval).collect());
let mut out = false;
for i in [0, 1] {
if let Some(x) = decrypt(out_label, [0; 16], self.table[i]) {
out = x[0] != 0;
}
}
out
}
}
pub fn map_values_to_keys(
keys: HashMap<String, [[u8; 16]; 2]>,
values: Vec<(String, bool)>,
) -> HashMap<String, [u8; 16]> {
let mut ret = HashMap::new();
for i in values {
match keys.get(&i.0) {
Some(v) => ret.insert(i.0, v[i.1 as usize]),
None => continue,
};
}
ret
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::garble_classic::Wire; use crate::garble_classic::Wire;
use crate::garble_classic::{decrypt, encrypt}; use crate::garble_classic::{decrypt, encrypt, map_values_to_keys};
use std::collections::HashMap; use std::collections::HashMap;
#[test] #[test]
@ -268,7 +475,7 @@ mod test {
} }
#[test] #[test]
fn circuit() { fn public_circuit() {
let a = Wire::new("a".to_string(), true).to_circ(); let a = Wire::new("a".to_string(), true).to_circ();
let b = Wire::new("b".to_string(), false).to_circ(); let b = Wire::new("b".to_string(), false).to_circ();
let c = Wire::new("c".to_string(), false).to_circ(); let c = Wire::new("c".to_string(), false).to_circ();
@ -278,7 +485,29 @@ mod test {
h.insert("a".to_string(), false); h.insert("a".to_string(), false);
h.insert("b".to_string(), false); h.insert("b".to_string(), false);
h.insert("c".to_string(), true); h.insert("c".to_string(), true);
let out = circ.evaluate(h); let out = circ.evaluate(h);
assert!(out == false); assert!(out == false);
} }
#[test]
fn garbled_circuit() {
let a = Wire::new("a".to_string(), true).to_circ();
let b = Wire::new("b".to_string(), false).to_circ();
let c = Wire::new("c".to_string(), false).to_circ();
let circ = (a | b) & c;
let (hidden_circ, sender, eval) = circ.to_hidden();
let values_sender = map_values_to_keys(
sender,
vec![("b".to_string(), false), ("c".to_string(), true)],
);
let values_eval = map_values_to_keys(eval, vec![("a".to_string(), true)]);
let out = hidden_circ.evaluate(values_sender, values_eval);
assert!(out == true);
}
} }