github.com/cloudflare/circl@v1.5.0/oprf/client.go (about) 1 package oprf 2 3 import ( 4 "crypto/rand" 5 6 "github.com/cloudflare/circl/group" 7 "github.com/cloudflare/circl/zk/dleq" 8 ) 9 10 type client struct{ params } 11 12 type Client struct { 13 client 14 } 15 16 type VerifiableClient struct { 17 client 18 pkS *PublicKey 19 } 20 21 type PartialObliviousClient struct { 22 client 23 pkS *PublicKey 24 } 25 26 func (c client) Blind(inputs [][]byte) (*FinalizeData, *EvaluationRequest, error) { 27 if len(inputs) == 0 { 28 return nil, nil, ErrInvalidInput 29 } 30 31 blinds := make([]Blind, len(inputs)) 32 for i := range inputs { 33 blinds[i] = c.params.group.RandomScalar(rand.Reader) 34 } 35 36 return c.blind(inputs, blinds) 37 } 38 39 func (c client) DeterministicBlind(inputs [][]byte, blinds []Blind) (*FinalizeData, *EvaluationRequest, error) { 40 if len(inputs) == 0 { 41 return nil, nil, ErrInvalidInput 42 } 43 if len(inputs) != len(blinds) { 44 return nil, nil, ErrInvalidInput 45 } 46 47 return c.blind(inputs, blinds) 48 } 49 50 func (c client) blind(inputs [][]byte, blinds []Blind) (*FinalizeData, *EvaluationRequest, error) { 51 blindedElements := make([]Blinded, len(inputs)) 52 dst := c.params.getDST(hashToGroupDST) 53 for i := range inputs { 54 point := c.params.group.HashToElement(inputs[i], dst) 55 if point.IsIdentity() { 56 return nil, nil, ErrInvalidInput 57 } 58 blindedElements[i] = c.params.group.NewElement().Mul(point, blinds[i]) 59 } 60 61 evalReq := &EvaluationRequest{blindedElements} 62 finData := &FinalizeData{inputs, blinds, evalReq} 63 64 return finData, evalReq, nil 65 } 66 67 func (c client) unblind(serUnblindeds [][]byte, blindeds []group.Element, blind []Blind) (err error) { 68 invBlind := c.params.group.NewScalar() 69 U := c.params.group.NewElement() 70 71 for i := range blindeds { 72 invBlind.Inv(blind[i]) 73 U.Mul(blindeds[i], invBlind) 74 serUnblindeds[i], err = U.MarshalBinaryCompress() 75 if err != nil { 76 return err 77 } 78 } 79 80 return nil 81 } 82 83 func (c client) validate(f *FinalizeData, e *Evaluation) (err error) { 84 if l := len(f.blinds); len(f.evalReq.Elements) != l || len(e.Elements) != l { 85 err = ErrInvalidInput 86 } 87 88 return 89 } 90 91 func (c client) finalize(f *FinalizeData, e *Evaluation, info []byte) ([][]byte, error) { 92 unblindedElements := make([][]byte, len(f.blinds)) 93 err := c.unblind(unblindedElements, e.Elements, f.blinds) 94 if err != nil { 95 return nil, err 96 } 97 98 h := c.params.hash.New() 99 outputs := make([][]byte, len(f.inputs)) 100 for i := range f.inputs { 101 outputs[i] = c.params.finalizeHash(h, f.inputs[i], info, unblindedElements[i]) 102 } 103 104 return outputs, nil 105 } 106 107 func (c Client) Finalize(f *FinalizeData, e *Evaluation) (outputs [][]byte, err error) { 108 if err = c.validate(f, e); err != nil { 109 return nil, err 110 } 111 112 return c.client.finalize(f, e, nil) 113 } 114 115 func (c VerifiableClient) Finalize(f *FinalizeData, e *Evaluation) (outputs [][]byte, err error) { 116 if err := c.validate(f, e); err != nil { 117 return nil, err 118 } 119 120 if !(dleq.Verifier{Params: c.getDLEQParams()}).VerifyBatch( 121 c.params.group.Generator(), 122 c.pkS.e, 123 f.evalReq.Elements, 124 e.Elements, 125 e.Proof, 126 ) { 127 return nil, ErrInvalidProof 128 } 129 130 return c.client.finalize(f, e, nil) 131 } 132 133 func (c PartialObliviousClient) Finalize(f *FinalizeData, e *Evaluation, info []byte) (outputs [][]byte, err error) { 134 if err = c.validate(f, e); err != nil { 135 return nil, err 136 } 137 138 tweakedKey, err := c.pointFromInfo(info) 139 if err != nil { 140 return nil, err 141 } 142 143 if !(dleq.Verifier{Params: c.getDLEQParams()}).VerifyBatch( 144 c.params.group.Generator(), 145 tweakedKey, 146 e.Elements, 147 f.evalReq.Elements, 148 e.Proof, 149 ) { 150 return nil, ErrInvalidProof 151 } 152 153 return c.client.finalize(f, e, info) 154 } 155 156 func (c PartialObliviousClient) pointFromInfo(info []byte) (group.Element, error) { 157 m, err := c.params.scalarFromInfo(info) 158 if err != nil { 159 return nil, err 160 } 161 162 T := c.params.group.NewElement().MulGen(m) 163 tweakedKey := c.params.group.NewElement().Add(T, c.pkS.e) 164 if tweakedKey.IsIdentity() { 165 return nil, ErrInvalidInfo 166 } 167 168 return tweakedKey, nil 169 }