Skip to content

Commit 60027e9

Browse files
author
zhdllwyc
committed
FMUL based on OT
1 parent 1689a9b commit 60027e9

File tree

6 files changed

+500
-0
lines changed

6 files changed

+500
-0
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ go 1.16
55
require (
66
github.com/bwesterb/go-ristretto v1.2.2
77
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
8+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
89
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10
910
)

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ github.com/bwesterb/go-ristretto v1.2.2/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7N
33
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c=
44
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
55
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
6+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
7+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
68
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
79
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
810
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

tss/ecdsa/ot/Fmul/Fmul.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Reference: https://eprint.iacr.org/2021/1373.pdf
2+
// Sender and receiver has private input a and b
3+
// Sender and receiver get s1 and s2 such that a*b = s1+s2 from Fmul
4+
// This scheme based on pure OT but not OT extension
5+
6+
package Fmul
7+
8+
import (
9+
"github.com/cloudflare/circl/group"
10+
)
11+
12+
// Input: myGroup, the group we operate in
13+
// Input: securityParameter
14+
// Output: The number of BaseOT needed
15+
func DecideNumOT(myGroup group.Group, sp int) int {
16+
numBaseOT := int(myGroup.Params().ScalarLength*8) + sp
17+
return numBaseOT
18+
}
19+
20+
// Input: aInput, bInput, the private input from both sender and receiver
21+
// Input: myGroup, the group we operate in
22+
// Input: n, the total number of BaseOT
23+
func Fmul(sender *SenderFmul, receiver *ReceiverFmul, aInput, bInput group.Scalar, myGroup group.Group, n int) error {
24+
// Sender Initialization
25+
As := sender.SenderInit(myGroup, aInput, n)
26+
27+
// ---- Round1: Sender sends As to receiver ----
28+
29+
Bs := receiver.ReceiverRound1(myGroup, As, bInput, n)
30+
31+
// ---- Round 2: Receiver sends Bs = [bi]G or Ai+[bi]G to sender ----
32+
33+
e0s, e1s := sender.SenderRound2(Bs, n)
34+
35+
// ---- Round 3: Sender sends e0s, e1s to receiver ----
36+
37+
sigma, vs, errDec := receiver.ReceiverRound3(e0s, e1s, n)
38+
if errDec != nil {
39+
return errDec
40+
}
41+
42+
// ---- Round 4: receiver sends sigma as well as vs to sender ----
43+
44+
sender.SenderRound4(vs, sigma, n)
45+
46+
return nil
47+
}

tss/ecdsa/ot/Fmul/FmulLocal.go

