Skip to content

Commit 76b537c

Browse files
committed
circl: Update to 3977848c88c641772e447c63a0ec29c8f4085e58
This change upgrades CIRCL's implementation of draft-irtf-cfrg-hpke-07 to 08. This breaks unit tests for ECH in crypto/tls, which currently expects HPKE-07. It also modifies the implementation of OPRF. Manually removed Ristretto code, which includes external dependencies that break ./all.bash.
1 parent 33dbd35 commit 76b537c

File tree

8 files changed

+111
-86
lines changed

8 files changed

+111
-86
lines changed

src/circl/hpke/hpke.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
"circl/kem"
2323
)
2424

25-
const versionLabel = "HPKE-07"
25+
const versionLabel = "HPKE-v1"
2626

2727
// Context defines the capabilities of an HPKE context.
2828
type Context interface {

src/circl/hpke/testdata/vectors_v07.json renamed to src/circl/hpke/testdata/vectors_v08_779d028.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/circl/hpke/vectors_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import (
1515

1616
func TestVectors(t *testing.T) {
1717
// Test vectors from
18-
// https://github.com/cfrg/draft-irtf-cfrg-hpke/blob/draft-irtf-cfrg-hpke-07/test-vectors.json
19-
vectors := readFile(t, "testdata/vectors_v07.json")
18+
// https://github.com/cfrg/draft-irtf-cfrg-hpke/blob/master/test-vectors.json
19+
vectors := readFile(t, "testdata/vectors_v08_779d028.json")
2020
for i, v := range vectors {
2121
t.Run(fmt.Sprintf("v%v", i), v.verify)
2222
}

src/circl/oprf/client.go

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package oprf
33
import (
44
"crypto/rand"
55
"errors"
6+
7+
"circl/group"
68
)
79

810
// Client is a representation of a OPRF client during protocol execution.
@@ -13,9 +15,22 @@ type Client struct {
1315

1416
// ClientRequest is a structure to encapsulate the output of a Request call.
1517
type ClientRequest struct {
16-
inputs [][]byte
17-
blinds []Blind
18-
BlindedElements []Blinded
18+
inputs [][]byte
19+
blinds []Blind
20+
elements []group.Element
21+
}
22+
23+
// BlindedElements returns the serialized blinded elements produced for the client request.
24+
func (r ClientRequest) BlindedElements() [][]byte {
25+
var err error
26+
serializedBlinds := make([][]byte, len(r.elements))
27+
for i := range r.elements {
28+
serializedBlinds[i], err = r.elements[i].MarshalBinaryCompress()
29+
if err != nil {
30+
return nil
31+
}
32+
}
33+
return serializedBlinds
1934
}
2035

2136
// NewClient creates a client in base mode.
@@ -58,14 +73,11 @@ func (c *Client) Request(inputs [][]byte) (*ClientRequest, error) {
5873
}
5974

6075
func (c *Client) blind(inputs [][]byte, blinds []Blind) (*ClientRequest, error) {
61-
var err error
62-
blindedElements := make([]Blinded, len(inputs))
76+
blindedElements := make([]group.Element, len(inputs))
6377
for i := range inputs {
6478
p := c.suite.Group.HashToElement(inputs[i], c.suite.getDST(hashToGroupDST))
65-
blindedElements[i], err = c.scalarMult(p, blinds[i])
66-
if err != nil {
67-
return nil, err
68-
}
79+
blindedElements[i] = c.suite.Group.NewElement()
80+
blindedElements[i].Mul(p, blinds[i])
6981
}
7082
return &ClientRequest{inputs, blinds, blindedElements}, nil
7183
}
@@ -75,17 +87,27 @@ func (c *Client) blind(inputs [][]byte, blinds []Blind) (*ClientRequest, error)
7587
// to verify the proof in verifiable mode.
7688
func (c *Client) Finalize(r *ClientRequest, e *Evaluation) ([][]byte, error) {
7789
l := len(r.blinds)
78-
if len(r.BlindedElements) != l || len(e.Elements) != l {
90+
if len(r.elements) != l || len(e.Elements) != l {
7991
return nil, errors.New("mismatch number of elements")
8092
}
8193

94+
var err error
95+
evals := make([]group.Element, len(e.Elements))
96+
for i := range e.Elements {
97+
evals[i] = c.suite.Group.NewElement()
98+
err = evals[i].UnmarshalBinary(e.Elements[i])
99+
if err != nil {
100+
return nil, err
101+
}
102+
}
103+
82104
if c.Mode == VerifiableMode {
83-
if !c.verifyProof(r.BlindedElements, e) {
105+
if !c.verifyProof(r.elements, evals, *e.Proof) {
84106
return nil, errors.New("invalid proof")
85107
}
86108
}
87109

88-
unblindedElements, err := c.unblind(e.Elements, r.blinds)
110+
unblindedElements, err := c.unblind(evals, r.blinds)
89111
if err != nil {
90112
return nil, err
91113
}
@@ -96,37 +118,37 @@ func (c *Client) Finalize(r *ClientRequest, e *Evaluation) ([][]byte, error) {
96118
return outputs, nil
97119
}
98120

99-
func (c *Client) verifyProof(blinds []Blinded, e *Evaluation) bool {
121+
func (c *Client) verifyProof(blinds []group.Element, elements []group.Element, proof Proof) bool {
100122
pkSm, err := c.pkS.Serialize()
101123
if err != nil {
102124
return false
103125
}
104-
a0, a1, err := c.computeComposites(pkSm, blinds, e.Elements, nil)
126+
127+
M, Z, err := c.computeComposites(nil, c.pkS.e, blinds, elements)
105128
if err != nil {
106129
return false
107130
}
108-
M := c.suite.Group.NewElement()
109-
err = M.UnmarshalBinary(a0)
131+
132+
a0, err := M.MarshalBinaryCompress()
110133
if err != nil {
111134
return false
112135
}
113-
Z := c.suite.Group.NewElement()
114-
err = Z.UnmarshalBinary(a1)
136+
a1, err := Z.MarshalBinaryCompress()
115137
if err != nil {
116138
return false
117139
}
118140

119141
sG := c.suite.Group.NewElement()
120142
ss := c.suite.Group.NewScalar()
121-
err = ss.UnmarshalBinary(e.Proof.S)
143+
err = ss.UnmarshalBinary(proof.S)
122144
if err != nil {
123145
return false
124146
}
125147
sG.MulGen(ss)
126148

127149
cP := c.suite.Group.NewElement()
128150
cc := c.suite.Group.NewScalar()
129-
err = cc.UnmarshalBinary(e.Proof.C)
151+
err = cc.UnmarshalBinary(proof.C)
130152
if err != nil {
131153
return false
132154
}
@@ -151,17 +173,13 @@ func (c *Client) verifyProof(blinds []Blinded, e *Evaluation) bool {
151173
return gotC.IsEqual(cc)
152174
}
153175

154-
func (c *Client) unblind(e []SerializedElement, blinds []Blind) ([][]byte, error) {
176+
func (c *Client) unblind(e []group.Element, blinds []Blind) ([][]byte, error) {
177+
var err error
155178
unblindedElements := make([][]byte, len(e))
156-
p := c.Group.NewElement()
157179
invBlind := c.Group.NewScalar()
158180
for i := range e {
159-
err := p.UnmarshalBinary(e[i])
160-
if err != nil {
161-
return nil, err
162-
}
163181
invBlind.Inv(blinds[i])
164-
unblindedElements[i], err = c.scalarMult(p, invBlind)
182+
unblindedElements[i], err = c.scalarMult(e[i], invBlind)
165183
if err != nil {
166184
return nil, err
167185
}

src/circl/oprf/oprf.go

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -151,18 +151,22 @@ func mustWrite(h io.Writer, bytes []byte) {
151151
}
152152

153153
func (s *suite) computeComposites(
154-
pkSm []byte,
155-
b []Blinded,
156-
eval []SerializedElement,
157-
skS group.Scalar,
158-
) ([]byte, []byte, error) {
159-
lenBuf := []byte{0, 0}
154+
k group.Scalar,
155+
B group.Element,
156+
Cs []group.Element,
157+
Ds []group.Element,
158+
) (group.Element, group.Element, error) {
159+
Bm, err := B.MarshalBinaryCompress()
160+
if err != nil {
161+
return nil, nil, err
162+
}
160163

164+
lenBuf := []byte{0, 0}
161165
H := s.New()
162166

163-
binary.BigEndian.PutUint16(lenBuf, uint16(len(pkSm)))
167+
binary.BigEndian.PutUint16(lenBuf, uint16(len(Bm)))
164168
mustWrite(H, lenBuf)
165-
mustWrite(H, pkSm)
169+
mustWrite(H, Bm)
166170

167171
dst := s.getDST(seedDST)
168172
binary.BigEndian.PutUint16(lenBuf, uint16(len(dst)))
@@ -173,60 +177,53 @@ func (s *suite) computeComposites(
173177

174178
M := s.Group.Identity()
175179
Z := s.Group.Identity()
176-
Mi := s.Group.NewElement()
177-
Zi := s.Group.NewElement()
178180
h2sDST := s.getDST(hashToScalarDST)
179-
for i := range b {
181+
for i := range Cs {
180182
h2Input := []byte{}
181183

184+
Ci, err := Cs[i].MarshalBinaryCompress()
185+
if err != nil {
186+
return nil, nil, err
187+
}
188+
189+
Di, err := Ds[i].MarshalBinaryCompress()
190+
if err != nil {
191+
return nil, nil, err
192+
}
193+
182194
binary.BigEndian.PutUint16(lenBuf, uint16(len(seed)))
183195
h2Input = append(append(h2Input, lenBuf...), seed...)
184196

185197
binary.BigEndian.PutUint16(lenBuf, uint16(i))
186198
h2Input = append(h2Input, lenBuf...)
187199

188-
binary.BigEndian.PutUint16(lenBuf, uint16(len(b[i])))
189-
h2Input = append(append(h2Input, lenBuf...), b[i]...)
200+
binary.BigEndian.PutUint16(lenBuf, uint16(len(Ci)))
201+
h2Input = append(append(h2Input, lenBuf...), Ci...)
190202

191-
binary.BigEndian.PutUint16(lenBuf, uint16(len(eval[i])))
192-
h2Input = append(append(h2Input, lenBuf...), eval[i]...)
203+
binary.BigEndian.PutUint16(lenBuf, uint16(len(Di)))
204+
h2Input = append(append(h2Input, lenBuf...), Di...)
193205

194206
dst := s.getDST(compositeDST)
195207
binary.BigEndian.PutUint16(lenBuf, uint16(len(dst)))
196208
h2Input = append(append(h2Input, lenBuf...), dst...)
197209

198210
di := s.Group.HashToScalar(h2Input, h2sDST)
199-
err := Mi.UnmarshalBinary(b[i])
200-
if err != nil {
201-
return nil, nil, err
202-
}
203-
Mi.Mul(Mi, di)
211+
Mi := s.Group.NewElement()
212+
Mi.Mul(Cs[i], di)
204213
M.Add(M, Mi)
205214

206-
if skS == nil {
207-
err = Zi.UnmarshalBinary(eval[i])
208-
if err != nil {
209-
return nil, nil, err
210-
}
211-
Zi.Mul(Zi, di)
215+
if k == nil {
216+
Zi := s.Group.NewElement()
217+
Zi.Mul(Ds[i], di)
212218
Z.Add(Z, Zi)
213219
}
214220
}
215221

216-
if skS != nil {
217-
Z.Mul(M, skS)
218-
}
219-
220-
serM, err := M.MarshalBinaryCompress()
221-
if err != nil {
222-
return nil, nil, err
223-
}
224-
serZ, err := Z.MarshalBinaryCompress()
225-
if err != nil {
226-
return nil, nil, err
222+
if k != nil {
223+
Z.Mul(M, k)
227224
}
228225

229-
return serM, serZ, nil
226+
return M, Z, nil
230227
}
231228

232229
func (s *suite) doChallenge(a [5][]byte) group.Scalar {

src/circl/oprf/oprf_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func testAPI(t *testing.T, suite oprf.SuiteID, mode oprf.Mode) {
9393
t.Fatal("invalid blinding of client: " + err.Error())
9494
}
9595

96-
eval, err := server.Evaluate(cr.BlindedElements)
96+
eval, err := server.Evaluate(cr.BlindedElements())
9797
if err != nil {
9898
t.Fatal("invalid evaluation of server: " + err.Error())
9999
}

src/circl/oprf/server.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func newServer(id SuiteID, m Mode, skS *PrivateKey) (*Server, error) {
4040
return &Server{*suite, *skS}, nil
4141
}
4242

43+
// GetPublicKey returns the public key corresponding to the server.
4344
func (s *Server) GetPublicKey() *PublicKey { return s.privateKey.Public() }
4445

4546
// Evaluate evaluates a set of blinded inputs from the client.
@@ -57,29 +58,36 @@ func (s *Server) evaluateWithProofScalar(blindedElements []Blinded, proofScalar
5758
}
5859

5960
var err error
60-
eval := make([]SerializedElement, l)
61-
p := s.suite.NewElement()
61+
input := make([]group.Element, l)
62+
eval := make([]group.Element, l)
63+
out := make([]SerializedElement, l)
6264

6365
for i := range blindedElements {
64-
err = p.UnmarshalBinary(blindedElements[i])
66+
input[i] = s.suite.NewElement()
67+
err = input[i].UnmarshalBinary(blindedElements[i])
6568
if err != nil {
6669
return nil, err
6770
}
68-
eval[i], err = s.scalarMult(p, s.privateKey.k)
71+
72+
eval[i] = s.Group.NewElement()
73+
eval[i].Mul(input[i], s.privateKey.k)
74+
75+
e, err := eval[i].MarshalBinaryCompress()
6976
if err != nil {
7077
return nil, err
7178
}
79+
out[i] = e
7280
}
7381

7482
var proof *Proof
7583
if s.Mode == VerifiableMode {
76-
proof, err = s.generateProofWithRandomScalar(blindedElements, eval, proofScalar)
84+
proof, err = s.generateProofWithRandomScalar(s.privateKey.k, s.Generator(), s.privateKey.Public().e, input, eval, proofScalar)
7785
if err != nil {
7886
return nil, err
7987
}
8088
}
8189

82-
return &Evaluation{eval, proof}, nil
90+
return &Evaluation{out, proof}, nil
8391
}
8492

8593
// FullEvaluate performs a full OPRF protocol at server-side.
@@ -104,26 +112,28 @@ func (s *Server) VerifyFinalize(input, expectedOutput []byte) bool {
104112
return subtle.ConstantTimeCompare(gotOutput, expectedOutput) == 1
105113
}
106114

107-
func (s *Server) generateProofWithRandomScalar(b []Blinded, eval []SerializedElement, rr group.Scalar) (*Proof, error) {
108-
pkS := s.privateKey.Public()
109-
pkSm, err := pkS.Serialize()
115+
func (s *Server) generateProofWithRandomScalar(k group.Scalar, A, B group.Element, Cs []group.Element, Ds []group.Element, rr group.Scalar) (*Proof, error) {
116+
M, Z, err := s.computeComposites(k, B, Cs, Ds)
110117
if err != nil {
111118
return nil, err
112119
}
113120

114-
a0, a1, err := s.computeComposites(pkSm, b, eval, s.privateKey.k)
121+
Bm, err := B.MarshalBinaryCompress()
115122
if err != nil {
116123
return nil, err
117124
}
118125

119-
M := s.Group.NewElement()
120-
err = M.UnmarshalBinary(a0)
126+
a0, err := M.MarshalBinaryCompress()
127+
if err != nil {
128+
return nil, err
129+
}
130+
a1, err := Z.MarshalBinaryCompress()
121131
if err != nil {
122132
return nil, err
123133
}
124134

125135
a2e := s.Group.NewElement()
126-
a2e.MulGen(rr)
136+
a2e.Mul(A, rr)
127137
a2, err := a2e.MarshalBinaryCompress()
128138
if err != nil {
129139
return nil, err
@@ -136,7 +146,7 @@ func (s *Server) generateProofWithRandomScalar(b []Blinded, eval []SerializedEle
136146
return nil, err
137147
}
138148

139-
cc := s.doChallenge([5][]byte{pkSm, a0, a1, a2, a3})
149+
cc := s.doChallenge([5][]byte{Bm, a0, a1, a2, a3})
140150
ss := s.suite.Group.NewScalar()
141151
ss.Mul(cc, s.privateKey.k)
142152
ss.Sub(rr, ss)

0 commit comments

Comments
 (0)