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  }