1
2
3
4
5
6
7 package curve25519
8
9 import (
10 "crypto/subtle"
11 "errors"
12 "strconv"
13
14 "golang.org/x/crypto/curve25519/internal/field"
15 )
16
17 func scalarMult(dst, scalar, point *[32]byte) {
18 var e [32]byte
19
20 copy(e[:], scalar[:])
21 e[0] &= 248
22 e[31] &= 127
23 e[31] |= 64
24
25 var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
26 x1.SetBytes(point[:])
27 x2.One()
28 x3.Set(&x1)
29 z3.One()
30
31 swap := 0
32 for pos := 254; pos >= 0; pos-- {
33 b := e[pos/8] >> uint(pos&7)
34 b &= 1
35 swap ^= int(b)
36 x2.Swap(&x3, swap)
37 z2.Swap(&z3, swap)
38 swap = int(b)
39
40 tmp0.Subtract(&x3, &z3)
41 tmp1.Subtract(&x2, &z2)
42 x2.Add(&x2, &z2)
43 z2.Add(&x3, &z3)
44 z3.Multiply(&tmp0, &x2)
45 z2.Multiply(&z2, &tmp1)
46 tmp0.Square(&tmp1)
47 tmp1.Square(&x2)
48 x3.Add(&z3, &z2)
49 z2.Subtract(&z3, &z2)
50 x2.Multiply(&tmp1, &tmp0)
51 tmp1.Subtract(&tmp1, &tmp0)
52 z2.Square(&z2)
53
54 z3.Mult32(&tmp1, 121666)
55 x3.Square(&x3)
56 tmp0.Add(&tmp0, &z3)
57 z3.Multiply(&x1, &z2)
58 z2.Multiply(&tmp1, &tmp0)
59 }
60
61 x2.Swap(&x3, swap)
62 z2.Swap(&z3, swap)
63
64 z2.Invert(&z2)
65 x2.Multiply(&x2, &z2)
66 copy(dst[:], x2.Bytes())
67 }
68
69 func scalarBaseMult(dst, scalar *[32]byte) {
70 checkBasepoint()
71 scalarMult(dst, scalar, &basePoint)
72 }
73
74 func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
75 var in [32]byte
76 if l := len(scalar); l != 32 {
77 return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
78 }
79 if l := len(point); l != 32 {
80 return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
81 }
82 copy(in[:], scalar)
83 if &point[0] == &Basepoint[0] {
84 scalarBaseMult(dst, &in)
85 } else {
86 var base, zero [32]byte
87 copy(base[:], point)
88 scalarMult(dst, &in, &base)
89 if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
90 return nil, errors.New("bad input point: low order point")
91 }
92 }
93 return dst[:], nil
94 }
95
96 func checkBasepoint() {
97 if subtle.ConstantTimeCompare(Basepoint, []byte{
98 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 }) != 1 {
103 panic("curve25519: global Basepoint value was modified")
104 }
105 }
106
View as plain text