github.com/cloudflare/circl@v1.5.0/oprf/keys.go (about) 1 package oprf 2 3 import ( 4 "encoding/binary" 5 "io" 6 7 "github.com/cloudflare/circl/group" 8 ) 9 10 type PrivateKey struct { 11 p params 12 k group.Scalar 13 pub *PublicKey 14 } 15 16 type PublicKey struct { 17 p params 18 e group.Element 19 } 20 21 func (k *PrivateKey) MarshalBinary() ([]byte, error) { return k.k.MarshalBinary() } 22 func (k *PublicKey) MarshalBinary() ([]byte, error) { return k.e.MarshalBinaryCompress() } 23 24 func (k *PrivateKey) UnmarshalBinary(s Suite, data []byte) error { 25 p, ok := s.(params) 26 if !ok { 27 return ErrInvalidSuite 28 } 29 k.p = p 30 k.k = k.p.group.NewScalar() 31 32 return k.k.UnmarshalBinary(data) 33 } 34 35 func (k *PublicKey) UnmarshalBinary(s Suite, data []byte) error { 36 p, ok := s.(params) 37 if !ok { 38 return ErrInvalidSuite 39 } 40 k.p = p 41 k.e = k.p.group.NewElement() 42 43 return k.e.UnmarshalBinary(data) 44 } 45 46 func (k *PrivateKey) Public() *PublicKey { 47 if k.pub == nil { 48 k.pub = &PublicKey{k.p, k.p.group.NewElement().MulGen(k.k)} 49 } 50 51 return k.pub 52 } 53 54 // GenerateKey generates a private key compatible with the suite. 55 func GenerateKey(s Suite, rnd io.Reader) (*PrivateKey, error) { 56 if rnd == nil { 57 return nil, io.ErrNoProgress 58 } 59 60 p, ok := s.(params) 61 if !ok { 62 return nil, ErrInvalidSuite 63 } 64 privateKey := p.group.RandomScalar(rnd) 65 66 return &PrivateKey{p, privateKey, nil}, nil 67 } 68 69 // DeriveKey generates a private key from a 32-byte seed and an optional info string. 70 func DeriveKey(s Suite, mode Mode, seed, info []byte) (*PrivateKey, error) { 71 const maxTries = 255 72 p, ok := s.(params) 73 if !ok { 74 return nil, ErrInvalidSuite 75 } 76 if !isValidMode(mode) { 77 return nil, ErrInvalidMode 78 } 79 if len(seed) != 32 { 80 return nil, ErrInvalidSeed 81 } 82 p.m = mode 83 84 lenInfo := []byte{0, 0} 85 binary.BigEndian.PutUint16(lenInfo, uint16(len(info))) 86 deriveInput := append(append(append([]byte{}, seed...), lenInfo...), info...) 87 88 dst := p.getDST(deriveKeyPairDST) 89 zero := p.group.NewScalar() 90 privateKey := p.group.NewScalar() 91 for counter := byte(0); privateKey.IsEqual(zero); counter++ { 92 if counter > maxTries { 93 return nil, ErrDeriveKeyPairError 94 } 95 privateKey = p.group.HashToScalar(append(deriveInput, counter), dst) 96 } 97 98 return &PrivateKey{p, privateKey, nil}, nil 99 }