1
2
3
4
5 package edwards25519
6
7 import (
8 "bytes"
9 "encoding/hex"
10 "math/big"
11 mathrand "math/rand"
12 "reflect"
13 "testing"
14 "testing/quick"
15 )
16
17
18
19 func (Scalar) Generate(rand *mathrand.Rand, size int) reflect.Value {
20 s := scZero
21 diceRoll := rand.Intn(100)
22 switch {
23 case diceRoll == 0:
24 case diceRoll == 1:
25 s = scOne
26 case diceRoll == 2:
27 s = scMinusOne
28 case diceRoll < 5:
29
30 rand.Read(s.s[:16])
31 s.s[15] &= (1 << 5) - 1
32 case diceRoll < 10:
33
34 s.s[31] = 1 << 4
35 rand.Read(s.s[:16])
36 s.s[15] &= (1 << 4) - 1
37 default:
38
39
40
41 rand.Read(s.s[:])
42 s.s[31] &= (1 << 4) - 1
43 }
44 return reflect.ValueOf(s)
45 }
46
47
48
49 var quickCheckConfig1024 = &quick.Config{MaxCountScale: 1 << 10}
50
51 func TestScalarGenerate(t *testing.T) {
52 f := func(sc Scalar) bool {
53 return isReduced(&sc)
54 }
55 if err := quick.Check(f, quickCheckConfig1024); err != nil {
56 t.Errorf("generated unreduced scalar: %v", err)
57 }
58 }
59
60 func TestScalarSetCanonicalBytes(t *testing.T) {
61 f1 := func(in [32]byte, sc Scalar) bool {
62
63 in[len(in)-1] &= (1 << 4) - 1
64 if _, err := sc.SetCanonicalBytes(in[:]); err != nil {
65 return false
66 }
67 return bytes.Equal(in[:], sc.Bytes()) && isReduced(&sc)
68 }
69 if err := quick.Check(f1, quickCheckConfig1024); err != nil {
70 t.Errorf("failed bytes->scalar->bytes round-trip: %v", err)
71 }
72
73 f2 := func(sc1, sc2 Scalar) bool {
74 if _, err := sc2.SetCanonicalBytes(sc1.Bytes()); err != nil {
75 return false
76 }
77 return sc1 == sc2
78 }
79 if err := quick.Check(f2, quickCheckConfig1024); err != nil {
80 t.Errorf("failed scalar->bytes->scalar round-trip: %v", err)
81 }
82
83 b := scMinusOne.s
84 b[31] += 1
85 s := scOne
86 if out, err := s.SetCanonicalBytes(b[:]); err == nil {
87 t.Errorf("SetCanonicalBytes worked on a non-canonical value")
88 } else if s != scOne {
89 t.Errorf("SetCanonicalBytes modified its receiver")
90 } else if out != nil {
91 t.Errorf("SetCanonicalBytes did not return nil with an error")
92 }
93 }
94
95 func TestScalarSetUniformBytes(t *testing.T) {
96 mod, _ := new(big.Int).SetString("27742317777372353535851937790883648493", 10)
97 mod.Add(mod, new(big.Int).Lsh(big.NewInt(1), 252))
98 f := func(in [64]byte, sc Scalar) bool {
99 sc.SetUniformBytes(in[:])
100 if !isReduced(&sc) {
101 return false
102 }
103 scBig := bigIntFromLittleEndianBytes(sc.s[:])
104 inBig := bigIntFromLittleEndianBytes(in[:])
105 return inBig.Mod(inBig, mod).Cmp(scBig) == 0
106 }
107 if err := quick.Check(f, quickCheckConfig1024); err != nil {
108 t.Error(err)
109 }
110 }
111
112 func TestScalarSetBytesWithClamping(t *testing.T) {
113
114
115 random := "633d368491364dc9cd4c1bf891b1d59460face1644813240a313e61f2c88216e"
116 s := new(Scalar).SetBytesWithClamping(decodeHex(random))
117 p := new(Point).ScalarBaseMult(s)
118 want := "1d87a9026fd0126a5736fe1628c95dd419172b5b618457e041c9c861b2494a94"
119 if got := hex.EncodeToString(p.Bytes()); got != want {
120 t.Errorf("random: got %q, want %q", got, want)
121 }
122
123 zero := "0000000000000000000000000000000000000000000000000000000000000000"
124 s = new(Scalar).SetBytesWithClamping(decodeHex(zero))
125 p = new(Point).ScalarBaseMult(s)
126 want = "693e47972caf527c7883ad1b39822f026f47db2ab0e1919955b8993aa04411d1"
127 if got := hex.EncodeToString(p.Bytes()); got != want {
128 t.Errorf("zero: got %q, want %q", got, want)
129 }
130
131 one := "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
132 s = new(Scalar).SetBytesWithClamping(decodeHex(one))
133 p = new(Point).ScalarBaseMult(s)
134 want = "12e9a68b73fd5aacdbcaf3e88c46fea6ebedb1aa84eed1842f07f8edab65e3a7"
135 if got := hex.EncodeToString(p.Bytes()); got != want {
136 t.Errorf("one: got %q, want %q", got, want)
137 }
138 }
139
140 func bigIntFromLittleEndianBytes(b []byte) *big.Int {
141 bb := make([]byte, len(b))
142 for i := range b {
143 bb[i] = b[len(b)-i-1]
144 }
145 return new(big.Int).SetBytes(bb)
146 }
147
148 func TestScalarMultiplyDistributesOverAdd(t *testing.T) {
149 multiplyDistributesOverAdd := func(x, y, z Scalar) bool {
150
151 var t1 Scalar
152 t1.Add(&x, &y)
153 t1.Multiply(&t1, &z)
154
155
156 var t2 Scalar
157 var t3 Scalar
158 t2.Multiply(&x, &z)
159 t3.Multiply(&y, &z)
160 t2.Add(&t2, &t3)
161
162 return t1 == t2 && isReduced(&t1) && isReduced(&t3)
163 }
164
165 if err := quick.Check(multiplyDistributesOverAdd, quickCheckConfig1024); err != nil {
166 t.Error(err)
167 }
168 }
169
170 func TestScalarAddLikeSubNeg(t *testing.T) {
171 addLikeSubNeg := func(x, y Scalar) bool {
172
173 var t1 Scalar
174 t1.Subtract(&x, &y)
175
176
177 var t2 Scalar
178 t2.Negate(&y)
179 t2.Add(&t2, &x)
180
181 return t1 == t2 && isReduced(&t1)
182 }
183
184 if err := quick.Check(addLikeSubNeg, quickCheckConfig1024); err != nil {
185 t.Error(err)
186 }
187 }
188
189 func TestScalarNonAdjacentForm(t *testing.T) {
190 s := Scalar{[32]byte{
191 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d,
192 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d,
193 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1,
194 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09,
195 }}
196 expectedNaf := [256]int8{
197 0, 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, -11, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1,
198 0, 0, 0, 0, 9, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0,
199 -9, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 9, 0,
200 0, 0, 0, -15, 0, 0, 0, 0, -7, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, -3, 0,
201 0, 0, 0, -11, 0, 0, 0, 0, -7, 0, 0, 0, 0, -13, 0, 0, 0, 0, 11, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 1, 0, 0,
202 0, 0, 0, -15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 13, 0, 0, 0,
203 0, 0, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 7,
204 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
205 }
206
207 sNaf := s.nonAdjacentForm(5)
208
209 for i := 0; i < 256; i++ {
210 if expectedNaf[i] != sNaf[i] {
211 t.Errorf("Wrong digit at position %d, got %d, expected %d", i, sNaf[i], expectedNaf[i])
212 }
213 }
214 }
215
216 type notZeroScalar Scalar
217
218 func (notZeroScalar) Generate(rand *mathrand.Rand, size int) reflect.Value {
219 var s Scalar
220 for s == scZero {
221 s = Scalar{}.Generate(rand, size).Interface().(Scalar)
222 }
223 return reflect.ValueOf(notZeroScalar(s))
224 }
225
226 func TestScalarEqual(t *testing.T) {
227 if scOne.Equal(&scMinusOne) == 1 {
228 t.Errorf("scOne.Equal(&scMinusOne) is true")
229 }
230 if scMinusOne.Equal(&scMinusOne) == 0 {
231 t.Errorf("scMinusOne.Equal(&scMinusOne) is false")
232 }
233 }
234
View as plain text