+235
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
package Fmul
2+
3+
import (
4+
"crypto/rand"
5+
"math/big"
6+
"sync"
7+
8+
"github.com/cloudflare/circl/group"
9+
"github.com/cloudflare/circl/ot/simplestOT"
10+
"golang.org/x/sync/errgroup"
11+
)
12+
13+
// ---- Sender Initialization ----
14+
15+
// Input: myGroup, the group we operate in
16+
// Input: a, the sender private input
17+
// Input: n, the total number of BaseOT
18+
// Output: Array of A=[ai]G for n BaseOT
19+
func (sender *SenderFmul) SenderInit(myGroup group.Group, a group.Scalar, n int) []group.Element {
20+
sender.myGroup = myGroup
21+
sender.a = a.Copy()
22+
sender.deltas = make([]group.Scalar, n)
23+
sender.m0s = make([][]byte, n)
24+
sender.m1s = make([][]byte, n)
25+
sender.baseOTsenders = make([]simplestOT.SenderSimOT, n)
26+
27+
var fmulWait sync.WaitGroup
28+
fmulWait.Add(n)
29+
for i := 0; i < n; i++ {
30+
go func(index int) {
31+
defer fmulWait.Done()
32+
sender.deltas[index] = myGroup.RandomNonZeroScalar(rand.Reader)
33+
m0iScalar := myGroup.NewScalar()
34+
m0iScalar.Sub(sender.deltas[index], sender.a)
35+
36+
m0iByte, err := m0iScalar.MarshalBinary()
37+
if err != nil {
38+
panic(err)
39+
}
40+
sender.m0s[index] = m0iByte
41+
42+
m1iScalar := myGroup.NewScalar()
43+
m1iScalar.Add(sender.deltas[index], sender.a)
44+
45+
m1iByte, err := m1iScalar.MarshalBinary()
46+
if err != nil {
47+
panic(err)
48+
}
49+
sender.m1s[index] = m1iByte
50+
51+
// n Base OT Sender Initialization
52+
var BaseOTSender simplestOT.SenderSimOT
53+
BaseOTSender.InitSender(myGroup, sender.m0s[index], sender.m1s[index], index)
54+
sender.baseOTsenders[index] = BaseOTSender
55+
}(i)
56+
}
57+
fmulWait.Wait()
58+
59+
sender.s1 = myGroup.NewScalar()
60+
sender.s1.SetUint64(0)
61+
62+
As := make([]group.Element, n)
63+
for i := 0; i < n; i++ {
64+
As[i] = sender.baseOTsenders[i].A.Copy()
65+
}
66+
return As
67+
68+
}
69+
70+
// ---- Round1: Sender sends As to receiver ----
71+
72+
// Receiver randomly generates n choice bits, either 0 or 1 for BaseOT, either -1(Scalar) or 1(Scalar) for Fmul
73+
// Matching 0 or 1 to -1(Scalar) or 1(Scalar) in constant time
74+
// Input: myGroup, the group we operate in
75+
// Input: As, the n [ai]G received from sender
76+
// Input: b, the receiver private input
77+
// Input: n, the total number of BaseOT
78+
// Output: Array of B = [b]G if c == 0, B = A+[b]G if c == 1
79+
func (receiver *ReceiverFmul) ReceiverRound1(myGroup group.Group, As []group.Element, b group.Scalar, n int) []group.Element {
80+
receiver.myGroup = myGroup
81+
receiver.b = b.Copy()
82+
receiver.ts = make([]int, n)
83+
receiver.tsScalar = make([]group.Scalar, n)
84+
receiver.zs = make([]group.Scalar, n)
85+
receiver.vs = make([]group.Scalar, n)
86+
87+
Scalar1 := myGroup.NewScalar()
88+
Scalar1.SetUint64(1)
89+
Scalar1.Neg(Scalar1)
90+
91+
receiver.baseOTreceivers = make([]simplestOT.ReceiverSimOT, n)
92+
93+
var fmulWait sync.WaitGroup
94+
fmulWait.Add(n)
95+
for i := 0; i < n; i++ {
96+
go func(index int) {
97+
defer fmulWait.Done()
98+
currScalar := myGroup.NewScalar()
99+
binaryBig, err := rand.Int(rand.Reader, big.NewInt(2))
100+
if err != nil {
101+
panic(err)
102+
}
103+
receiver.ts[index] = int(binaryBig.Int64())
104+
currScalar.SetUint64(uint64(2 * receiver.ts[index]))
105+
currScalar.Neg(currScalar)
106+
receiver.tsScalar[index] = Scalar1.Copy()
107+
receiver.tsScalar[index].Sub(receiver.tsScalar[index], currScalar)
108+
receiver.zs[index] = myGroup.NewScalar()
109+
receiver.baseOTreceivers[index].Round1Receiver(myGroup, receiver.ts[index], index, As[index])
110+
}(i)
111+
}
112+
fmulWait.Wait()
113+
114+
receiver.s2 = myGroup.NewScalar()
115+
receiver.s2.SetUint64(0)
116+
117+
Bs := make([]group.Element, n)
118+
for i := 0; i < n; i++ {
119+
Bs[i] = receiver.baseOTreceivers[i].B.Copy()
120+
}
121+
return Bs
122+
}
123+
124+
// ---- Round 2: Receiver sends Bs = [bi]G or Ai+[bi]G to sender ----
125+
126+
// Input: Bs, the n [bi]G or Ai+[bi]G received from receiver
127+
// Input: n, the total number of BaseOT
128+
// Output: Array of m0s encryptions and m1s encryptions
129+
func (sender *SenderFmul) SenderRound2(Bs []group.Element, n int) ([][]byte, [][]byte) {
130+
var fmulWait sync.WaitGroup
131+
fmulWait.Add(n)
132+
for i := 0; i < n; i++ {
133+
go func(index int) {
134+
defer fmulWait.Done()
135+
sender.baseOTsenders[index].Round2Sender(Bs[index])
136+
}(i)
137+
}
138+
fmulWait.Wait()
139+
140+
e0s := make([][]byte, n)
141+
e1s := make([][]byte, n)
142+
for i := 0; i < n; i++ {
143+
e0s[i], e1s[i] = sender.baseOTsenders[i].Returne0e1()
144+
}
145+
146+
return e0s, e1s
147+
}
148+
149+
// ---- Round 3: Sender sends e0s, e1s to receiver ----
150+
151+
// Input: e0s, e1s, the encryptions of m0s and m1s
152+
// Input: n, the total number of BaseOT
153+
// Ouptut: Blinding sigma and Array of v
154+
func (receiver *ReceiverFmul) ReceiverRound3(e0s, e1s [][]byte, n int) (group.Scalar, []group.Scalar, error) {
155+
var errGroup errgroup.Group
156+
receiver.s2.SetUint64(0)
157+
158+
for i := 0; i < n; i++ {
159+
func(index int) {
160+
errGroup.Go(func() error {
161+
errDec := receiver.baseOTreceivers[index].Round3Receiver(e0s[index], e1s[index], receiver.ts[index])
162+
if errDec != nil {
163+
return errDec
164+
}
165+
mc := receiver.baseOTreceivers[index].Returnmc()
166+
errByte := receiver.zs[index].UnmarshalBinary(mc)
167+
if errByte != nil {
168+
panic(errByte)
169+
}
170+
return nil
171+
})
172+
}(i)
173+
}
174+
175+
if err := errGroup.Wait(); err != nil {
176+
return nil, nil, err
177+
}
178+
179+
// v \times t = b
180+
vn := receiver.b.Copy()
181+
for i := 0; i < n-1; i++ {
182+
receiver.vs[i] = receiver.myGroup.RandomNonZeroScalar(rand.Reader)
183+
vt := receiver.myGroup.NewScalar()
184+
vt.Mul(receiver.tsScalar[i], receiver.vs[i])
185+
vn.Sub(vn, vt)
186+
}
187+
tsnInv := receiver.myGroup.NewScalar()
188+
tsnInv.Inv(receiver.tsScalar[n-1])
189+
vn.Mul(vn, tsnInv)
190+
receiver.vs[n-1] = vn
191+
receiver.sigma = receiver.myGroup.RandomNonZeroScalar(rand.Reader)
192+
193+
for i := 0; i < n; i++ {
194+
vzi := receiver.myGroup.NewScalar()
195+
vzi.Mul(receiver.vs[i], receiver.zs[i])
196+
receiver.s2.Add(receiver.s2, vzi)
197+
}
198+
199+
// s2 = v \times z + sigma
200+
receiver.s2.Add(receiver.s2, receiver.sigma)
201+
202+
sigma := receiver.sigma.Copy()
203+
vs := make([]group.Scalar, n)
204+
for i := 0; i < n; i++ {
205+
vs[i] = receiver.vs[i].Copy()
206+
}
207+
208+
return sigma, vs, nil
209+
}
210+
211+
// ---- Round 4: receiver sends sigma as well as vs to sender ----
212+
213+
// Input: vs, from receiver
214+
// Input: sigma, blinding from receiver
215+
// Input: n, the total number of BaseOT
216+
func (sender *SenderFmul) SenderRound4(vs []group.Scalar, sigma group.Scalar, n int) {
217+
sender.s1.SetUint64(0)
218+
219+
vdelta := sender.myGroup.NewScalar()
220+
221+
// s1 = - v \times delta - sigma
222+
for i := 0; i < n; i++ {
223+
vdelta.Mul(vs[i], sender.deltas[i])
224+
sender.s1.Sub(sender.s1, vdelta)
225+
}
226+
sender.s1.Sub(sender.s1, sigma)
227+
}
228+
229+
func (sender *SenderFmul) Returns1() group.Scalar {
230+
return sender.s1
231+
}
232+
233+
func (receiver *ReceiverFmul) Returns2() group.Scalar {
234+
return receiver.s2
235+
}

