garbled separating sender and eval
This commit is contained in:
parent
244c4df28e
commit
1d09d1ef39
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_hidden_re(
|
||||||
|
&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 CircOption {
|
impl BitAnd for Circuit {
|
||||||
type Output = CircOption;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user