fancy_garbling/garble/
binary_and.rs1use crate::{HasModulus, WireLabel, WireMod2, hash_wires, util::tweak2};
2use subtle::ConditionallySelectable;
3use vectoreyes::U8x16;
4
5pub trait BinaryWireLabel: WireLabel + ConditionallySelectable {
8 fn garble_and_gate(gate_num: usize, A: &Self, B: &Self, delta: &Self) -> (U8x16, U8x16, Self);
13
14 fn evaluate_and_gate(gate_num: usize, A: &Self, B: &Self, gate0: &U8x16, gate1: &U8x16)
18 -> Self;
19}
20
21impl BinaryWireLabel for WireMod2 {
22 fn garble_and_gate(gate_num: usize, A: &Self, B: &Self, delta: &Self) -> (U8x16, U8x16, Self) {
23 let q = A.modulus();
24 let D = delta;
25
26 let r = B.color(); let g = tweak2(gate_num as u64, 0);
29
30 let alpha = A.color(); let X1 = *A + *D * alpha;
33
34 let beta = (q - B.color()) % q;
36 let Y1 = *B + *D * beta;
37
38 let AD = *A + *D;
39 let BD = *B + *D;
40
41 let a_selector = (A.color() as u8).into();
43 let b_selector = (B.color() as u8).into();
44
45 let B = Self::conditional_select(&BD, B, b_selector);
46 let newA = Self::conditional_select(&AD, A, a_selector);
47 let idx = u8::conditional_select(&(r as u8), &0u8, a_selector);
48
49 let [hashA, hashB, hashX, hashY] = hash_wires([&newA, &B, &X1, &Y1], g);
50
51 let X = Self::hash_to_mod(hashX, q) + *D * (alpha * r % q);
52 let Y = Self::hash_to_mod(hashY, q);
53
54 let gate0 =
55 hashA ^ U8x16::conditional_select(&X.to_repr(), &(X + *D).to_repr(), idx.into());
56 let gate1 = hashB ^ (Y + *A).to_repr();
57
58 (gate0, gate1, X + Y)
59 }
60
61 fn evaluate_and_gate(
62 gate_num: usize,
63 A: &Self,
64 B: &Self,
65 gate0: &U8x16,
66 gate1: &U8x16,
67 ) -> Self {
68 let g = tweak2(gate_num as u64, 0);
69
70 let [hashA, hashB] = hash_wires([A, B], g);
71
72 let L = Self::from_repr(
74 U8x16::conditional_select(&hashA, &(hashA ^ *gate0), (A.color() as u8).into()),
75 2,
76 );
77
78 let R = Self::from_repr(
80 U8x16::conditional_select(&hashB, &(hashB ^ *gate1), (B.color() as u8).into()),
81 2,
82 );
83
84 L + R + *A * B.color()
85 }
86}