1
2
3
4
5 package ecdh
6
7 import (
8 "crypto/internal/edwards25519/field"
9 "crypto/internal/randutil"
10 "errors"
11 "io"
12 )
13
14 var (
15 x25519PublicKeySize = 32
16 x25519PrivateKeySize = 32
17 x25519SharedSecretSize = 32
18 )
19
20
21
22
23
24
25 func X25519() Curve { return x25519 }
26
27 var x25519 = &x25519Curve{}
28
29 type x25519Curve struct{}
30
31 func (c *x25519Curve) String() string {
32 return "X25519"
33 }
34
35 func (c *x25519Curve) GenerateKey(rand io.Reader) (*PrivateKey, error) {
36 key := make([]byte, x25519PrivateKeySize)
37 randutil.MaybeReadByte(rand)
38 if _, err := io.ReadFull(rand, key); err != nil {
39 return nil, err
40 }
41 return c.NewPrivateKey(key)
42 }
43
44 func (c *x25519Curve) NewPrivateKey(key []byte) (*PrivateKey, error) {
45 if len(key) != x25519PrivateKeySize {
46 return nil, errors.New("crypto/ecdh: invalid private key size")
47 }
48 return &PrivateKey{
49 curve: c,
50 privateKey: append([]byte{}, key...),
51 }, nil
52 }
53
54 func (c *x25519Curve) privateKeyToPublicKey(key *PrivateKey) *PublicKey {
55 if key.curve != c {
56 panic("crypto/ecdh: internal error: converting the wrong key type")
57 }
58 k := &PublicKey{
59 curve: key.curve,
60 publicKey: make([]byte, x25519PublicKeySize),
61 }
62 x25519Basepoint := [32]byte{9}
63 x25519ScalarMult(k.publicKey, key.privateKey, x25519Basepoint[:])
64 return k
65 }
66
67 func (c *x25519Curve) NewPublicKey(key []byte) (*PublicKey, error) {
68 if len(key) != x25519PublicKeySize {
69 return nil, errors.New("crypto/ecdh: invalid public key")
70 }
71 return &PublicKey{
72 curve: c,
73 publicKey: append([]byte{}, key...),
74 }, nil
75 }
76
77 func (c *x25519Curve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) {
78 out := make([]byte, x25519SharedSecretSize)
79 x25519ScalarMult(out, local.privateKey, remote.publicKey)
80 if isZero(out) {
81 return nil, errors.New("crypto/ecdh: bad X25519 remote ECDH input: low order point")
82 }
83 return out, nil
84 }
85
86 func x25519ScalarMult(dst, scalar, point []byte) {
87 var e [32]byte
88
89 copy(e[:], scalar[:])
90 e[0] &= 248
91 e[31] &= 127
92 e[31] |= 64
93
94 var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
95 x1.SetBytes(point[:])
96 x2.One()
97 x3.Set(&x1)
98 z3.One()
99
100 swap := 0
101 for pos := 254; pos >= 0; pos-- {
102 b := e[pos/8] >> uint(pos&7)
103 b &= 1
104 swap ^= int(b)
105 x2.Swap(&x3, swap)
106 z2.Swap(&z3, swap)
107 swap = int(b)
108
109 tmp0.Subtract(&x3, &z3)
110 tmp1.Subtract(&x2, &z2)
111 x2.Add(&x2, &z2)
112 z2.Add(&x3, &z3)
113 z3.Multiply(&tmp0, &x2)
114 z2.Multiply(&z2, &tmp1)
115 tmp0.Square(&tmp1)
116 tmp1.Square(&x2)
117 x3.Add(&z3, &z2)
118 z2.Subtract(&z3, &z2)
119 x2.Multiply(&tmp1, &tmp0)
120 tmp1.Subtract(&tmp1, &tmp0)
121 z2.Square(&z2)
122
123 z3.Mult32(&tmp1, 121666)
124 x3.Square(&x3)
125 tmp0.Add(&tmp0, &z3)
126 z3.Multiply(&x1, &z2)
127 z2.Multiply(&tmp1, &tmp0)
128 }
129
130 x2.Swap(&x3, swap)
131 z2.Swap(&z3, swap)
132
133 z2.Invert(&z2)
134 x2.Multiply(&x2, &z2)
135 copy(dst[:], x2.Bytes())
136 }
137
View as plain text