github.com/cloudflare/circl@v1.5.0/dh/x25519/key.go (about)

     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  }