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.

149 lines
3.5 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/go-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. // Implements PubKeyInner
  31. type PubKeyEd25519 [32]byte
  32. // Address is the SHA256-20 of the raw pubkey bytes.
  33. func (pubKey PubKeyEd25519) Address() Address {
  34. return Address(tmhash.Sum(pubKey[:]))
  35. }
  36. func (pubKey PubKeyEd25519) Bytes() []byte {
  37. bz, err := cdc.MarshalBinaryBare(pubKey)
  38. if err != nil {
  39. panic(err)
  40. }
  41. return bz
  42. }
  43. func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool {
  44. // make sure we use the same algorithm to sign
  45. sig, ok := sig_.(SignatureEd25519)
  46. if !ok {
  47. return false
  48. }
  49. pubKeyBytes := [32]byte(pubKey)
  50. sigBytes := [64]byte(sig)
  51. return ed25519.Verify(&pubKeyBytes, msg, &sigBytes)
  52. }
  53. // For use with golang/crypto/nacl/box
  54. // If error, returns nil.
  55. func (pubKey PubKeyEd25519) ToCurve25519() *[32]byte {
  56. keyCurve25519, pubKeyBytes := new([32]byte), [32]byte(pubKey)
  57. ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes)
  58. if !ok {
  59. return nil
  60. }
  61. return keyCurve25519
  62. }
  63. func (pubKey PubKeyEd25519) String() string {
  64. return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:])
  65. }
  66. func (pubKey PubKeyEd25519) Equals(other PubKey) bool {
  67. if otherEd, ok := other.(PubKeyEd25519); ok {
  68. return bytes.Equal(pubKey[:], otherEd[:])
  69. } else {
  70. return false
  71. }
  72. }
  73. //-------------------------------------
  74. var _ PubKey = PubKeySecp256k1{}
  75. // Implements PubKey.
  76. // Compressed pubkey (just the x-cord),
  77. // prefixed with 0x02 or 0x03, depending on the y-cord.
  78. type PubKeySecp256k1 [33]byte
  79. // Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey))
  80. func (pubKey PubKeySecp256k1) Address() Address {
  81. hasherSHA256 := sha256.New()
  82. hasherSHA256.Write(pubKey[:]) // does not error
  83. sha := hasherSHA256.Sum(nil)
  84. hasherRIPEMD160 := ripemd160.New()
  85. hasherRIPEMD160.Write(sha) // does not error
  86. return Address(hasherRIPEMD160.Sum(nil))
  87. }
  88. func (pubKey PubKeySecp256k1) Bytes() []byte {
  89. bz, err := cdc.MarshalBinaryBare(pubKey)
  90. if err != nil {
  91. panic(err)
  92. }
  93. return bz
  94. }
  95. func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool {
  96. // and assert same algorithm to sign and verify
  97. sig, ok := sig_.(SignatureSecp256k1)
  98. if !ok {
  99. return false
  100. }
  101. pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
  102. if err != nil {
  103. return false
  104. }
  105. sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256())
  106. if err != nil {
  107. return false
  108. }
  109. return sig__.Verify(Sha256(msg), pub__)
  110. }
  111. func (pubKey PubKeySecp256k1) String() string {
  112. return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:])
  113. }
  114. func (pubKey PubKeySecp256k1) Equals(other PubKey) bool {
  115. if otherSecp, ok := other.(PubKeySecp256k1); ok {
  116. return bytes.Equal(pubKey[:], otherSecp[:])
  117. } else {
  118. return false
  119. }
  120. }