1
- //
2
1
// Package oprf provides an implementation of Oblivious Pseudorandom Functions
3
- // (OPRFs), as defined on draft-irtf-cfrg-voprf.
2
+ // (OPRFs), as defined on draft-irtf-cfrg-voprf: https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/
4
3
// It implements:
5
4
// For a Client:
6
5
// - Blind
11
10
// - Setup
12
11
// - Evaluate
13
12
// - VerifyFinalize
14
- // References
15
- // - OPRF draft: https://datatracker.ietf.org/doc/draft-irtf-cfrg-voprf/
16
13
package oprf
17
14
18
15
import (
@@ -22,6 +19,7 @@ import (
22
19
"encoding/binary"
23
20
"errors"
24
21
"hash"
22
+ "io"
25
23
26
24
"github.com/cloudflare/circl/oprf/group"
27
25
)
45
43
46
44
var (
47
45
// ErrUnsupportedGroup is an error stating that the ciphersuite chosen is not supported
48
- ErrUnsupportedGroup = errors .New ("the chosen group is not supported " )
46
+ ErrUnsupportedGroup = errors .New ("unsupported group" )
49
47
)
50
48
51
49
// BlindToken corresponds to a token that has been blinded.
@@ -75,21 +73,21 @@ type KeyPair struct {
75
73
76
74
// Client is a representation of a Client during protocol execution.
77
75
type Client struct {
78
- suite * group.Ciphersuite
79
- ctx []byte
76
+ suite * group.Ciphersuite
77
+ context []byte
80
78
}
81
79
82
80
// Server is a representation of a Server during protocol execution.
83
81
type Server struct {
84
- suite * group.Ciphersuite
85
- ctx []byte
86
- Kp * KeyPair
82
+ suite * group.Ciphersuite
83
+ context []byte
84
+ Kp * KeyPair
87
85
}
88
86
89
87
func generateContext (id SuiteID ) []byte {
90
- ctx := [3 ]byte {OPRFMode , 0 , byte (id )}
88
+ context := [3 ]byte {OPRFMode , 0 , byte (id )}
91
89
92
- return ctx [:]
90
+ return context [:]
93
91
}
94
92
95
93
// Serialize serializes a KeyPair elements into byte arrays.
@@ -132,11 +130,11 @@ func assignKeyPair(suite *group.Ciphersuite, privK, pubK []byte) (*KeyPair, erro
132
130
return kp , nil
133
131
}
134
132
135
- func suiteFromID (id SuiteID , ctx []byte ) (* group.Ciphersuite , error ) {
133
+ func suiteFromID (id SuiteID , context []byte ) (* group.Ciphersuite , error ) {
136
134
var err error
137
135
var suite * group.Ciphersuite
138
136
139
- suite , err = group .NewSuite (uint16 (id ), ctx )
137
+ suite , err = group .NewSuite (uint16 (id ), context )
140
138
if err != nil {
141
139
return nil , err
142
140
}
@@ -146,26 +144,26 @@ func suiteFromID(id SuiteID, ctx []byte) (*group.Ciphersuite, error) {
146
144
147
145
// NewServer creates a new instantiation of a Server.
148
146
func NewServer (id SuiteID ) (* Server , error ) {
149
- ctx := generateContext (id )
147
+ context := generateContext (id )
150
148
151
- suite , err := suiteFromID (id , ctx )
149
+ suite , err := suiteFromID (id , context )
152
150
if err != nil {
153
151
return nil , err
154
152
}
155
153
keyPair := GenerateKeyPair (suite )
156
154
157
155
return & Server {
158
- suite : suite ,
159
- ctx : ctx ,
160
- Kp : keyPair }, nil
156
+ suite : suite ,
157
+ context : context ,
158
+ Kp : keyPair }, nil
161
159
}
162
160
163
161
// NewServerWithKeyPair creates a new instantiation of a Server. It can create
164
162
// a server with existing keys or use pre-generated keys.
165
163
func NewServerWithKeyPair (id SuiteID , privK , pubK []byte ) (* Server , error ) {
166
- ctx := generateContext (id )
164
+ context := generateContext (id )
167
165
168
- suite , err := suiteFromID (id , ctx )
166
+ suite , err := suiteFromID (id , context )
169
167
if err != nil {
170
168
return nil , err
171
169
}
@@ -176,9 +174,9 @@ func NewServerWithKeyPair(id SuiteID, privK, pubK []byte) (*Server, error) {
176
174
}
177
175
178
176
return & Server {
179
- suite : suite ,
180
- ctx : ctx ,
181
- Kp : keyPair }, nil
177
+ suite : suite ,
178
+ context : context ,
179
+ Kp : keyPair }, nil
182
180
}
183
181
184
182
// Evaluate blindly signs a client token.
@@ -195,8 +193,18 @@ func (s *Server) Evaluate(b BlindToken) (*Evaluation, error) {
195
193
return & Evaluation {ser }, nil
196
194
}
197
195
196
+ func mustWrite (h io.Writer , data []byte ) {
197
+ dataLen , err := h .Write (data )
198
+ if err != nil {
199
+ panic (err )
200
+ }
201
+ if len (data ) != dataLen {
202
+ panic ("failed to write" )
203
+ }
204
+ }
205
+
198
206
// FinalizeHash computes the final hash for the suite.
199
- func finalizeHash (c * group.Ciphersuite , data , iToken , info , ctx []byte ) []byte {
207
+ func finalizeHash (c * group.Ciphersuite , data , iToken , info , context []byte ) []byte {
200
208
var h hash.Hash
201
209
if c .Hash == "sha256" {
202
210
h = sha256 .New ()
@@ -207,23 +215,23 @@ func finalizeHash(c *group.Ciphersuite, data, iToken, info, ctx []byte) []byte {
207
215
lenBuf := make ([]byte , 2 )
208
216
209
217
binary .BigEndian .PutUint16 (lenBuf , uint16 (len (data )))
210
- _ , _ = h . Write ( lenBuf )
211
- _ , _ = h . Write ( data )
218
+ mustWrite ( h , lenBuf )
219
+ mustWrite ( h , data )
212
220
213
221
binary .BigEndian .PutUint16 (lenBuf , uint16 (len (iToken )))
214
- _ , _ = h . Write ( lenBuf )
215
- _ , _ = h . Write ( iToken )
222
+ mustWrite ( h , lenBuf )
223
+ mustWrite ( h , iToken )
216
224
217
225
binary .BigEndian .PutUint16 (lenBuf , uint16 (len (info )))
218
- _ , _ = h . Write ( lenBuf )
219
- _ , _ = h . Write ( info )
226
+ mustWrite ( h , lenBuf )
227
+ mustWrite ( h , info )
220
228
221
229
dst := []byte ("VOPRF05-Finalize-" )
222
- dst = append (dst , ctx ... )
230
+ dst = append (dst , context ... )
223
231
224
232
binary .BigEndian .PutUint16 (lenBuf , uint16 (len (dst )))
225
- _ , _ = h . Write ( lenBuf )
226
- _ , _ = h . Write ( dst )
233
+ mustWrite ( h , lenBuf )
234
+ mustWrite ( h , dst )
227
235
228
236
return h .Sum (nil )
229
237
}
@@ -238,7 +246,7 @@ func (s *Server) FullEvaluate(in, info []byte) ([]byte, error) {
238
246
t := p .ScalarMult (s .Kp .PrivK )
239
247
iToken := t .Serialize ()
240
248
241
- h := finalizeHash (s .suite , in , iToken , info , s .ctx )
249
+ h := finalizeHash (s .suite , in , iToken , info , s .context )
242
250
243
251
return h , nil
244
252
}
@@ -257,30 +265,30 @@ func (s *Server) VerifyFinalize(in, info, out []byte) bool {
257
265
return false
258
266
}
259
267
260
- h := finalizeHash (s .suite , in , e .element , info , s .ctx )
268
+ h := finalizeHash (s .suite , in , e .element , info , s .context )
261
269
return subtle .ConstantTimeCompare (h , out ) == 1
262
270
}
263
271
264
272
// NewClient creates a new instantiation of a Client.
265
273
func NewClient (id SuiteID ) (* Client , error ) {
266
- ctx := generateContext (id )
274
+ context := generateContext (id )
267
275
268
- suite , err := suiteFromID (id , ctx )
276
+ suite , err := suiteFromID (id , context )
269
277
if err != nil {
270
278
return nil , err
271
279
}
272
280
273
281
return & Client {
274
- suite : suite ,
275
- ctx : ctx }, nil
282
+ suite : suite ,
283
+ context : context }, nil
276
284
}
277
285
278
286
// ClientRequest is a structure to encapsulate the output of a Request call.
279
287
type ClientRequest struct {
280
- suite * group.Ciphersuite
281
- ctx []byte
282
- token * Token
283
- bToken BlindToken
288
+ suite * group.Ciphersuite
289
+ context []byte
290
+ token * Token
291
+ BlindedToken BlindToken
284
292
}
285
293
286
294
// Request generates a token and its blinded version.
@@ -293,10 +301,10 @@ func (c *Client) Request(in []byte) (*ClientRequest, error) {
293
301
}
294
302
295
303
t := p .ScalarMult (r )
296
- bToken := t .Serialize ()
304
+ BlindedToken := t .Serialize ()
297
305
298
306
tk := & Token {in , r }
299
- return & ClientRequest {c .suite , c .ctx , tk , bToken }, nil
307
+ return & ClientRequest {c .suite , c .context , tk , BlindedToken }, nil
300
308
}
301
309
302
310
// Finalize computes the signed token from the server Evaluation and returns
@@ -314,6 +322,6 @@ func (cr *ClientRequest) Finalize(e *Evaluation, info []byte) ([]byte, error) {
314
322
tt := p .ScalarMult (rInv )
315
323
iToken := tt .Serialize ()
316
324
317
- h := finalizeHash (cr .suite , cr .token .data , iToken , info , cr .ctx )
325
+ h := finalizeHash (cr .suite , cr .token .data , iToken , info , cr .context )
318
326
return h , nil
319
327
}
0 commit comments