Skip to content

Commit 6b783e5

Browse files
author
zhdllwyc
committed
simplest OT
1 parent 3af71e2 commit 6b783e5

File tree

4 files changed

+490
-0
lines changed

4 files changed

+490
-0
lines changed

ot/simplestOT/simplestOT.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Reference: https://eprint.iacr.org/2015/267.pdf (1 out of 2 OT case)
2+
// Sender has 2 messages m0, m1
3+
// Receiver receives mc based on the choice bit c
4+
5+
package simplestOT
6+
7+
import (
8+
"github.com/cloudflare/circl/group"
9+
)
10+
11+
// Input: myGroup, the group we operate in
12+
// Input: m0, m1 the 2 message of the sender
13+
// Input: choice, the bit c of the receiver
14+
// Input: index, the index of this BaseOT
15+
func BaseOT(myGroup group.Group, sender *SenderSimOT, receiver *ReceiverSimOT, m0, m1 []byte, choice, index int) error {
16+
17+
// Initialization
18+
A := sender.InitSender(myGroup, m0, m1, index)
19+
20+
// Round 1
21+
// Sender sends A to receiver
22+
B := receiver.Round1Receiver(myGroup, choice, index, A)
23+
24+
// Round 2
25+
// Receiver sends B to sender
26+
e0, e1 := sender.Round2Sender(B)
27+
28+
// Round 3
29+
// Sender sends e0 e1 to receiver
30+
errDec := receiver.Round3Receiver(e0, e1, receiver.c)
31+
if errDec != nil {
32+
return errDec
33+
}
34+
35+
return nil
36+
}

ot/simplestOT/simplestOTLocal.go

+240
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
package simplestOT
2+
3+
import (
4+
"crypto/aes"
5+
"crypto/cipher"
6+
"crypto/rand"
7+
"crypto/subtle"
8+
"errors"
9+
"io"
10+
11+
"github.com/cloudflare/circl/group"
12+
"golang.org/x/crypto/sha3"
13+
)
14+
15+
const keyLength = 16
16+
17+
// AES GCM encryption, we don't need to pad because our input is fixed length
18+
// Need to use authenticated encryption to defend against tampering on ciphertext
19+
// Input: key, plaintext message
20+
// Output: ciphertext
21+
func aesEncGCM(key, plaintext []byte) []byte {
22+
block, err := aes.NewCipher(key)
23+
if err != nil {
24+
panic(err)
25+
}
26+
27+
aesgcm, err := cipher.NewGCM(block)
28+
if err != nil {
29+
panic(err.Error())
30+
}
31+
32+
nonce := make([]byte, aesgcm.NonceSize())
33+
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
34+
panic(err)
35+
}
36+
37+
ciphertext := aesgcm.Seal(nonce, nonce, plaintext, nil)
38+
return ciphertext
39+
}
40+
41+
// AES GCM decryption
42+
// Input: key, ciphertext message
43+
// Output: plaintext
44+
func aesDecGCM(key, ciphertext []byte) ([]byte, error) {
45+
block, err := aes.NewCipher(key)
46+
if err != nil {
47+
panic(err)
48+
}
49+
aesgcm, err := cipher.NewGCM(block)
50+
if err != nil {
51+
panic(err.Error())
52+
}
53+
nonceSize := aesgcm.NonceSize()
54+
if len(ciphertext) < nonceSize {
55+
return nil, errors.New("ciphertext too short")
56+
}
57+
58+
nonce, encryptedMessage := ciphertext[:nonceSize], ciphertext[nonceSize:]
59+
60+
plaintext, err := aesgcm.Open(nil, nonce, encryptedMessage, nil)
61+
62+
return plaintext, err
63+
}
64+
65+
// Initialization
66+
67+
// Input: myGroup, the group we operate in
68+
// Input: m0, m1 the 2 message of the sender
69+
// Input: index, the index of this BaseOT
70+
// Output: A = [a]G, a the sender randomness
71+
func (sender *SenderSimOT) InitSender(myGroup group.Group, m0, m1 []byte, index int) group.Element {
72+
sender.a = myGroup.RandomNonZeroScalar(rand.Reader)
73+
sender.k0 = make([]byte, keyLength)
74+
sender.k1 = make([]byte, keyLength)
75+
sender.m0 = m0
76+
sender.m1 = m1
77+
sender.index = index
78+
sender.A = myGroup.NewElement()
79+
sender.A.MulGen(sender.a)
80+
sender.myGroup = myGroup
81+
return sender.A.Copy()
82+
}
83+
84+
// Round 1
85+
86+
// ---- sender should send A to receiver ----
87+
88+
// Input: myGroup, the group we operate in
89+
// Input: choice, the receiver choice bit
90+
// Input: index, the index of this BaseOT
91+
// Input: A, from sender
92+
// Output: B = [b]G if c == 0, B = A+[b]G if c == 1 (Implementation in constant time). b, the receiver randomness
93+
func (receiver *ReceiverSimOT) Round1Receiver(myGroup group.Group, choice int, index int, A group.Element) group.Element {
94+
receiver.b = myGroup.RandomNonZeroScalar(rand.Reader)
95+
receiver.c = choice
96+
receiver.kR = make([]byte, keyLength)
97+
receiver.index = index
98+
receiver.A = A
99+
receiver.myGroup = myGroup
100+
101+
bG := myGroup.NewElement()
102+
bG.MulGen(receiver.b)
103+
cScalar := myGroup.NewScalar()
104+
cScalar.SetUint64(uint64(receiver.c))
105+
add := receiver.A.Copy()
106+
add.Mul(receiver.A, cScalar)
107+
receiver.B = myGroup.NewElement()
108+
receiver.B.Add(bG, add)
109+
110+
return receiver.B.Copy()
111+
}
112+
113+
// Round 2
114+
115+
// ---- receiver should send B to sender ----
116+
117+
// Input: B from the receiver
118+
// Output: e0, e1, encryption of m0 and m1 under key k0, k1
119+
func (sender *SenderSimOT) Round2Sender(B group.Element) ([]byte, []byte) {
120+
sender.B = B
121+
122+
aB := sender.myGroup.NewElement()
123+
aB.Mul(sender.B, sender.a)
124+
maA := sender.myGroup.NewElement()
125+
maA.Mul(sender.A, sender.a)
126+
maA.Neg(maA)
127+
aBaA := sender.myGroup.NewElement()
128+
aBaA.Add(aB, maA)
129+
130+
// Hash the whole transcript A|B|...
131+
AByte, errByte := sender.A.MarshalBinary()
132+
if errByte != nil {
133+
panic(errByte)
134+
}
135+
BByte, errByte := sender.B.MarshalBinary()
136+
if errByte != nil {
137+
panic(errByte)
138+
}
139+
aBByte, errByte := aB.MarshalBinary()
140+
if errByte != nil {
141+
panic(errByte)
142+
}
143+
hashByte0 := append(AByte, BByte...)
144+
hashByte0 = append(hashByte0, aBByte...)
145+
146+
s := sha3.NewShake128()
147+
_, errWrite := s.Write(hashByte0)
148+
if errWrite != nil {
149+
panic(errWrite)
150+
}
151+
_, errRead := s.Read(sender.k0)
152+
if errRead != nil {
153+
panic(errRead)
154+
}
155+
156+
aBaAByte, errByte := aBaA.MarshalBinary()
157+
if errByte != nil {
158+
panic(errByte)
159+
}
160+
hashByte1 := append(AByte, BByte...)
161+
hashByte1 = append(hashByte1, aBaAByte...)
162+
s = sha3.NewShake128()
163+
_, errWrite = s.Write(hashByte1)
164+
if errWrite != nil {
165+
panic(errWrite)
166+
}
167+
_, errRead = s.Read(sender.k1)
168+
if errRead != nil {
169+
panic(errRead)
170+
}
171+
172+
e0 := aesEncGCM(sender.k0, sender.m0)
173+
sender.e0 = e0
174+
175+
e1 := aesEncGCM(sender.k1, sender.m1)
176+
sender.e1 = e1
177+
178+
return sender.e0, sender.e1
179+
}
180+
181+
// Round 3
182+
183+
// ---- sender should send e0, e1 to receiver ----
184+
185+
// Input: e0, e1: encryption of m0 and m1 from the sender
186+
// Input: choice, choice bit of receiver
187+
// Choose e0 or e1 based on choice bit in constant time
188+
func (receiver *ReceiverSimOT) Round3Receiver(e0, e1 []byte, choice int) error {
189+
receiver.ec = make([]byte, len(e1))
190+
// If c == 1, copy e1
191+
subtle.ConstantTimeCopy(choice, receiver.ec, e1)
192+
// If c == 0, copy e0
193+
subtle.ConstantTimeCopy(1-choice, receiver.ec, e0)
194+
195+
AByte, errByte := receiver.A.MarshalBinary()
196+
if errByte != nil {
197+
panic(errByte)
198+
}
199+
BByte, errByte := receiver.B.MarshalBinary()
200+
if errByte != nil {
201+
panic(errByte)
202+
}
203+
bA := receiver.myGroup.NewElement()
204+
bA.Mul(receiver.A, receiver.b)
205+
bAByte, errByte := bA.MarshalBinary()
206+
if errByte != nil {
207+
panic(errByte)
208+
}
209+
// Hash the whole transcript so far
210+
hashByte := append(AByte, BByte...)
211+
hashByte = append(hashByte, bAByte...)
212+
213+
s := sha3.NewShake128()
214+
_, errWrite := s.Write(hashByte)
215+
if errWrite != nil {
216+
panic(errWrite)
217+
}
218+
_, errRead := s.Read(receiver.kR) // kR, decryption key of mc
219+
if errRead != nil {
220+
panic(errRead)
221+
}
222+
mc, errDec := aesDecGCM(receiver.kR, receiver.ec)
223+
if errDec != nil {
224+
return errDec
225+
}
226+
receiver.mc = mc
227+
return nil
228+
}
229+
230+
func (receiver *ReceiverSimOT) Returnmc() []byte {
231+
return receiver.mc
232+
}
233+
234+
func (sender *SenderSimOT) Returne0e1() ([]byte, []byte) {
235+
return sender.e0, sender.e1
236+
}
237+
238+
func (sender *SenderSimOT) Returnm0m1() ([]byte, []byte) {
239+
return sender.m0, sender.m1
240+
}

ot/simplestOT/simplestOTParty.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package simplestOT
2+
3+
import "github.com/cloudflare/circl/group"
4+
5+
type SenderSimOT struct {
6+
index int // Indicate which OT
7+
m0 []byte // The M0 message from sender
8+
m1 []byte // The M1 message from sender
9+
a group.Scalar // The randomness of the sender
10+
A group.Element // [a]G
11+
B group.Element // The random group element from the receiver
12+
k0 []byte // The encryption key of M0
13+
k1 []byte // The encryption key of M1
14+
e0 []byte // The encryption of M0 under k0
15+
e1 []byte // The encryption of M1 under k1
16+
myGroup group.Group // The elliptic curve we operate in
17+
}
18+
19+
type ReceiverSimOT struct {
20+
index int // Indicate which OT
21+
c int // The choice bit of the receiver
22+
A group.Element // The random group element from the sender
23+
b group.Scalar // The randomness of the receiver
24+
B group.Element // B = [b]G if c == 0, B = A+[b]G if c == 1
25+
kR []byte // The decryption key of receiver
26+
ec []byte // The encryption of mc
27+
mc []byte // The decrypted message from sender
28+
myGroup group.Group // The elliptic curve we operate in
29+
}

0 commit comments

Comments
 (0)