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 }