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.

198 lines
5.9 KiB

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