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
14package curve25519
15
16import "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.
23func 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.
38func 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
47const (
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.
55var Basepoint []byte
56
57var basePoint = [32]byte{9}
58
59func 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.
70func 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
77func 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}