You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.4 KiB

  1. package secp256k1_test
  2. import (
  3. "encoding/hex"
  4. "math/big"
  5. "testing"
  6. "github.com/btcsuite/btcutil/base58"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "github.com/tendermint/tendermint/crypto"
  10. "github.com/tendermint/tendermint/crypto/secp256k1"
  11. underlyingSecp256k1 "github.com/btcsuite/btcd/btcec"
  12. )
  13. type keyData struct {
  14. priv string
  15. pub string
  16. addr string
  17. }
  18. var secpDataTable = []keyData{
  19. {
  20. priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330",
  21. pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c",
  22. addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3",
  23. },
  24. }
  25. func TestPubKeySecp256k1Address(t *testing.T) {
  26. for _, d := range secpDataTable {
  27. privB, _ := hex.DecodeString(d.priv)
  28. pubB, _ := hex.DecodeString(d.pub)
  29. addrBbz, _, _ := base58.CheckDecode(d.addr)
  30. addrB := crypto.Address(addrBbz)
  31. var priv secp256k1.PrivKey = privB
  32. pubKey := priv.PubKey()
  33. pubT, _ := pubKey.(secp256k1.PubKey)
  34. addr := pubKey.Address()
  35. assert.Equal(t, pubT, secp256k1.PubKey(pubB), "Expected pub keys to match")
  36. assert.Equal(t, addr, addrB, "Expected addresses to match")
  37. }
  38. }
  39. func TestSignAndValidateSecp256k1(t *testing.T) {
  40. privKey := secp256k1.GenPrivKey()
  41. pubKey := privKey.PubKey()
  42. msg := crypto.CRandBytes(128)
  43. sig, err := privKey.Sign(msg)
  44. require.Nil(t, err)
  45. assert.True(t, pubKey.VerifyBytes(msg, sig))
  46. // Mutate the signature, just one bit.
  47. sig[3] ^= byte(0x01)
  48. assert.False(t, pubKey.VerifyBytes(msg, sig))
  49. }
  50. // This test is intended to justify the removal of calls to the underlying library
  51. // in creating the privkey.
  52. func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) {
  53. numberOfTests := 256
  54. for i := 0; i < numberOfTests; i++ {
  55. // Seed the test case with some random bytes
  56. privKeyBytes := [32]byte{}
  57. copy(privKeyBytes[:], crypto.CRandBytes(32))
  58. // This function creates a private and public key in the underlying libraries format.
  59. // The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes
  60. priv, _ := underlyingSecp256k1.PrivKeyFromBytes(underlyingSecp256k1.S256(), privKeyBytes[:])
  61. // this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes,
  62. // pads the bytes from the left with zero bytes. Therefore these two functions composed
  63. // result in the identity function on privKeyBytes, hence the following equality check
  64. // always returning true.
  65. serializedBytes := priv.Serialize()
  66. require.Equal(t, privKeyBytes[:], serializedBytes)
  67. }
  68. }
  69. func TestGenPrivKeySecp256k1(t *testing.T) {
  70. // curve oder N
  71. N := underlyingSecp256k1.S256().N
  72. tests := []struct {
  73. name string
  74. secret []byte
  75. }{
  76. {"empty secret", []byte{}},
  77. {
  78. "some long secret",
  79. []byte("We live in a society exquisitely dependent on science and technology, " +
  80. "in which hardly anyone knows anything about science and technology."),
  81. },
  82. {"another seed used in cosmos tests #1", []byte{0}},
  83. {"another seed used in cosmos tests #2", []byte("mySecret")},
  84. {"another seed used in cosmos tests #3", []byte("")},
  85. }
  86. for _, tt := range tests {
  87. tt := tt
  88. t.Run(tt.name, func(t *testing.T) {
  89. gotPrivKey := secp256k1.GenPrivKeySecp256k1(tt.secret)
  90. require.NotNil(t, gotPrivKey)
  91. // interpret as a big.Int and make sure it is a valid field element:
  92. fe := new(big.Int).SetBytes(gotPrivKey[:])
  93. require.True(t, fe.Cmp(N) < 0)
  94. require.True(t, fe.Sign() > 0)
  95. })
  96. }
  97. }