From 9496e9d4a03b5c9b103096a1e68c88e48fbcbe2e Mon Sep 17 00:00:00 2001 From: Markku Rossi Date: Wed, 10 Jan 2024 14:15:03 +0100 Subject: [PATCH] Secure multiplication Fx. --- bmr/fx.go | 46 +++++++++++++++++++++++++++ bmr/fx_test.go | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ bmr/network.go | 12 ++++++++ bmr/wire.go | 23 +++++++++++++- 4 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 bmr/fx.go create mode 100644 bmr/fx_test.go create mode 100644 bmr/network.go diff --git a/bmr/fx.go b/bmr/fx.go new file mode 100644 index 00000000..fa861003 --- /dev/null +++ b/bmr/fx.go @@ -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 +} diff --git a/bmr/fx_test.go b/bmr/fx_test.go new file mode 100644 index 00000000..40ea0e17 --- /dev/null +++ b/bmr/fx_test.go @@ -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 +} diff --git a/bmr/network.go b/bmr/network.go new file mode 100644 index 00000000..d72b01fd --- /dev/null +++ b/bmr/network.go @@ -0,0 +1,12 @@ +// +// Copyright (c) 2024 Markku Rossi +// +// All rights reserved. +// + +package bmr + +// Network protocol messages. +const ( + OpFx byte = iota +) diff --git a/bmr/wire.go b/bmr/wire.go index c7e9d829..e29674e1 100644 --- a/bmr/wire.go +++ b/bmr/wire.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 Markku Rossi +// Copyright (c) 2022-2024 Markku Rossi // // All rights reserved. // @@ -7,8 +7,12 @@ package bmr import ( + "bytes" "crypto/rand" + "encoding/binary" "fmt" + + "github.com/markkurossi/mpc/ot" ) // Wire implements a circuit wire. @@ -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)) +}