tss/ecdsa/ot/Fmul/FmulParty.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package Fmul
2+
3+
import (
4+
"github.com/cloudflare/circl/group"
5+
"github.com/cloudflare/circl/ot/simplestOT"
6+
)
7+
8+
type SenderFmul struct {
9+
a group.Scalar // The input of the sender
10+
deltas []group.Scalar // The n random of the sender
11+
m0s [][]byte // The n m0 messages of the sender
12+
m1s [][]byte // The n m1 messages of the sender
13+
baseOTsenders []simplestOT.SenderSimOT // The n senders for n baseOT
14+
s1 group.Scalar // The final additive share
15+
myGroup group.Group // The elliptic curve we operate in
16+
}
17+
18+
type ReceiverFmul struct {
19+
b group.Scalar // The input of the receiver
20+
ts []int // The n choice bits of the receiver, either 0 or 1
21+
tsScalar []group.Scalar // The scalar version of n choice bits, either -1 or 1
22+
zs []group.Scalar // The n OT transfered messages from the sender
23+
vs []group.Scalar // The n random of the receiver such that v*t = b
24+
sigma group.Scalar // The blinding scalar
25+
baseOTreceivers []simplestOT.ReceiverSimOT // The n receivers for n baseOT
26+
s2 group.Scalar // The final additive share
27+
myGroup group.Group // The elliptic curve we operate in
28+
}

0 commit comments

Comments
 (0)