Commit c7af0db5 authored by Anders Jensen Løvig's avatar Anders Jensen Løvig
Browse files

Builder

parent 91d638fc
# Cryptographic Computing - Handin 4
A Go implementation of a passive secure two-party protocol for blood type compatibility based on oblivious transfer.
A Go implementation of a passive secure two-party protocol for blood type compatibility based on Yao's garbled circuit protocol.
## Implementation
......
......@@ -19,17 +19,17 @@ type Protocol struct {
A, B *Party
}
func NewProtocol() (p *Protocol, err error) {
func NewProtocol(builder *garbled.CircuitBuilder) (p *Protocol, err error) {
connA2B := make(chan []byte)
connB2A := make(chan []byte)
obliv := oblivious.NewProtocol(len(blood.Table))
A, err := NewParty(connA2B, connB2A, obliv.R)
A, err := NewParty(builder, connA2B, connB2A, obliv.R)
if err != nil {
return
}
B, err := NewParty(connB2A, connA2B, obliv.S)
B, err := NewParty(builder, connB2A, connA2B, obliv.S)
if err != nil {
return
}
......@@ -52,8 +52,8 @@ type Party struct {
circuit *garbled.Circuit
}
func NewParty(in chan []byte, out chan []byte, obliv *oblivious.Party) (p *Party, err error) {
c, err := garbled.NewCircuit(NumInputs, NumWires, K)
func NewParty(builder *garbled.CircuitBuilder, in chan []byte, out chan []byte, obliv *oblivious.Party) (p *Party, err error) {
c, err := builder.Build()
if err != nil {
return
}
......@@ -104,7 +104,7 @@ func (alice *Party) RunAlice(x int) (result bool, err error) {
func (bob *Party) RunBob(y int) (err error) {
// 1. Garble
err = bob.circuit.GarbleBloodCircuit()
err = bob.circuit.Garble()
if err != nil {
return
}
......@@ -134,11 +134,28 @@ func (bob *Party) RunBob(y int) (err error) {
return
}
// Evaluates an OR gate with not b.
func OrGateWithNot(a, b bool) bool {
return a || !b
}
// Evaluates and and gate.
func AndGate(a, b bool) bool {
return a && b
}
// RunProtocol runs the protocol between receiving blood type x and donor blood
// type y.
// outputMode: 0: Alice learns, 1: Bob learns else both learns
func RunProtocol(x, y int, outputMode int) (z bool, err error) {
p, err := NewProtocol()
builder := garbled.NewCircuitBuilder(6, 128)
or1 := builder.AddGate(0, 3, OrGateWithNot)
or2 := builder.AddGate(1, 4, OrGateWithNot)
or3 := builder.AddGate(2, 5, OrGateWithNot)
and1 := builder.AddGate(or1, or2, AndGate)
_ = builder.AddGate(or3, and1, AndGate)
p, err := NewProtocol(builder)
if err != nil {
return
}
......
package garbled
type gate struct {
// left is the left input wire
left int
// left is the left input wire
right int
// out is the output wire
out int
// fun is the gate evaluation function
fun func(a, b bool) bool
}
type CircuitBuilder struct {
// k is the bit-length of encodings
k int
// numInputs is the number of input wires
numInputs int
// gates contain all created gates
gates []*gate
}
// Returns a new CircuitBuilder for a circuit with numInputs input wires.
func NewCircuitBuilder(numInputs, k int) *CircuitBuilder {
return &CircuitBuilder{
k: k,
numInputs: numInputs,
gates: make([]*gate, 0),
}
}
// Adds a gate with left and right input wire and evaluted by fun.
// Returns the output wire.
func (b *CircuitBuilder) AddGate(left, right int, fun func(a, b bool) bool) (out int) {
out = b.numInputs + len(b.gates)
b.gates = append(b.gates, &gate{
left: left,
right: right,
out: out,
fun: fun,
})
return
}
// Builds the circuit configured in this builder.
func (b *CircuitBuilder) Build() (c *Circuit, err error) {
numWires := b.numInputs + len(b.gates)
return NewCircuit(b.numInputs, numWires, b.k, b.gates)
}
......@@ -9,8 +9,11 @@ import (
)
type Circuit struct {
// Parameters
numInputs, numWires, k int
gates []*gate
G func(a, b []byte, i int) []byte
F *Table
......@@ -18,8 +21,12 @@ type Circuit struct {
D *Table
}
func NewCircuit(numInputs, numWires, k int) (c *Circuit, err error) {
F, err := NewTable(numWires-numInputs, 4, k*2)
func NewCircuit(numInputs, numWires, k int, gates []*gate) (c *Circuit, err error) {
if k%8 != 0 {
return nil, errors.New("k must be multiple of 8")
}
numNonInputs := numWires - numInputs
F, err := NewTable(numNonInputs, 4, k*2)
if err != nil {
return
}
......@@ -28,13 +35,15 @@ func NewCircuit(numInputs, numWires, k int) (c *Circuit, err error) {
numWires: numWires,
k: k,
gates: gates,
G: G,
F: F,
}
return
}
func (c *Circuit) GarbleBloodCircuit() (err error) {
func (c *Circuit) Garble() (err error) {
// 1. Create two random strings for each wire.
kTable, err := NewTable(c.numWires, 2, c.k)
if err != nil {
......@@ -46,12 +55,16 @@ func (c *Circuit) GarbleBloodCircuit() (err error) {
}
// 2. Create a garbled table for all F values (4 for each gate)
c.F.setRow(0, c.garbleGate(kTable, 0, 3, 6, ORGateWithNot))
c.F.setRow(1, c.garbleGate(kTable, 1, 4, 7, ORGateWithNot))
c.F.setRow(2, c.garbleGate(kTable, 2, 5, 8, ORGateWithNot))
for i, gate := range c.gates {
c.F.setRow(i, c.garbleGate(kTable, gate))
}
// c.F.setRow(0, c.garbleGate(kTable, 0, 3, 6, ORGateWithNot))
// c.F.setRow(1, c.garbleGate(kTable, 1, 4, 7, ORGateWithNot))
// c.F.setRow(2, c.garbleGate(kTable, 2, 5, 8, ORGateWithNot))
c.F.setRow(3, c.garbleGate(kTable, 6, 7, 9, ANDGate))
c.F.setRow(4, c.garbleGate(kTable, 8, 9, 10, ANDGate))
// c.F.setRow(3, c.garbleGate(kTable, 6, 7, 9, ANDGate))
// c.F.setRow(4, c.garbleGate(kTable, 8, 9, 10, ANDGate))
// Create e
c.E = make([]*Table, 2)
......@@ -73,7 +86,6 @@ func (c *Circuit) GarbleBloodCircuit() (err error) {
return
}
c.D.SetData(kTable.getRow(c.numWires - 1))
return
}
......@@ -105,17 +117,22 @@ func Decode(d *Table, Z []byte) (bool, error) {
}
//Creates a row (C_0^i, C_1^i, C_2^i ,C_3^i) for the garbled table, where
func (c *Circuit) garbleGate(K *Table, Li, Ri, out int, gateFun func(a, b int) int) []byte {
func (c *Circuit) garbleGate(K *Table, gate *gate) []byte {
cRow := make([]byte, 4*2*K.valueLen) // because 4 values of double length
perm := util.Perm(4) // Random permutation
// for (a,b) in {0,1} x {0,1}
for a := 0; a <= 1; a++ {
for b := 0; b <= 1; b++ {
left := c.G(K.getValue(Li, a), K.getValue(Ri, b), out)
left := c.G(K.getValue(gate.left, a), K.getValue(gate.right, b), gate.out)
right := make([]byte, K.valueLen*2)
copy(right[:K.valueLen], K.getValue(out, gateFun(a, b)))
c := 0
if gate.fun(a == 1, b == 1) {
c = 1
}
copy(right[:K.valueLen], K.getValue(gate.out, c))
dst := util.XOR(left, right) // XOR with left as destination.
......@@ -143,18 +160,13 @@ func (c *Circuit) Evaluate(x []byte) ([]byte, error) {
}
copy(K.data[:len(x)], x)
Li := []int{0, 1, 2, 6, 8}
Ri := []int{3, 4, 5, 7, 9}
Oi := []int{6, 7, 8, 9, 10}
zeroes := make([]byte, K.valueLen)
// For each circuit gate
for i := 0; i < c.F.rows; i++ {
// For each C
for i, gate := range c.gates {
success := false
for j := 0; j < 4; j++ {
left := c.G(K.getValue(0, Li[i]), K.getValue(0, Ri[i]), Oi[i])
left := c.G(K.getValue(0, gate.left), K.getValue(0, gate.right), gate.out)
right := c.F.getValue(i, j)
dst := util.XOR(left, right)
......@@ -169,29 +181,28 @@ func (c *Circuit) Evaluate(x []byte) ([]byte, error) {
}
}
// for i := 0; i < c.F.rows; i++ {
// // For each C
// success := false
// for j := 0; j < 4; j++ {
// left := c.G(K.getValue(0, Li[i]), K.getValue(0, Ri[i]), Oi[i])
// right := c.F.getValue(i, j)
// dst := util.XOR(left, right)
// if bytes.Equal(zeroes, dst[K.valueLen:]) {
// K.setValue(0, i+c.numInputs, dst[:K.valueLen])
// success = true
// break
// }
// }
// if !success {
// return nil, fmt.Errorf("failed to evaluate circuit layer %d", i)
// }
// }
return K.getValue(0, c.numWires-1), nil
}
////////////////////////////////////////////////////////////////
// GATES
////////////////////////////////////////////////////////////////
func ORGate(a, b int) int {
if a+b != 0 {
return 1
} else {
return 0
}
}
func ORGateWithNot(a, b int) int {
if ((1 - b) + a) == 0 {
return 0
} else {
return 1
}
}
func ANDGate(a, b int) int {
return a * b
}
......@@ -13,7 +13,7 @@ func TestGBC(t *testing.T) {
_ = K.randomizeTable()
c := &Circuit{G: testingG}
res := c.garbleGate(K, 0, 1, 2, ORGate)
res := c.garbleGate(K, &gate{0, 1, 2, or})
count := 0
for i := 0; i < 4; i++ {
index := i * 2 * K.valueLen
......@@ -25,7 +25,7 @@ func TestGBC(t *testing.T) {
t.Error("Function should return 3 true labels and 1 false label when using an OR Gate")
}
res = c.garbleGate(K, 0, 1, 2, ANDGate)
res = c.garbleGate(K, &gate{0, 1, 2, and})
count = 0
for i := 0; i < 4; i++ {
index := i * 2 * K.valueLen
......@@ -42,6 +42,14 @@ func testingG(A, B []byte, i int) []byte {
return make([]byte, len(A)*2)
}
func or(a, b bool) bool {
return a || b
}
func and(a, b bool) bool {
return a && b
}
func TestDecode(t *testing.T) {
}
......@@ -69,13 +69,3 @@ func TestTableValue(t *testing.T) {
AssertByteSlice(t, table.getRows(0, 2), []byte{123, 81, 0, 0, 1, 2, 3, 4})
AssertByteSlice(t, table.getRows(1, 1), []byte{1, 2, 3, 4})
}
func TestGetData(t *testing.T) {
c, _ := NewCircuit(6, 11, 128)
_ = c.GarbleBloodCircuit()
data := c.F.GetData()
if !bytes.Equal(data, c.F.data) {
t.Errorf("Bytes not equal")
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment