|
| 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 | +} |
0 commit comments