Skip to content

Commit

Permalink
Secure multiplication Fx.
Browse files Browse the repository at this point in the history
  • Loading branch information
markkurossi committed Jan 10, 2024
1 parent 5f30855 commit 9496e9d
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 1 deletion.
46 changes: 46 additions & 0 deletions bmr/fx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Copyright (c) 2024 Markku Rossi
//
// All rights reserved.
//

package bmr

import (
"github.com/markkurossi/mpc/ot"
)

// FxSend implements the sender part of the secure multiplication
// algorithm Fx (3.1.1 Secure Multiplication - page 7).
func FxSend(oti ot.OT, a Label) (r Label, err error) {
r, err = NewLabel()
if err != nil {
return
}

x0 := r
x1 := r
x1.Xor(a)

wire := ot.Wire{
L0: x0.ToOT(),
L1: x1.ToOT(),
}

err = oti.Send([]ot.Wire{wire})
return
}

// FxReceive implements the receiver part of the secure multiplication
// algorithm Fx (3.1.1 Secure Multiplication - page 7).
func FxReceive(oti ot.OT, bit bool) (xb Label, err error) {
flags := []bool{bit}
var result [1]ot.Label

err = oti.Receive(flags, result[:])
if err != nil {
return
}
xb.FromOT(result[0])
return
}
84 changes: 84 additions & 0 deletions bmr/fx_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// Copyright (c) 2024 Markku Rossi
//
// All rights reserved.
//

package bmr

import (
"testing"

"github.com/markkurossi/mpc/ot"
)

func TestFx(t *testing.T) {
testFx(t, false)
testFx(t, true)
}

func testFx(t *testing.T, b bool) {
fp, tp := ot.NewPipe()

ch := make(chan interface{})

go fxReceiver(tp, ch, b)

oti := ot.NewCO()
err := oti.InitSender(fp)
if err != nil {
t.Fatal(err)
}

a, err := NewLabel()
if err != nil {
t.Fatal(err)
}
r, err := FxSend(oti, a)
if err != nil {
t.Fatal(err)
}

ret := <-ch
switch xb := ret.(type) {
case error:
t.Fatal(xb)

case Label:
if b {
// b = 1 implies that xb = x1 = r⊕a
tst := r
tst.Xor(a)
if !tst.Equal(xb) {
t.Errorf("b=1, got %v, expected %v\n", xb, tst)
}
} else {
// b = 0 implies that xb = x0 = r
if !xb.Equal(r) {
t.Errorf("b=0: got %v, expected %v\n", xb, r)
}
}

default:
t.Fatalf("unexpected result: %v(%T)", ret, ret)
}
}

func fxReceiver(pipe ot.IO, ch chan interface{}, bit bool) {
defer close(ch)

oti := ot.NewCO()
err := oti.InitReceiver(pipe)
if err != nil {
ch <- err
return
}

xb, err := FxReceive(oti, bit)
if err != nil {
ch <- err
return
}

ch <- xb
}
12 changes: 12 additions & 0 deletions bmr/network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Copyright (c) 2024 Markku Rossi
//
// All rights reserved.
//

package bmr

// Network protocol messages.
const (
OpFx byte = iota
)
23 changes: 22 additions & 1 deletion bmr/wire.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//
// Copyright (c) 2022 Markku Rossi
// Copyright (c) 2022-2024 Markku Rossi
//
// All rights reserved.
//

package bmr

import (
"bytes"
"crypto/rand"
"encoding/binary"
"fmt"

"github.com/markkurossi/mpc/ot"
)

// Wire implements a circuit wire.
Expand Down Expand Up @@ -39,9 +43,26 @@ func (l Label) String() string {
return fmt.Sprintf("%x", [k / 8]byte(l))
}

// Equal tests if the label is equal with the argument label.
func (l Label) Equal(o Label) bool {
return bytes.Equal(l[:], o[:])
}

// Xor sets l to l^o.
func (l *Label) Xor(o Label) {
for i := 0; i < len(l); i++ {
l[i] ^= o[i]
}
}

// ToOT converts the label to ot.Label.
func (l *Label) ToOT() ot.Label {
var label ot.Label
label.D0 = uint64(binary.BigEndian.Uint32(l[:]))
return label
}

// FromOT sets the label to the ot.Label.
func (l *Label) FromOT(label ot.Label) {
binary.BigEndian.PutUint32(l[:], uint32(label.D0))
}

0 comments on commit 9496e9d

Please sign in to comment.