curve25519.go raw

   1  // Copyright 2019 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Package curve25519 provides an implementation of the X25519 function, which
   6  // performs scalar multiplication on the elliptic curve known as Curve25519
   7  // according to [RFC 7748].
   8  //
   9  // The curve25519 package is a wrapper for the X25519 implementation in the
  10  // crypto/ecdh package. It is [frozen] and is not accepting new features.
  11  //
  12  // [RFC 7748]: https://datatracker.ietf.org/doc/html/rfc7748
  13  // [frozen]: https://go.dev/wiki/Frozen
  14  package curve25519
  15  
  16  import "crypto/ecdh"
  17  
  18  // ScalarMult sets dst to the product scalar * point.
  19  //
  20  // Deprecated: when provided a low-order point, ScalarMult will set dst to all
  21  // zeroes, irrespective of the scalar. Instead, use the X25519 function, which
  22  // will return an error.
  23  func ScalarMult(dst, scalar, point *[32]byte) {
  24  	if _, err := x25519(dst, scalar[:], point[:]); err != nil {
  25  		// The only error condition for x25519 when the inputs are 32 bytes long
  26  		// is if the output would have been the all-zero value.
  27  		for i := range dst {
  28  			dst[i] = 0
  29  		}
  30  	}
  31  }
  32  
  33  // ScalarBaseMult sets dst to the product scalar * base where base is the
  34  // standard generator.
  35  //
  36  // It is recommended to use the X25519 function with Basepoint instead, as
  37  // copying into fixed size arrays can lead to unexpected bugs.
  38  func ScalarBaseMult(dst, scalar *[32]byte) {
  39  	curve := ecdh.X25519()
  40  	priv, err := curve.NewPrivateKey(scalar[:])
  41  	if err != nil {
  42  		panic("curve25519: " + err.Error())
  43  	}
  44  	copy(dst[:], priv.PublicKey().Bytes())
  45  }
  46  
  47  const (
  48  	// ScalarSize is the size of the scalar input to X25519.
  49  	ScalarSize = 32
  50  	// PointSize is the size of the point input to X25519.
  51  	PointSize = 32
  52  )
  53  
  54  // Basepoint is the canonical Curve25519 generator.
  55  var Basepoint []byte
  56  
  57  var basePoint = [32]byte{9}
  58  
  59  func init() { Basepoint = basePoint[:] }
  60  
  61  // X25519 returns the result of the scalar multiplication (scalar * point),
  62  // according to RFC 7748, Section 5. scalar, point and the return value are
  63  // slices of 32 bytes.
  64  //
  65  // scalar can be generated at random, for example with crypto/rand. point should
  66  // be either Basepoint or the output of another X25519 call.
  67  //
  68  // If point is Basepoint (but not if it's a different slice with the same
  69  // contents) a precomputed implementation might be used for performance.
  70  func X25519(scalar, point []byte) ([]byte, error) {
  71  	// Outline the body of function, to let the allocation be inlined in the
  72  	// caller, and possibly avoid escaping to the heap.
  73  	var dst [32]byte
  74  	return x25519(&dst, scalar, point)
  75  }
  76  
  77  func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
  78  	curve := ecdh.X25519()
  79  	pub, err := curve.NewPublicKey(point)
  80  	if err != nil {
  81  		return nil, err
  82  	}
  83  	priv, err := curve.NewPrivateKey(scalar)
  84  	if err != nil {
  85  		return nil, err
  86  	}
  87  	out, err := priv.ECDH(pub)
  88  	if err != nil {
  89  		return nil, err
  90  	}
  91  	copy(dst[:], out)
  92  	return dst[:], nil
  93  }
  94