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.

113 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.PrivKeySecp256k1
  32. copy(priv[:], privB)
  33. pubKey := priv.PubKey()
  34. pubT, _ := pubKey.(secp256k1.PubKeySecp256k1)
  35. pub := pubT[:]
  36. addr := pubKey.Address()
  37. assert.Equal(t, pub, pubB, "Expected pub keys to match")
  38. assert.Equal(t, addr, addrB, "Expected addresses to match")
  39. }
  40. }
  41. func TestSignAndValidateSecp256k1(t *testing.T) {
  42. privKey := secp256k1.GenPrivKey()
  43. pubKey := privKey.PubKey()
  44. msg := crypto.CRandBytes(128)
  45. sig, err := privKey.Sign(msg)
  46. require.Nil(t, err)
  47. assert.True(t, pubKey.VerifyBytes(msg, sig))
  48. // Mutate the signature, just one bit.
  49. sig[3] ^= byte(0x01)
  50. assert.False(t, pubKey.VerifyBytes(msg, sig))
  51. }
  52. // This test is intended to justify the removal of calls to the underlying library
  53. // in creating the privkey.
  54. func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) {
  55. numberOfTests := 256
  56. for i := 0; i < numberOfTests; i++ {
  57. // Seed the test case with some random bytes
  58. privKeyBytes := [32]byte{}
  59. copy(privKeyBytes[:], crypto.CRandBytes(32))
  60. // This function creates a private and public key in the underlying libraries format.
  61. // The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes
  62. priv, _ := underlyingSecp256k1.PrivKeyFromBytes(underlyingSecp256k1.S256(), privKeyBytes[:])
  63. // this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes,
  64. // pads the bytes from the left with zero bytes. Therefore these two functions composed
  65. // result in the identity function on privKeyBytes, hence the following equality check
  66. // always returning true.
  67. serializedBytes := priv.Serialize()
  68. require.Equal(t, privKeyBytes[:], serializedBytes)
  69. }
  70. }
  71. func TestGenPrivKeySecp256k1(t *testing.T) {
  72. // curve oder N
  73. N := underlyingSecp256k1.S256().N
  74. tests := []struct {
  75. name string
  76. secret []byte
  77. }{
  78. {"empty secret", []byte{}},
  79. {"some long secret", []byte("We live in a society exquisitely dependent on science and technology, in which hardly anyone knows anything about science and technology.")},
  80. {"another seed used in cosmos tests #1", []byte{0}},
  81. {"another seed used in cosmos tests #2", []byte("mySecret")},
  82. {"another seed used in cosmos tests #3", []byte("")},
  83. }
  84. for _, tt := range tests {
  85. tt := tt
  86. t.Run(tt.name, func(t *testing.T) {
  87. gotPrivKey := secp256k1.GenPrivKeySecp256k1(tt.secret)
  88. require.NotNil(t, gotPrivKey)
  89. // interpret as a big.Int and make sure it is a valid field element:
  90. fe := new(big.Int).SetBytes(gotPrivKey[:])
  91. require.True(t, fe.Cmp(N) < 0)
  92. require.True(t, fe.Sign() > 0)
  93. })
  94. }
  95. }