...

Source file src/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor_test.go

Documentation: github.com/decred/dcrd/dcrec/secp256k1/v4

     1  // Copyright (c) 2020-2022 The Decred developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package secp256k1
     6  
     7  import (
     8  	"math/big"
     9  	"math/rand"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  // randBytes returns a byte slice of the required size created from a random
    15  // value generated by the passed rng.
    16  func randBytes(t *testing.T, rng *rand.Rand, numBytes uint8) []byte {
    17  	t.Helper()
    18  
    19  	buf := make([]byte, numBytes)
    20  	if _, err := rng.Read(buf); err != nil {
    21  		t.Fatalf("failed to read random: %v", err)
    22  	}
    23  
    24  	return buf
    25  }
    26  
    27  // TestIsOnCurveAdaptor ensures the IsOnCurve method used to satisfy the
    28  // elliptic.Curve interface works as intended.
    29  func TestIsOnCurveAdaptor(t *testing.T) {
    30  	s256 := S256()
    31  	if !s256.IsOnCurve(s256.Params().Gx, s256.Params().Gy) {
    32  		t.Fatal("generator point does not claim to be on the curve")
    33  	}
    34  }
    35  
    36  // isValidAffinePoint returns true if the point (x,y) is on the secp256k1 curve
    37  // or is the point at infinity.
    38  func isValidAffinePoint(x, y *big.Int) bool {
    39  	if x.Sign() == 0 && y.Sign() == 0 {
    40  		return true
    41  	}
    42  	return S256().IsOnCurve(x, y)
    43  }
    44  
    45  // TestAddAffineAdaptor tests addition of points in affine coordinates via the
    46  // method used to satisfy the elliptic.Curve interface works as intended for
    47  // some edge cases and known good values.
    48  func TestAddAffineAdaptor(t *testing.T) {
    49  	tests := []struct {
    50  		name   string // test description
    51  		x1, y1 string // hex encoded coordinates of first point to add
    52  		x2, y2 string // hex encoded coordinates of second point to add
    53  		x3, y3 string // hex encoded coordinates of expected point
    54  	}{{
    55  		// Addition with the point at infinity (left hand side).
    56  		name: "∞ + P = P",
    57  		x1:   "0",
    58  		y1:   "0",
    59  		x2:   "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
    60  		y2:   "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
    61  		x3:   "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
    62  		y3:   "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
    63  	}, {
    64  		// Addition with the point at infinity (right hand side).
    65  		name: "P + ∞ = P",
    66  		x1:   "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
    67  		y1:   "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
    68  		x2:   "0",
    69  		y2:   "0",
    70  		x3:   "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
    71  		y3:   "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
    72  	}, {
    73  		// Addition with different x values.
    74  		name: "P(x1, y1) + P(x2, y2)",
    75  		x1:   "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
    76  		y1:   "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
    77  		x2:   "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
    78  		y2:   "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
    79  		x3:   "fd5b88c21d3143518d522cd2796f3d726793c88b3e05636bc829448e053fed69",
    80  		y3:   "21cf4f6a5be5ff6380234c50424a970b1f7e718f5eb58f68198c108d642a137f",
    81  	}, {
    82  		// Addition with same x opposite y.
    83  		name: "P(x, y) + P(x, -y) = ∞",
    84  		x1:   "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
    85  		y1:   "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
    86  		x2:   "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
    87  		y2:   "f48e156428cf0276dc092da5856e182288d7569f97934a56fe44be60f0d359fd",
    88  		x3:   "0",
    89  		y3:   "0",
    90  	}, {
    91  		// Addition with same point.
    92  		name: "P(x, y) + P(x, y) = 2P",
    93  		x1:   "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
    94  		y1:   "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
    95  		x2:   "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
    96  		y2:   "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
    97  		x3:   "59477d88ae64a104dbb8d31ec4ce2d91b2fe50fa628fb6a064e22582196b365b",
    98  		y3:   "938dc8c0f13d1e75c987cb1a220501bd614b0d3dd9eb5c639847e1240216e3b6",
    99  	}}
   100  
   101  	curve := S256()
   102  	for _, test := range tests {
   103  		// Parse the test data.
   104  		x1, y1 := fromHex(test.x1), fromHex(test.y1)
   105  		x2, y2 := fromHex(test.x2), fromHex(test.y2)
   106  		x3, y3 := fromHex(test.x3), fromHex(test.y3)
   107  
   108  		// Ensure the test data is using points that are actually on the curve
   109  		// (or the point at infinity).
   110  		if !isValidAffinePoint(x1, y1) {
   111  			t.Errorf("%s: first point is not on curve", test.name)
   112  			continue
   113  		}
   114  		if !isValidAffinePoint(x2, y2) {
   115  			t.Errorf("%s: second point is not on curve", test.name)
   116  			continue
   117  		}
   118  		if !isValidAffinePoint(x3, y3) {
   119  			t.Errorf("%s: expected point is not on curve", test.name)
   120  			continue
   121  		}
   122  
   123  		// Add the two points and ensure the result matches expected.
   124  		rx, ry := curve.Add(x1, y1, x2, y2)
   125  		if rx.Cmp(x3) != 0 || ry.Cmp(y3) != 0 {
   126  			t.Errorf("%s: wrong result\ngot: (%x, %x)\nwant: (%x, %x)",
   127  				test.name, rx, ry, x3, y3)
   128  			continue
   129  		}
   130  	}
   131  }
   132  
   133  // TestDoubleAffineAdaptor tests doubling of points in affine coordinates via
   134  // the method used to satisfy the elliptic.Curve interface works as intended for
   135  // some edge cases and known good values.
   136  func TestDoubleAffineAdaptor(t *testing.T) {
   137  	tests := []struct {
   138  		name   string // test description
   139  		x1, y1 string // hex encoded coordinates of point to double
   140  		x3, y3 string // hex encoded coordinates of expected point
   141  	}{{
   142  		// Doubling the point at infinity is still the point at infinity.
   143  		name: "2*∞ = ∞ (point at infinity)",
   144  		x1:   "0",
   145  		y1:   "0",
   146  		x3:   "0",
   147  		y3:   "0",
   148  	}, {
   149  		name: "random point 1",
   150  		x1:   "e41387ffd8baaeeb43c2faa44e141b19790e8ac1f7ff43d480dc132230536f86",
   151  		y1:   "1b88191d430f559896149c86cbcb703193105e3cf3213c0c3556399836a2b899",
   152  		x3:   "88da47a089d333371bd798c548ef7caae76e737c1980b452d367b3cfe3082c19",
   153  		y3:   "3b6f659b09a362821dfcfefdbfbc2e59b935ba081b6c249eb147b3c2100b1bc1",
   154  	}, {
   155  		name: "random point 2",
   156  		x1:   "b3589b5d984f03ef7c80aeae444f919374799edf18d375cab10489a3009cff0c",
   157  		y1:   "c26cf343875b3630e15bccc61202815b5d8f1fd11308934a584a5babe69db36a",
   158  		x3:   "e193860172998751e527bb12563855602a227fc1f612523394da53b746bb2fb1",
   159  		y3:   "2bfcf13d2f5ab8bb5c611fab5ebbed3dc2f057062b39a335224c22f090c04789",
   160  	}, {
   161  		name: "random point 3",
   162  		x1:   "2b31a40fbebe3440d43ac28dba23eee71c62762c3fe3dbd88b4ab82dc6a82340",
   163  		y1:   "9ba7deb02f5c010e217607fd49d58db78ec273371ea828b49891ce2fd74959a1",
   164  		x3:   "2c8d5ef0d343b1a1a48aa336078eadda8481cb048d9305dc4fdf7ee5f65973a2",
   165  		y3:   "bb4914ac729e26d3cd8f8dc8f702f3f4bb7e0e9c5ae43335f6e94c2de6c3dc95",
   166  	}, {
   167  		name: "random point 4",
   168  		x1:   "61c64b760b51981fab54716d5078ab7dffc93730b1d1823477e27c51f6904c7a",
   169  		y1:   "ef6eb16ea1a36af69d7f66524c75a3a5e84c13be8fbc2e811e0563c5405e49bd",
   170  		x3:   "5f0dcdd2595f5ad83318a0f9da481039e36f135005420393e72dfca985b482f4",
   171  		y3:   "a01c849b0837065c1cb481b0932c441f49d1cab1b4b9f355c35173d93f110ae0",
   172  	}}
   173  
   174  	curve := S256()
   175  	for _, test := range tests {
   176  		// Parse test data.
   177  		x1, y1 := fromHex(test.x1), fromHex(test.y1)
   178  		x3, y3 := fromHex(test.x3), fromHex(test.y3)
   179  
   180  		// Ensure the test data is using points that are actually on
   181  		// the curve (or the point at infinity).
   182  		if !isValidAffinePoint(x1, y1) {
   183  			t.Errorf("%s: first point is not on the curve", test.name)
   184  			continue
   185  		}
   186  		if !isValidAffinePoint(x3, y3) {
   187  			t.Errorf("%s: expected point is not on the curve", test.name)
   188  			continue
   189  		}
   190  
   191  		// Double the point and ensure the result matches expected.
   192  		rx, ry := curve.Double(x1, y1)
   193  		if rx.Cmp(x3) != 0 || ry.Cmp(y3) != 0 {
   194  			t.Errorf("%s: wrong result\ngot: (%x, %x)\nwant: (%x, %x)",
   195  				test.name, rx, ry, x3, y3)
   196  			continue
   197  		}
   198  	}
   199  }
   200  
   201  // TestScalarBaseMultAdaptor ensures the ScalarBaseMult method used to satisfy
   202  // the elliptic.Curve interface works as intended for some edge cases and known
   203  // good values.
   204  func TestScalarBaseMultAdaptor(t *testing.T) {
   205  	tests := []struct {
   206  		name   string // test description
   207  		k      string // hex encoded scalar
   208  		rx, ry string // hex encoded coordinates of expected point
   209  	}{{
   210  		name: "zero",
   211  		k:    "0000000000000000000000000000000000000000000000000000000000000000",
   212  		rx:   "0000000000000000000000000000000000000000000000000000000000000000",
   213  		ry:   "0000000000000000000000000000000000000000000000000000000000000000",
   214  	}, {
   215  		name: "one (aka 1*G = G)",
   216  		k:    "0000000000000000000000000000000000000000000000000000000000000001",
   217  		rx:   "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
   218  		ry:   "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
   219  	}, {
   220  		name: "group order - 1 (aka -1*G = -G)",
   221  		k:    "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
   222  		rx:   "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
   223  		ry:   "b7c52588d95c3b9aa25b0403f1eef75702e84bb7597aabe663b82f6f04ef2777",
   224  	}, {
   225  		name: "known good point 1",
   226  		k:    "aa5e28d6a97a2479a65527f7290311a3624d4cc0fa1578598ee3c2613bf99522",
   227  		rx:   "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
   228  		ry:   "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
   229  	}, {
   230  		name: "known good point 2",
   231  		k:    "7e2b897b8cebc6361663ad410835639826d590f393d90a9538881735256dfae3",
   232  		rx:   "d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575",
   233  		ry:   "131c670d414c4546b88ac3ff664611b1c38ceb1c21d76369d7a7a0969d61d97d",
   234  	}, {
   235  		name: "known good point 3",
   236  		k:    "6461e6df0fe7dfd05329f41bf771b86578143d4dd1f7866fb4ca7e97c5fa945d",
   237  		rx:   "e8aecc370aedd953483719a116711963ce201ac3eb21d3f3257bb48668c6a72f",
   238  		ry:   "c25caf2f0eba1ddb2f0f3f47866299ef907867b7d27e95b3873bf98397b24ee1",
   239  	}, {
   240  		name: "known good point 4",
   241  		k:    "376a3a2cdcd12581efff13ee4ad44c4044b8a0524c42422a7e1e181e4deeccec",
   242  		rx:   "14890e61fcd4b0bd92e5b36c81372ca6fed471ef3aa60a3e415ee4fe987daba1",
   243  		ry:   "297b858d9f752ab42d3bca67ee0eb6dcd1c2b7b0dbe23397e66adc272263f982",
   244  	}, {
   245  		name: "known good point 5",
   246  		k:    "1b22644a7be026548810c378d0b2994eefa6d2b9881803cb02ceff865287d1b9",
   247  		rx:   "f73c65ead01c5126f28f442d087689bfa08e12763e0cec1d35b01751fd735ed3",
   248  		ry:   "f449a8376906482a84ed01479bd18882b919c140d638307f0c0934ba12590bde",
   249  	}}
   250  
   251  	curve := S256()
   252  	for _, test := range tests {
   253  		// Parse the test data.
   254  		k := fromHex(test.k)
   255  		xWant, yWant := fromHex(test.rx), fromHex(test.ry)
   256  
   257  		// Ensure the test data is using points that are actually on the curve
   258  		// (or the point at infinity).
   259  		if !isValidAffinePoint(xWant, yWant) {
   260  			t.Errorf("%s: expected point is not on curve", test.name)
   261  			continue
   262  		}
   263  
   264  		rx, ry := curve.ScalarBaseMult(k.Bytes())
   265  		if rx.Cmp(xWant) != 0 || ry.Cmp(yWant) != 0 {
   266  			t.Errorf("%s: wrong result:\ngot (%x, %x)\nwant (%x, %x)",
   267  				test.name, rx, ry, xWant, yWant)
   268  		}
   269  	}
   270  }
   271  
   272  // TestScalarBaseMultAdaptorRandom ensures that the ScalarBaseMult method used
   273  // to satisfy the elliptic.Curve interface works as intended for
   274  // randomly-generated scalars of all lengths up to 40 bytes.
   275  func TestScalarBaseMultAdaptorRandom(t *testing.T) {
   276  	// Use a unique random seed each test instance and log it if the tests fail.
   277  	seed := time.Now().Unix()
   278  	rng := rand.New(rand.NewSource(seed))
   279  	defer func(t *testing.T, seed int64) {
   280  		if t.Failed() {
   281  			t.Logf("random seed: %d", seed)
   282  		}
   283  	}(t, seed)
   284  
   285  	s256 := S256()
   286  	const maxBytes = 40
   287  	const iterations = 10
   288  	for numBytes := uint8(1); numBytes < maxBytes; numBytes++ {
   289  		for i := 0; i < iterations; i++ {
   290  			// Generate a random scalar of the current length.
   291  			k := randBytes(t, rng, numBytes)
   292  
   293  			// Ensure the correct results by performing the multiplication with
   294  			// both the func under test as well as the generic scalar mult func.
   295  			x, y := s256.ScalarBaseMult(k)
   296  			xWant, yWant := s256.ScalarMult(s256.Gx, s256.Gy, k)
   297  			if x.Cmp(xWant) != 0 || y.Cmp(yWant) != 0 {
   298  				t.Errorf("bad output for %x: got (%x, %x), want (%x, %x)", k,
   299  					x, y, xWant, yWant)
   300  				continue
   301  			}
   302  		}
   303  	}
   304  }
   305  
   306  // TestScalarMultAdaptor ensures the ScalarMult method used to satisfy the
   307  // elliptic.Curve interface works as intended for some edge cases and known good
   308  // values.
   309  func TestScalarMultAdaptor(t *testing.T) {
   310  	tests := []struct {
   311  		name   string // test description
   312  		k      string // hex encoded scalar
   313  		x, y   string // hex encoded coordinates of point to multiply
   314  		rx, ry string // hex encoded coordinates of expected point
   315  	}{{
   316  		name: "0*P = ∞ (point at infinity)",
   317  		k:    "0",
   318  		x:    "7e660beda020e9cc20391cef85374576853b0f22b8925d5d81c5845bb834c21e",
   319  		y:    "2d114a5edb320cc9806527d1daf1bbb96a8fedc6f9e8ead421eaef2c7208e409",
   320  		rx:   "0",
   321  		ry:   "0",
   322  	}, {
   323  		name: "1*P = P",
   324  		k:    "1",
   325  		x:    "c00be8830995d1e44f1420dd3b90d3441fb66f6861c84a35f959c495a3be5440",
   326  		y:    "ecf9665e6eba45720de652a340600c7356efe24d228bfe6ea2043e7791c51bb7",
   327  		rx:   "c00be8830995d1e44f1420dd3b90d3441fb66f6861c84a35f959c495a3be5440",
   328  		ry:   "ecf9665e6eba45720de652a340600c7356efe24d228bfe6ea2043e7791c51bb7",
   329  	}, {
   330  		name: "(group order - 1)*P = -P (aka -1*P = -P)",
   331  		k:    "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
   332  		x:    "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
   333  		y:    "cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08",
   334  		rx:   "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
   335  		ry:   "339ea810e73639c329e6c27c9ce4415ff6c1f6976bd173cc2a8c80276f1f2127",
   336  	}, {
   337  		name: "(group order - 1)*-P = P (aka -1*-P = -P, with P from prev test)",
   338  		k:    "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140",
   339  		x:    "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
   340  		y:    "339ea810e73639c329e6c27c9ce4415ff6c1f6976bd173cc2a8c80276f1f2127",
   341  		rx:   "74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9",
   342  		ry:   "cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08",
   343  	}, {
   344  		name: "known good point from base mult tests (aka k*G)",
   345  		k:    "aa5e28d6a97a2479a65527f7290311a3624d4cc0fa1578598ee3c2613bf99522",
   346  		x:    "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
   347  		y:    "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
   348  		rx:   "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6",
   349  		ry:   "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232",
   350  	}, {
   351  		name: "known good result 1",
   352  		k:    "7e2b897b8cebc6361663ad410835639826d590f393d90a9538881735256dfae3",
   353  		x:    "1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5",
   354  		y:    "b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396",
   355  		rx:   "6951f3b50aafbc63e21707dd53623b7f42badd633a0567ef1b37f6e42a4237ad",
   356  		ry:   "9c930796a49110122fbfdedc36418af726197ed950b783a2d29058f8c02130de",
   357  	}, {
   358  		name: "known good result 2",
   359  		k:    "6461e6df0fe7dfd05329f41bf771b86578143d4dd1f7866fb4ca7e97c5fa945d",
   360  		x:    "659214ac1a1790023f53c4cf55a0a63b9e20c1151efa971215b395a558aa151",
   361  		y:    "b126363aa4243d2759320a356230569a4eea355d9dabd94ed7f4590701e5364d",
   362  		rx:   "4ffad856833396ef753c0bd4ea40319295f107c476793df0adac2caea53b3df4",
   363  		ry:   "586fa6b1e9a3ff7df8a2b9b3698badcf40aa06af5600fefc56dd8ae4db5451c5",
   364  	}, {
   365  		name: "known good result 3",
   366  		k:    "376a3a2cdcd12581efff13ee4ad44c4044b8a0524c42422a7e1e181e4deeccec",
   367  		x:    "3f0e80e574456d8f8fa64e044b2eb72ea22eb53fe1efe3a443933aca7f8cb0e3",
   368  		y:    "cb66d7d7296cbc91e90b9c08485d01b39501253aa65b53a4cb0289e2ea5f404f",
   369  		rx:   "35ae6480b18e48070709d9276ed97a50c6ee1fc05ac44386c85826533233d28f",
   370  		ry:   "f88abee3efabd95e80ce8c664bbc3d4d12b24e1a0f4d2b98ba6542789c6715fd",
   371  	}, {
   372  		name: "known good result 4",
   373  		k:    "1b22644a7be026548810c378d0b2994eefa6d2b9881803cb02ceff865287d1b9",
   374  		x:    "d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e",
   375  		y:    "581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58",
   376  		rx:   "cca7f9a4b0d379c31c438050e163a8945f2f910498bd3b545be20ed862bd6cd9",
   377  		ry:   "cfc7bbf37bef62da6e5753ed419168fa1376a3fe949c139a8dd0f5303f4ae947",
   378  	}, {
   379  		name: "known good result 5",
   380  		k:    "7f5b2cb4b43840c75e4afad83d792e1965d8c21c1109505f45c7d46df422d73e",
   381  		x:    "bce74de6d5f98dc027740c2bbff05b6aafe5fd8d103f827e48894a2bd3460117",
   382  		y:    "5bea1fa17a41b115525a3e7dbf0d8d5a4f7ce5c6fc73a6f4f216512417c9f6b4",
   383  		rx:   "3d96b9290fe6c4f2d62fe2175f4333907d0c3637fada1010b45c7d80690e16de",
   384  		ry:   "d59c0e8192d7fbd4846172d6479630b751cd03d0d9be0dca2759c6212b70575d",
   385  	}, {
   386  		// From btcd issue #709.
   387  		name: "early implementation regression point",
   388  		k:    "a2e8ba2e8ba2e8ba2e8ba2e8ba2e8ba219b51835b55cc30ebfe2f6599bc56f58",
   389  		x:    "000000000000000000000000000000000000000000000000000000000000002c",
   390  		y:    "420e7a99bba18a9d3952597510fd2b6728cfeafc21a4e73951091d4d8ddbe94e",
   391  		rx:   "a2112dcdfbcd10ae1133a358de7b82db68e0a3eb4b492cc8268d1e7118c98788",
   392  		ry:   "27fc7463b7bb3c5f98ecf2c84a6272bb1681ed553d92c69f2dfe25a9f9fd3836",
   393  	}}
   394  
   395  	curve := S256()
   396  	for _, test := range tests {
   397  		// Parse the test data.
   398  		k := fromHex(test.k)
   399  		x, y := fromHex(test.x), fromHex(test.y)
   400  		xWant, yWant := fromHex(test.rx), fromHex(test.ry)
   401  
   402  		// Ensure the test data is using points that are actually on the curve
   403  		// (or the point at infinity).
   404  		if !isValidAffinePoint(x, y) {
   405  			t.Errorf("%s: point is not on curve", test.name)
   406  			continue
   407  		}
   408  		if !isValidAffinePoint(xWant, yWant) {
   409  			t.Errorf("%s: expected point is not on curve", test.name)
   410  			continue
   411  		}
   412  
   413  		// Perform scalar point multiplication ensure the result matches
   414  		// expected.
   415  		rx, ry := curve.ScalarMult(x, y, k.Bytes())
   416  		if rx.Cmp(xWant) != 0 || ry.Cmp(yWant) != 0 {
   417  			t.Errorf("%s: wrong result\ngot: (%x, %x)\nwant: (%x, %x)",
   418  				test.name, rx, ry, xWant, yWant)
   419  		}
   420  	}
   421  }
   422  

View as plain text