1 package oprf
2
3 import (
4 "crypto/rand"
5 "crypto/subtle"
6
7 "github.com/cloudflare/circl/group"
8 "github.com/cloudflare/circl/zk/dleq"
9 )
10
11 type server struct {
12 params
13 privateKey *PrivateKey
14 }
15
16 type Server struct{ server }
17
18 type VerifiableServer struct{ server }
19
20 type PartialObliviousServer struct{ server }
21
22 func (s server) PublicKey() *PublicKey { return s.privateKey.Public() }
23
24 func (s server) evaluate(elements []Blinded, secret Blind) []Evaluated {
25 evaluations := make([]Evaluated, len(elements))
26 for i := range elements {
27 evaluations[i] = s.params.group.NewElement().Mul(elements[i], secret)
28 }
29
30 return evaluations
31 }
32
33 func (s Server) Evaluate(req *EvaluationRequest) (*Evaluation, error) {
34 evaluations := s.server.evaluate(req.Elements, s.privateKey.k)
35
36 return &Evaluation{evaluations, nil}, nil
37 }
38
39 func (s VerifiableServer) Evaluate(req *EvaluationRequest) (*Evaluation, error) {
40 evaluations := s.server.evaluate(req.Elements, s.privateKey.k)
41
42 proof, err := dleq.Prover{Params: s.getDLEQParams()}.ProveBatch(
43 s.privateKey.k,
44 s.params.group.Generator(),
45 s.PublicKey().e,
46 req.Elements,
47 evaluations,
48 rand.Reader,
49 )
50 if err != nil {
51 return nil, err
52 }
53
54 return &Evaluation{evaluations, proof}, nil
55 }
56
57 func (s PartialObliviousServer) Evaluate(req *EvaluationRequest, info []byte) (*Evaluation, error) {
58 keyProof, evalSecret, err := s.secretFromInfo(info)
59 if err != nil {
60 return nil, err
61 }
62
63 evaluations := s.server.evaluate(req.Elements, evalSecret)
64
65 proof, err := dleq.Prover{Params: s.getDLEQParams()}.ProveBatch(
66 keyProof,
67 s.params.group.Generator(),
68 s.params.group.NewElement().MulGen(keyProof),
69 evaluations,
70 req.Elements,
71 rand.Reader,
72 )
73 if err != nil {
74 return nil, err
75 }
76
77 return &Evaluation{evaluations, proof}, nil
78 }
79
80 func (s server) secretFromInfo(info []byte) (t, tInv group.Scalar, err error) {
81 m, err := s.params.scalarFromInfo(info)
82 if err != nil {
83 return nil, nil, err
84 }
85 t = s.params.group.NewScalar().Add(m, s.privateKey.k)
86
87 if zero := s.params.group.NewScalar(); t.IsEqual(zero) {
88 return nil, nil, ErrInverseZero
89 }
90 tInv = s.params.group.NewScalar().Inv(t)
91
92 return t, tInv, nil
93 }
94
95 func (s server) fullEvaluate(input, info []byte) ([]byte, error) {
96 evalSecret := s.privateKey.k
97 if s.params.m == PartialObliviousMode {
98 var err error
99 _, evalSecret, err = s.secretFromInfo(info)
100 if err != nil {
101 return nil, err
102 }
103 }
104
105 element := s.params.group.HashToElement(input, s.params.getDST(hashToGroupDST))
106 evaluation := s.params.group.NewElement().Mul(element, evalSecret)
107 serEval, err := evaluation.MarshalBinaryCompress()
108 if err != nil {
109 return nil, err
110 }
111
112 return s.finalizeHash(s.params.hash.New(), input, info, serEval), nil
113 }
114
115 func (s Server) FullEvaluate(input []byte) (output []byte, err error) {
116 return s.fullEvaluate(input, nil)
117 }
118
119 func (s VerifiableServer) FullEvaluate(input []byte) (output []byte, err error) {
120 return s.fullEvaluate(input, nil)
121 }
122
123 func (s PartialObliviousServer) FullEvaluate(input, info []byte) (output []byte, err error) {
124 return s.fullEvaluate(input, info)
125 }
126
127 func (s server) verifyFinalize(input, info, expectedOutput []byte) bool {
128 gotOutput, err := s.fullEvaluate(input, info)
129 if err != nil {
130 return false
131 }
132
133 return subtle.ConstantTimeCompare(gotOutput, expectedOutput) == 1
134 }
135
136 func (s Server) VerifyFinalize(input, expectedOutput []byte) bool {
137 return s.verifyFinalize(input, nil, expectedOutput)
138 }
139
140 func (s VerifiableServer) VerifyFinalize(input, expectedOutput []byte) bool {
141 return s.verifyFinalize(input, nil, expectedOutput)
142 }
143
144 func (s PartialObliviousServer) VerifyFinalize(input, info, expectedOutput []byte) bool {
145 return s.verifyFinalize(input, info, expectedOutput)
146 }
147
View as plain text