Skip to content

Commit

Permalink
Optimized garbling.
Browse files Browse the repository at this point in the history
  • Loading branch information
markkurossi committed Apr 7, 2020
1 parent 3ce214d commit 0966211
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 74 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ Circuit: #gates=6717340 (XOR=4787324 XNOR=108545 AND=1821471 OR=0 INV=0)
```

Pruning dead gates:

```
Circuit: #gates=5972956 (XOR=4315452 XNOR=53761 AND=1603743 OR=0 INV=0)
┏━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┓
Expand All @@ -403,6 +404,22 @@ Circuit: #gates=5972956 (XOR=4315452 XNOR=53761 AND=1603743 OR=0 INV=0)
┗━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━┻━━━━━━━┛
```

Optimized garbling:

```
Circuit: #gates=5972956 (XOR=4315452 XNOR=53761 AND=1603743 OR=0 INV=0)
┏━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┓
┃ Op ┃ Time ┃ % ┃ Xfer ┃
┣━━━━━━━━╋━━━━━━━━━━━━━━╋━━━━━━━━╋━━━━━━━┫
┃ Wait ┃ 820.73261ms ┃ 41.67% ┃ ┃
┃ Recv ┃ 749.691218ms ┃ 38.06% ┃ 126MB ┃
┃ Inputs ┃ 226.025987ms ┃ 11.47% ┃ 41kB ┃
┃ Eval ┃ 173.069098ms ┃ 8.79% ┃ ┃
┃ Result ┃ 212.406µs ┃ 0.01% ┃ 1kB ┃
┃ Total ┃ 1.969731319s ┃ ┃ ┃
┗━━━━━━━━┻━━━━━━━━━━━━━━┻━━━━━━━━┻━━━━━━━┛
```

## RSA signature computation

| Input Size | MODP Size | Total gates | Non-XOR gates |
Expand Down
65 changes: 12 additions & 53 deletions circuit/garble.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"crypto/cipher"
"crypto/rand"
"fmt"
"sort"

"github.com/markkurossi/mpc/ot"
)
Expand All @@ -20,39 +19,6 @@ var (
verbose = false
)

type TableEntry struct {
Index int
Data ot.Label
}

type ByIndex []TableEntry

func (a ByIndex) Len() int {
return len(a)
}

func (a ByIndex) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}

func (a ByIndex) Less(i, j int) bool {
return a[i].Index < a[j].Index
}

func entry(alg cipher.Block, a, b, c ot.Label, tweak uint32) TableEntry {
return TableEntry{
Index: idx(a, b),
Data: encrypt(alg, a, b, c, tweak),
}
}

func entryUnary(alg cipher.Block, a, c ot.Label, tweak uint32) TableEntry {
return TableEntry{
Index: idxUnary(a),
Data: encrypt(alg, a, ot.Label{}, c, tweak),
}
}

func idxUnary(l0 ot.Label) int {
if l0.S() {
return 1
Expand Down Expand Up @@ -242,7 +208,7 @@ func (g *Gate) Garble(wires []ot.Wire, enc cipher.Block, r ot.Label,
}
wires[g.Output.ID()] = c

var table [4]TableEntry
var table [4]ot.Label
var count int

switch g.Op {
Expand All @@ -256,10 +222,10 @@ func (g *Gate) Garble(wires []ot.Wire, enc cipher.Block, r ot.Label,
// 0 1 0
// 1 0 0
// 1 1 1
table[0] = entry(enc, a.L0, b.L0, c.L0, id)
table[1] = entry(enc, a.L0, b.L1, c.L0, id)
table[2] = entry(enc, a.L1, b.L0, c.L0, id)
table[3] = entry(enc, a.L1, b.L1, c.L1, id)
table[idx(a.L0, b.L0)] = encrypt(enc, a.L0, b.L0, c.L0, id)
table[idx(a.L0, b.L1)] = encrypt(enc, a.L0, b.L1, c.L0, id)
table[idx(a.L1, b.L0)] = encrypt(enc, a.L1, b.L0, c.L0, id)
table[idx(a.L1, b.L1)] = encrypt(enc, a.L1, b.L1, c.L1, id)
count = 4

case OR:
Expand All @@ -269,31 +235,24 @@ func (g *Gate) Garble(wires []ot.Wire, enc cipher.Block, r ot.Label,
// 0 1 1
// 1 0 1
// 1 1 1
table[0] = entry(enc, a.L0, b.L0, c.L0, id)
table[1] = entry(enc, a.L0, b.L1, c.L1, id)
table[2] = entry(enc, a.L1, b.L0, c.L1, id)
table[3] = entry(enc, a.L1, b.L1, c.L1, id)
table[idx(a.L0, b.L0)] = encrypt(enc, a.L0, b.L0, c.L0, id)
table[idx(a.L0, b.L1)] = encrypt(enc, a.L0, b.L1, c.L1, id)
table[idx(a.L1, b.L0)] = encrypt(enc, a.L1, b.L0, c.L1, id)
table[idx(a.L1, b.L1)] = encrypt(enc, a.L1, b.L1, c.L1, id)
count = 4

case INV:
// a b c
// -----
// 0 1
// 1 0
table[0] = entryUnary(enc, a.L0, c.L1, id)
table[1] = entryUnary(enc, a.L1, c.L0, id)
table[idxUnary(a.L0)] = encrypt(enc, a.L0, ot.Label{}, c.L1, id)
table[idxUnary(a.L1)] = encrypt(enc, a.L1, ot.Label{}, c.L0, id)
count = 2

default:
return nil, fmt.Errorf("Invalid operand %s", g.Op)
}

sort.Sort(ByIndex(table[:count]))

result := make([]ot.Label, count)
for idx, entry := range table[:count] {
result[idx] = entry.Data
}

return result, nil
return table[:count], nil
}
34 changes: 13 additions & 21 deletions circuit/garble_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"crypto/aes"
"crypto/cipher"
"fmt"
"sort"

"github.com/markkurossi/mpc/ot"
)
Expand Down Expand Up @@ -101,7 +100,7 @@ func (c *Circuit) GarbleStream(key []byte, r ot.Label, inputIDs []Wire) error {
}

func (g *Gate) GarbleStream(wires *StreamWires, enc cipher.Block,
r ot.Label, id uint32, buf []ot.Label) ([]ot.Label, error) {
r ot.Label, id uint32, table []ot.Label) ([]ot.Label, error) {

var a, b, c ot.Wire
var err error
Expand Down Expand Up @@ -151,7 +150,7 @@ func (g *Gate) GarbleStream(wires *StreamWires, enc cipher.Block,
}
wires.Set(g.Output, c)

var table [4]TableEntry
table = table[0:4]
var count int

switch g.Op {
Expand All @@ -165,10 +164,10 @@ func (g *Gate) GarbleStream(wires *StreamWires, enc cipher.Block,
// 0 1 0
// 1 0 0
// 1 1 1
table[0] = entry(enc, a.L0, b.L0, c.L0, id)
table[1] = entry(enc, a.L0, b.L1, c.L0, id)
table[2] = entry(enc, a.L1, b.L0, c.L0, id)
table[3] = entry(enc, a.L1, b.L1, c.L1, id)
table[idx(a.L0, b.L0)] = encrypt(enc, a.L0, b.L0, c.L0, id)
table[idx(a.L0, b.L1)] = encrypt(enc, a.L0, b.L1, c.L0, id)
table[idx(a.L1, b.L0)] = encrypt(enc, a.L1, b.L0, c.L0, id)
table[idx(a.L1, b.L1)] = encrypt(enc, a.L1, b.L1, c.L1, id)
count = 4

case OR:
Expand All @@ -178,31 +177,24 @@ func (g *Gate) GarbleStream(wires *StreamWires, enc cipher.Block,
// 0 1 1
// 1 0 1
// 1 1 1
table[0] = entry(enc, a.L0, b.L0, c.L0, id)
table[1] = entry(enc, a.L0, b.L1, c.L1, id)
table[2] = entry(enc, a.L1, b.L0, c.L1, id)
table[3] = entry(enc, a.L1, b.L1, c.L1, id)
table[idx(a.L0, b.L0)] = encrypt(enc, a.L0, b.L0, c.L0, id)
table[idx(a.L0, b.L1)] = encrypt(enc, a.L0, b.L1, c.L1, id)
table[idx(a.L1, b.L0)] = encrypt(enc, a.L1, b.L0, c.L1, id)
table[idx(a.L1, b.L1)] = encrypt(enc, a.L1, b.L1, c.L1, id)
count = 4

case INV:
// a b c
// -----
// 0 1
// 1 0
table[0] = entryUnary(enc, a.L0, c.L1, id)
table[1] = entryUnary(enc, a.L1, c.L0, id)
table[idxUnary(a.L0)] = encrypt(enc, a.L0, ot.Label{}, c.L1, id)
table[idxUnary(a.L1)] = encrypt(enc, a.L1, ot.Label{}, c.L0, id)
count = 2

default:
return nil, fmt.Errorf("Invalid operand %s", g.Op)
}

sort.Sort(ByIndex(table[:count]))

buf = buf[:count]
for idx, entry := range table[:count] {
buf[idx] = entry.Data
}

return buf, nil
return table[:count], nil
}

0 comments on commit 0966211

Please sign in to comment.