key.go raw

   1  package x25519
   2  
   3  import (
   4  	"crypto/subtle"
   5  
   6  	fp "github.com/cloudflare/circl/math/fp25519"
   7  )
   8  
   9  // Size is the length in bytes of a X25519 key.
  10  const Size = 32
  11  
  12  // Key represents a X25519 key.
  13  type Key [Size]byte
  14  
  15  func (k *Key) clamp(in *Key) *Key {
  16  	*k = *in
  17  	k[0] &= 248
  18  	k[31] = (k[31] & 127) | 64
  19  	return k
  20  }
  21  
  22  // isValidPubKey verifies if the public key is not a low-order point.
  23  func (k *Key) isValidPubKey() bool {
  24  	fp.Modp((*fp.Elt)(k))
  25  	var isLowOrder int
  26  	for _, P := range lowOrderPoints {
  27  		isLowOrder |= subtle.ConstantTimeCompare(P[:], k[:])
  28  	}
  29  	return isLowOrder == 0
  30  }
  31  
  32  // KeyGen obtains a public key given a secret key.
  33  func KeyGen(public, secret *Key) {
  34  	ladderJoye(public.clamp(secret))
  35  }
  36  
  37  // Shared calculates Alice's shared key from Alice's secret key and Bob's
  38  // public key returning true on success. A failure case happens when the public
  39  // key is a low-order point, thus the shared key is all-zeros and the function
  40  // returns false.
  41  func Shared(shared, secret, public *Key) bool {
  42  	validPk := *public
  43  	validPk[31] &= (1 << (255 % 8)) - 1
  44  	ok := validPk.isValidPubKey()
  45  	ladderMontgomery(shared.clamp(secret), &validPk)
  46  	return ok
  47  }
  48