1// Copyright (c) 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 5package edwards25519 6 7import ( 8 "testing" 9 "testing/quick" 10) 11 12var ( 13 // a random scalar generated using dalek. 14 dalekScalar, _ = (&Scalar{}).SetCanonicalBytes([]byte{219, 106, 114, 9, 174, 249, 155, 89, 69, 203, 201, 93, 92, 116, 234, 187, 78, 115, 103, 172, 182, 98, 62, 103, 187, 136, 13, 100, 248, 110, 12, 4}) 15 // the above, times the edwards25519 basepoint. 16 dalekScalarBasepoint, _ = new(Point).SetBytes([]byte{0xf4, 0xef, 0x7c, 0xa, 0x34, 0x55, 0x7b, 0x9f, 0x72, 0x3b, 0xb6, 0x1e, 0xf9, 0x46, 0x9, 0x91, 0x1c, 0xb9, 0xc0, 0x6c, 0x17, 0x28, 0x2d, 0x8b, 0x43, 0x2b, 0x5, 0x18, 0x6a, 0x54, 0x3e, 0x48}) 17) 18 19func TestScalarMultSmallScalars(t *testing.T) { 20 var z Scalar 21 var p Point 22 p.ScalarMult(&z, B) 23 if I.Equal(&p) != 1 { 24 t.Error("0*B != 0") 25 } 26 checkOnCurve(t, &p) 27 28 scEight, _ := (&Scalar{}).SetCanonicalBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) 29 p.ScalarMult(scEight, B) 30 if B.Equal(&p) != 1 { 31 t.Error("1*B != 1") 32 } 33 checkOnCurve(t, &p) 34} 35 36func TestScalarMultVsDalek(t *testing.T) { 37 var p Point 38 p.ScalarMult(dalekScalar, B) 39 if dalekScalarBasepoint.Equal(&p) != 1 { 40 t.Error("Scalar mul does not match dalek") 41 } 42 checkOnCurve(t, &p) 43} 44 45func TestBaseMultVsDalek(t *testing.T) { 46 var p Point 47 p.ScalarBaseMult(dalekScalar) 48 if dalekScalarBasepoint.Equal(&p) != 1 { 49 t.Error("Scalar mul does not match dalek") 50 } 51 checkOnCurve(t, &p) 52} 53 54func TestVarTimeDoubleBaseMultVsDalek(t *testing.T) { 55 var p Point 56 var z Scalar 57 p.VarTimeDoubleScalarBaseMult(dalekScalar, B, &z) 58 if dalekScalarBasepoint.Equal(&p) != 1 { 59 t.Error("VarTimeDoubleScalarBaseMult fails with b=0") 60 } 61 checkOnCurve(t, &p) 62 p.VarTimeDoubleScalarBaseMult(&z, B, dalekScalar) 63 if dalekScalarBasepoint.Equal(&p) != 1 { 64 t.Error("VarTimeDoubleScalarBaseMult fails with a=0") 65 } 66 checkOnCurve(t, &p) 67} 68 69func TestScalarMultDistributesOverAdd(t *testing.T) { 70 scalarMultDistributesOverAdd := func(x, y Scalar) bool { 71 var z Scalar 72 z.Add(&x, &y) 73 var p, q, r, check Point 74 p.ScalarMult(&x, B) 75 q.ScalarMult(&y, B) 76 r.ScalarMult(&z, B) 77 check.Add(&p, &q) 78 checkOnCurve(t, &p, &q, &r, &check) 79 return check.Equal(&r) == 1 80 } 81 82 if err := quick.Check(scalarMultDistributesOverAdd, quickCheckConfig(32)); err != nil { 83 t.Error(err) 84 } 85} 86 87func TestScalarMultNonIdentityPoint(t *testing.T) { 88 // Check whether p.ScalarMult and q.ScalaBaseMult give the same, 89 // when p and q are originally set to the base point. 90 91 scalarMultNonIdentityPoint := func(x Scalar) bool { 92 var p, q Point 93 p.Set(B) 94 q.Set(B) 95 96 p.ScalarMult(&x, B) 97 q.ScalarBaseMult(&x) 98 99 checkOnCurve(t, &p, &q) 100 101 return p.Equal(&q) == 1 102 } 103 104 if err := quick.Check(scalarMultNonIdentityPoint, quickCheckConfig(32)); err != nil { 105 t.Error(err) 106 } 107} 108 109func TestBasepointTableGeneration(t *testing.T) { 110 // The basepoint table is 32 affineLookupTables, 111 // corresponding to (16^2i)*B for table i. 112 basepointTable := basepointTable() 113 114 tmp1 := &projP1xP1{} 115 tmp2 := &projP2{} 116 tmp3 := &Point{} 117 tmp3.Set(B) 118 table := make([]affineLookupTable, 32) 119 for i := 0; i < 32; i++ { 120 // Build the table 121 table[i].FromP3(tmp3) 122 // Assert equality with the hardcoded one 123 if table[i] != basepointTable[i] { 124 t.Errorf("Basepoint table %d does not match", i) 125 } 126 127 // Set p = (16^2)*p = 256*p = 2^8*p 128 tmp2.FromP3(tmp3) 129 for j := 0; j < 7; j++ { 130 tmp1.Double(tmp2) 131 tmp2.FromP1xP1(tmp1) 132 } 133 tmp1.Double(tmp2) 134 tmp3.fromP1xP1(tmp1) 135 checkOnCurve(t, tmp3) 136 } 137} 138 139func TestScalarMultMatchesBaseMult(t *testing.T) { 140 scalarMultMatchesBaseMult := func(x Scalar) bool { 141 var p, q Point 142 p.ScalarMult(&x, B) 143 q.ScalarBaseMult(&x) 144 checkOnCurve(t, &p, &q) 145 return p.Equal(&q) == 1 146 } 147 148 if err := quick.Check(scalarMultMatchesBaseMult, quickCheckConfig(32)); err != nil { 149 t.Error(err) 150 } 151} 152 153func TestBasepointNafTableGeneration(t *testing.T) { 154 var table nafLookupTable8 155 table.FromP3(B) 156 157 if table != *basepointNafTable() { 158 t.Error("BasepointNafTable does not match") 159 } 160} 161 162func TestVarTimeDoubleBaseMultMatchesBaseMult(t *testing.T) { 163 varTimeDoubleBaseMultMatchesBaseMult := func(x, y Scalar) bool { 164 var p, q1, q2, check Point 165 166 p.VarTimeDoubleScalarBaseMult(&x, B, &y) 167 168 q1.ScalarBaseMult(&x) 169 q2.ScalarBaseMult(&y) 170 check.Add(&q1, &q2) 171 172 checkOnCurve(t, &p, &check, &q1, &q2) 173 return p.Equal(&check) == 1 174 } 175 176 if err := quick.Check(varTimeDoubleBaseMultMatchesBaseMult, quickCheckConfig(32)); err != nil { 177 t.Error(err) 178 } 179} 180 181// Benchmarks. 182 183func BenchmarkScalarBaseMult(b *testing.B) { 184 var p Point 185 186 for i := 0; i < b.N; i++ { 187 p.ScalarBaseMult(dalekScalar) 188 } 189} 190 191func BenchmarkScalarMult(b *testing.B) { 192 var p Point 193 194 for i := 0; i < b.N; i++ { 195 p.ScalarMult(dalekScalar, B) 196 } 197} 198 199func BenchmarkVarTimeDoubleScalarBaseMult(b *testing.B) { 200 var p Point 201 202 for i := 0; i < b.N; i++ { 203 p.VarTimeDoubleScalarBaseMult(dalekScalar, B, dalekScalar) 204 } 205} 206