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.

153 lines
3.7 KiB

  1. package crypto
  2. import (
  3. "bytes"
  4. "crypto/sha256"
  5. "fmt"
  6. "golang.org/x/crypto/ripemd160"
  7. secp256k1 "github.com/btcsuite/btcd/btcec"
  8. "github.com/tendermint/ed25519"
  9. "github.com/tendermint/ed25519/extra25519"
  10. cmn "github.com/tendermint/tmlibs/common"
  11. "github.com/tendermint/tendermint/crypto/tmhash"
  12. )
  13. // An address is a []byte, but hex-encoded even in JSON.
  14. // []byte leaves us the option to change the address length.
  15. // Use an alias so Unmarshal methods (with ptr receivers) are available too.
  16. type Address = cmn.HexBytes
  17. func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) {
  18. err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey)
  19. return
  20. }
  21. //----------------------------------------
  22. type PubKey interface {
  23. Address() Address
  24. Bytes() []byte
  25. VerifyBytes(msg []byte, sig Signature) bool
  26. Equals(PubKey) bool
  27. }
  28. //-------------------------------------
  29. var _ PubKey = PubKeyEd25519{}
  30. const PubKeyEd25519Size = 32
  31. // Implements PubKeyInner
  32. type PubKeyEd25519 [PubKeyEd25519Size]byte
  33. // Address is the SHA256-20 of the raw pubkey bytes.
  34. func (pubKey PubKeyEd25519) Address() Address {
  35. return Address(tmhash.Sum(pubKey[:]))
  36. }
  37. func (pubKey PubKeyEd25519) Bytes() []byte {
  38. bz, err := cdc.MarshalBinaryBare(pubKey)
  39. if err != nil {
  40. panic(err)
  41. }
  42. return bz
  43. }
  44. func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool {
  45. // make sure we use the same algorithm to sign
  46. sig, ok := sig_.(SignatureEd25519)
  47. if !ok {
  48. return false
  49. }
  50. pubKeyBytes := [PubKeyEd25519Size]byte(pubKey)
  51. sigBytes := [SignatureEd25519Size]byte(sig)
  52. return ed25519.Verify(&pubKeyBytes, msg, &sigBytes)
  53. }
  54. // For use with golang/crypto/nacl/box
  55. // If error, returns nil.
  56. func (pubKey PubKeyEd25519) ToCurve25519() *[PubKeyEd25519Size]byte {
  57. keyCurve25519, pubKeyBytes := new([PubKeyEd25519Size]byte), [PubKeyEd25519Size]byte(pubKey)
  58. ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes)
  59. if !ok {
  60. return nil
  61. }
  62. return keyCurve25519
  63. }
  64. func (pubKey PubKeyEd25519) String() string {
  65. return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:])
  66. }
  67. func (pubKey PubKeyEd25519) Equals(other PubKey) bool {
  68. if otherEd, ok := other.(PubKeyEd25519); ok {
  69. return bytes.Equal(pubKey[:], otherEd[:])
  70. } else {
  71. return false
  72. }
  73. }
  74. //-------------------------------------
  75. var _ PubKey = PubKeySecp256k1{}
  76. const PubKeySecp256k1Size = 33
  77. // Implements PubKey.
  78. // Compressed pubkey (just the x-cord),
  79. // prefixed with 0x02 or 0x03, depending on the y-cord.
  80. type PubKeySecp256k1 [PubKeySecp256k1Size]byte
  81. // Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
  82. func (pubKey PubKeySecp256k1) Address() Address {
  83. hasherSHA256 := sha256.New()
  84. hasherSHA256.Write(pubKey[:]) // does not error
  85. sha := hasherSHA256.Sum(nil)
  86. hasherRIPEMD160 := ripemd160.New()
  87. hasherRIPEMD160.Write(sha) // does not error
  88. return Address(hasherRIPEMD160.Sum(nil))
  89. }
  90. func (pubKey PubKeySecp256k1) Bytes() []byte {
  91. bz, err := cdc.MarshalBinaryBare(pubKey)
  92. if err != nil {
  93. panic(err)
  94. }
  95. return bz
  96. }
  97. func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool {
  98. // and assert same algorithm to sign and verify
  99. sig, ok := sig_.(SignatureSecp256k1)
  100. if !ok {
  101. return false
  102. }
  103. pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
  104. if err != nil {
  105. return false
  106. }
  107. sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256())
  108. if err != nil {
  109. return false
  110. }
  111. return sig__.Verify(Sha256(msg), pub__)
  112. }
  113. func (pubKey PubKeySecp256k1) String() string {
  114. return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:])
  115. }
  116. func (pubKey PubKeySecp256k1) Equals(other PubKey) bool {
  117. if otherSecp, ok := other.(PubKeySecp256k1); ok {
  118. return bytes.Equal(pubKey[:], otherSecp[:])
  119. } else {
  120. return false
  121. }
  122. }