Skip to content

Commit

Permalink
FMUL based on OT
Browse files Browse the repository at this point in the history
  • Loading branch information
zhdllwyc committed Aug 18, 2022
1 parent 1689a9b commit 60027e9
Show file tree
Hide file tree
Showing 6 changed files with 500 additions and 0 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ go 1.16
require (
github.com/bwesterb/go-ristretto v1.2.2
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ github.com/bwesterb/go-ristretto v1.2.2/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7N
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
47 changes: 47 additions & 0 deletions tss/ecdsa/ot/Fmul/Fmul.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Reference: https://eprint.iacr.org/2021/1373.pdf
// Sender and receiver has private input a and b
// Sender and receiver get s1 and s2 such that a*b = s1+s2 from Fmul
// This scheme based on pure OT but not OT extension

package Fmul

import (
"github.com/cloudflare/circl/group"
)

// Input: myGroup, the group we operate in
// Input: securityParameter
// Output: The number of BaseOT needed
func DecideNumOT(myGroup group.Group, sp int) int {
numBaseOT := int(myGroup.Params().ScalarLength*8) + sp
return numBaseOT
}

// Input: aInput, bInput, the private input from both sender and receiver
// Input: myGroup, the group we operate in
// Input: n, the total number of BaseOT
func Fmul(sender *SenderFmul, receiver *ReceiverFmul, aInput, bInput group.Scalar, myGroup group.Group, n int) error {
// Sender Initialization
As := sender.SenderInit(myGroup, aInput, n)

// ---- Round1: Sender sends As to receiver ----

Bs := receiver.ReceiverRound1(myGroup, As, bInput, n)

// ---- Round 2: Receiver sends Bs = [bi]G or Ai+[bi]G to sender ----

e0s, e1s := sender.SenderRound2(Bs, n)

// ---- Round 3: Sender sends e0s, e1s to receiver ----

sigma, vs, errDec := receiver.ReceiverRound3(e0s, e1s, n)
if errDec != nil {
return errDec
}

// ---- Round 4: receiver sends sigma as well as vs to sender ----

sender.SenderRound4(vs, sigma, n)

return nil
}
235 changes: 235 additions & 0 deletions tss/ecdsa/ot/Fmul/FmulLocal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package Fmul

import (
"crypto/rand"
"math/big"
"sync"

"github.com/cloudflare/circl/group"
"github.com/cloudflare/circl/ot/simplestOT"
"golang.org/x/sync/errgroup"
)

// ---- Sender Initialization ----

// Input: myGroup, the group we operate in
// Input: a, the sender private input
// Input: n, the total number of BaseOT
// Output: Array of A=[ai]G for n BaseOT
func (sender *SenderFmul) SenderInit(myGroup group.Group, a group.Scalar, n int) []group.Element {
sender.myGroup = myGroup
sender.a = a.Copy()
sender.deltas = make([]group.Scalar, n)
sender.m0s = make([][]byte, n)
sender.m1s = make([][]byte, n)
sender.baseOTsenders = make([]simplestOT.SenderSimOT, n)

var fmulWait sync.WaitGroup
fmulWait.Add(n)
for i := 0; i < n; i++ {
go func(index int) {
defer fmulWait.Done()
sender.deltas[index] = myGroup.RandomNonZeroScalar(rand.Reader)
m0iScalar := myGroup.NewScalar()
m0iScalar.Sub(sender.deltas[index], sender.a)

m0iByte, err := m0iScalar.MarshalBinary()
if err != nil {
panic(err)
}
sender.m0s[index] = m0iByte

m1iScalar := myGroup.NewScalar()
m1iScalar.Add(sender.deltas[index], sender.a)

m1iByte, err := m1iScalar.MarshalBinary()
if err != nil {
panic(err)
}
sender.m1s[index] = m1iByte

// n Base OT Sender Initialization
var BaseOTSender simplestOT.SenderSimOT
BaseOTSender.InitSender(myGroup, sender.m0s[index], sender.m1s[index], index)
sender.baseOTsenders[index] = BaseOTSender
}(i)
}
fmulWait.Wait()

sender.s1 = myGroup.NewScalar()
sender.s1.SetUint64(0)

As := make([]group.Element, n)
for i := 0; i < n; i++ {
As[i] = sender.baseOTsenders[i].A.Copy()
}
return As

}

// ---- Round1: Sender sends As to receiver ----

// Receiver randomly generates n choice bits, either 0 or 1 for BaseOT, either -1(Scalar) or 1(Scalar) for Fmul
// Matching 0 or 1 to -1(Scalar) or 1(Scalar) in constant time
// Input: myGroup, the group we operate in
// Input: As, the n [ai]G received from sender
// Input: b, the receiver private input
// Input: n, the total number of BaseOT
// Output: Array of B = [b]G if c == 0, B = A+[b]G if c == 1
func (receiver *ReceiverFmul) ReceiverRound1(myGroup group.Group, As []group.Element, b group.Scalar, n int) []group.Element {
receiver.myGroup = myGroup
receiver.b = b.Copy()
receiver.ts = make([]int, n)
receiver.tsScalar = make([]group.Scalar, n)
receiver.zs = make([]group.Scalar, n)
receiver.vs = make([]group.Scalar, n)

Scalar1 := myGroup.NewScalar()
Scalar1.SetUint64(1)
Scalar1.Neg(Scalar1)

receiver.baseOTreceivers = make([]simplestOT.ReceiverSimOT, n)

var fmulWait sync.WaitGroup
fmulWait.Add(n)
for i := 0; i < n; i++ {
go func(index int) {
defer fmulWait.Done()
currScalar := myGroup.NewScalar()
binaryBig, err := rand.Int(rand.Reader, big.NewInt(2))
if err != nil {
panic(err)
}
receiver.ts[index] = int(binaryBig.Int64())
currScalar.SetUint64(uint64(2 * receiver.ts[index]))
currScalar.Neg(currScalar)
receiver.tsScalar[index] = Scalar1.Copy()
receiver.tsScalar[index].Sub(receiver.tsScalar[index], currScalar)
receiver.zs[index] = myGroup.NewScalar()
receiver.baseOTreceivers[index].Round1Receiver(myGroup, receiver.ts[index], index, As[index])
}(i)
}
fmulWait.Wait()

receiver.s2 = myGroup.NewScalar()
receiver.s2.SetUint64(0)

Bs := make([]group.Element, n)
for i := 0; i < n; i++ {
Bs[i] = receiver.baseOTreceivers[i].B.Copy()
}
return Bs
}

// ---- Round 2: Receiver sends Bs = [bi]G or Ai+[bi]G to sender ----

// Input: Bs, the n [bi]G or Ai+[bi]G received from receiver
// Input: n, the total number of BaseOT
// Output: Array of m0s encryptions and m1s encryptions
func (sender *SenderFmul) SenderRound2(Bs []group.Element, n int) ([][]byte, [][]byte) {
var fmulWait sync.WaitGroup
fmulWait.Add(n)
for i := 0; i < n; i++ {
go func(index int) {
defer fmulWait.Done()
sender.baseOTsenders[index].Round2Sender(Bs[index])
}(i)
}
fmulWait.Wait()

e0s := make([][]byte, n)
e1s := make([][]byte, n)
for i := 0; i < n; i++ {
e0s[i], e1s[i] = sender.baseOTsenders[i].Returne0e1()
}

return e0s, e1s
}

// ---- Round 3: Sender sends e0s, e1s to receiver ----

// Input: e0s, e1s, the encryptions of m0s and m1s
// Input: n, the total number of BaseOT
// Ouptut: Blinding sigma and Array of v
func (receiver *ReceiverFmul) ReceiverRound3(e0s, e1s [][]byte, n int) (group.Scalar, []group.Scalar, error) {
var errGroup errgroup.Group
receiver.s2.SetUint64(0)

for i := 0; i < n; i++ {
func(index int) {
errGroup.Go(func() error {
errDec := receiver.baseOTreceivers[index].Round3Receiver(e0s[index], e1s[index], receiver.ts[index])
if errDec != nil {
return errDec
}
mc := receiver.baseOTreceivers[index].Returnmc()
errByte := receiver.zs[index].UnmarshalBinary(mc)
if errByte != nil {
panic(errByte)
}
return nil
})
}(i)
}

if err := errGroup.Wait(); err != nil {
return nil, nil, err
}

// v \times t = b
vn := receiver.b.Copy()
for i := 0; i < n-1; i++ {
receiver.vs[i] = receiver.myGroup.RandomNonZeroScalar(rand.Reader)
vt := receiver.myGroup.NewScalar()
vt.Mul(receiver.tsScalar[i], receiver.vs[i])
vn.Sub(vn, vt)
}
tsnInv := receiver.myGroup.NewScalar()
tsnInv.Inv(receiver.tsScalar[n-1])
vn.Mul(vn, tsnInv)
receiver.vs[n-1] = vn
receiver.sigma = receiver.myGroup.RandomNonZeroScalar(rand.Reader)

for i := 0; i < n; i++ {
vzi := receiver.myGroup.NewScalar()
vzi.Mul(receiver.vs[i], receiver.zs[i])
receiver.s2.Add(receiver.s2, vzi)
}

// s2 = v \times z + sigma
receiver.s2.Add(receiver.s2, receiver.sigma)

sigma := receiver.sigma.Copy()
vs := make([]group.Scalar, n)
for i := 0; i < n; i++ {
vs[i] = receiver.vs[i].Copy()
}

return sigma, vs, nil
}

// ---- Round 4: receiver sends sigma as well as vs to sender ----

// Input: vs, from receiver
// Input: sigma, blinding from receiver
// Input: n, the total number of BaseOT
func (sender *SenderFmul) SenderRound4(vs []group.Scalar, sigma group.Scalar, n int) {
sender.s1.SetUint64(0)

vdelta := sender.myGroup.NewScalar()

// s1 = - v \times delta - sigma
for i := 0; i < n; i++ {
vdelta.Mul(vs[i], sender.deltas[i])
sender.s1.Sub(sender.s1, vdelta)
}
sender.s1.Sub(sender.s1, sigma)
}

func (sender *SenderFmul) Returns1() group.Scalar {
return sender.s1
}

func (receiver *ReceiverFmul) Returns2() group.Scalar {
return receiver.s2
}
28 changes: 28 additions & 0 deletions tss/ecdsa/ot/Fmul/FmulParty.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package Fmul

import (
"github.com/cloudflare/circl/group"
"github.com/cloudflare/circl/ot/simplestOT"
)

type SenderFmul struct {
a group.Scalar // The input of the sender
deltas []group.Scalar // The n random of the sender
m0s [][]byte // The n m0 messages of the sender
m1s [][]byte // The n m1 messages of the sender
baseOTsenders []simplestOT.SenderSimOT // The n senders for n baseOT
s1 group.Scalar // The final additive share
myGroup group.Group // The elliptic curve we operate in
}

type ReceiverFmul struct {
b group.Scalar // The input of the receiver
ts []int // The n choice bits of the receiver, either 0 or 1
tsScalar []group.Scalar // The scalar version of n choice bits, either -1 or 1
zs []group.Scalar // The n OT transfered messages from the sender
vs []group.Scalar // The n random of the receiver such that v*t = b
sigma group.Scalar // The blinding scalar
baseOTreceivers []simplestOT.ReceiverSimOT // The n receivers for n baseOT
s2 group.Scalar // The final additive share
myGroup group.Group // The elliptic curve we operate in
}

0 comments on commit 60027e9

Please sign in to comment.