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.

207 lines
6.1 KiB

  1. package secp256k1
  2. import (
  3. "bytes"
  4. "crypto/sha256"
  5. "crypto/subtle"
  6. "fmt"
  7. "io"
  8. secp256k1 "github.com/btcsuite/btcd/btcec"
  9. amino "github.com/tendermint/go-amino"
  10. "github.com/tendermint/tendermint/crypto"
  11. "github.com/tendermint/tendermint/libs/common"
  12. "golang.org/x/crypto/ripemd160"
  13. )
  14. //-------------------------------------
  15. const (
  16. Secp256k1PrivKeyAminoRoute = "tendermint/PrivKeySecp256k1"
  17. Secp256k1PubKeyAminoRoute = "tendermint/PubKeySecp256k1"
  18. Secp256k1SignatureAminoRoute = "tendermint/SignatureSecp256k1"
  19. )
  20. var cdc = amino.NewCodec()
  21. func init() {
  22. cdc.RegisterInterface((*crypto.PubKey)(nil), nil)
  23. cdc.RegisterConcrete(PubKeySecp256k1{},
  24. Secp256k1PubKeyAminoRoute, nil)
  25. cdc.RegisterInterface((*crypto.PrivKey)(nil), nil)
  26. cdc.RegisterConcrete(PrivKeySecp256k1{},
  27. Secp256k1PrivKeyAminoRoute, nil)
  28. cdc.RegisterInterface((*crypto.Signature)(nil), nil)
  29. cdc.RegisterConcrete(SignatureSecp256k1{},
  30. Secp256k1SignatureAminoRoute, nil)
  31. }
  32. //-------------------------------------
  33. var _ crypto.PrivKey = PrivKeySecp256k1{}
  34. // PrivKeySecp256k1 implements PrivKey.
  35. type PrivKeySecp256k1 [32]byte
  36. // Bytes marshalls the private key using amino encoding.
  37. func (privKey PrivKeySecp256k1) Bytes() []byte {
  38. return cdc.MustMarshalBinaryBare(privKey)
  39. }
  40. // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
  41. func (privKey PrivKeySecp256k1) Sign(msg []byte) (crypto.Signature, error) {
  42. priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
  43. sig, err := priv.Sign(crypto.Sha256(msg))
  44. if err != nil {
  45. return nil, err
  46. }
  47. return SignatureSecp256k1(sig.Serialize()), nil
  48. }
  49. // PubKey performs the point-scalar multiplication from the privKey on the
  50. // generator point to get the pubkey.
  51. func (privKey PrivKeySecp256k1) PubKey() crypto.PubKey {
  52. _, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
  53. var pubkeyBytes PubKeySecp256k1
  54. copy(pubkeyBytes[:], pubkeyObject.SerializeCompressed())
  55. return pubkeyBytes
  56. }
  57. // Equals - you probably don't need to use this.
  58. // Runs in constant time based on length of the keys.
  59. func (privKey PrivKeySecp256k1) Equals(other crypto.PrivKey) bool {
  60. if otherSecp, ok := other.(PrivKeySecp256k1); ok {
  61. return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1
  62. }
  63. return false
  64. }
  65. // GenPrivKey generates a new ECDSA private key on curve secp256k1 private key.
  66. // It uses OS randomness in conjunction with the current global random seed
  67. // in tendermint/libs/common to generate the private key.
  68. func GenPrivKey() PrivKeySecp256k1 {
  69. return genPrivKey(crypto.CReader())
  70. }
  71. // genPrivKey generates a new secp256k1 private key using the provided reader.
  72. func genPrivKey(rand io.Reader) PrivKeySecp256k1 {
  73. privKeyBytes := [32]byte{}
  74. _, err := io.ReadFull(rand, privKeyBytes[:])
  75. if err != nil {
  76. panic(err)
  77. }
  78. // crypto.CRandBytes is guaranteed to be 32 bytes long, so it can be
  79. // casted to PrivKeySecp256k1.
  80. return PrivKeySecp256k1(privKeyBytes)
  81. }
  82. // GenPrivKeySecp256k1 hashes the secret with SHA2, and uses
  83. // that 32 byte output to create the private key.
  84. // NOTE: secret should be the output of a KDF like bcrypt,
  85. // if it's derived from user input.
  86. func GenPrivKeySecp256k1(secret []byte) PrivKeySecp256k1 {
  87. privKey32 := sha256.Sum256(secret)
  88. // sha256.Sum256() is guaranteed to be 32 bytes long, so it can be
  89. // casted to PrivKeySecp256k1.
  90. return PrivKeySecp256k1(privKey32)
  91. }
  92. //-------------------------------------
  93. var _ crypto.PubKey = PubKeySecp256k1{}
  94. // PubKeySecp256k1Size is comprised of 32 bytes for one field element
  95. // (the x-coordinate), plus one byte for the parity of the y-coordinate.
  96. const PubKeySecp256k1Size = 33
  97. // PubKeySecp256k1 implements crypto.PubKey.
  98. // It is the compressed form of the pubkey. The first byte depends is a 0x02 byte
  99. // if the y-coordinate is the lexicographically largest of the two associated with
  100. // the x-coordinate. Otherwise the first byte is a 0x03.
  101. // This prefix is followed with the x-coordinate.
  102. type PubKeySecp256k1 [PubKeySecp256k1Size]byte
  103. // Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
  104. func (pubKey PubKeySecp256k1) Address() crypto.Address {
  105. hasherSHA256 := sha256.New()
  106. hasherSHA256.Write(pubKey[:]) // does not error
  107. sha := hasherSHA256.Sum(nil)
  108. hasherRIPEMD160 := ripemd160.New()
  109. hasherRIPEMD160.Write(sha) // does not error
  110. return crypto.Address(hasherRIPEMD160.Sum(nil))
  111. }
  112. // Bytes returns the pubkey marshalled with amino encoding.
  113. func (pubKey PubKeySecp256k1) Bytes() []byte {
  114. bz, err := cdc.MarshalBinaryBare(pubKey)
  115. if err != nil {
  116. panic(err)
  117. }
  118. return bz
  119. }
  120. func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, interfaceSig crypto.Signature) bool {
  121. // and assert same algorithm to sign and verify
  122. sig, ok := interfaceSig.(SignatureSecp256k1)
  123. if !ok {
  124. return false
  125. }
  126. pub, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
  127. if err != nil {
  128. return false
  129. }
  130. parsedSig, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256())
  131. if err != nil {
  132. return false
  133. }
  134. return parsedSig.Verify(crypto.Sha256(msg), pub)
  135. }
  136. func (pubKey PubKeySecp256k1) String() string {
  137. return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:])
  138. }
  139. func (pubKey PubKeySecp256k1) Equals(other crypto.PubKey) bool {
  140. if otherSecp, ok := other.(PubKeySecp256k1); ok {
  141. return bytes.Equal(pubKey[:], otherSecp[:])
  142. }
  143. return false
  144. }
  145. //-------------------------------------
  146. var _ crypto.Signature = SignatureSecp256k1{}
  147. // SignatureSecp256k1 implements crypto.Signature
  148. type SignatureSecp256k1 []byte
  149. func (sig SignatureSecp256k1) Bytes() []byte {
  150. bz, err := cdc.MarshalBinaryBare(sig)
  151. if err != nil {
  152. panic(err)
  153. }
  154. return bz
  155. }
  156. func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 }
  157. func (sig SignatureSecp256k1) String() string {
  158. return fmt.Sprintf("/%X.../", common.Fingerprint(sig[:]))
  159. }
  160. func (sig SignatureSecp256k1) Equals(other crypto.Signature) bool {
  161. if otherSecp, ok := other.(SignatureSecp256k1); ok {
  162. return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1
  163. } else {
  164. return false
  165. }
  166. }
  167. func SignatureSecp256k1FromBytes(data []byte) crypto.Signature {
  168. sig := make(SignatureSecp256k1, len(data))
  169. copy(sig[:], data)
  170. return sig
  171. }