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.

204 lines
5.4 KiB

lint: Enable Golint (#4212) * Fix many golint errors * Fix golint errors in the 'lite' package * Don't export Pool.store * Fix typo * Revert unwanted changes * Fix errors in counter package * Fix linter errors in kvstore package * Fix linter error in example package * Fix error in tests package * Fix linter errors in v2 package * Fix linter errors in consensus package * Fix linter errors in evidence package * Fix linter error in fail package * Fix linter errors in query package * Fix linter errors in core package * Fix linter errors in node package * Fix linter errors in mempool package * Fix linter error in conn package * Fix linter errors in pex package * Rename PEXReactor export to Reactor * Fix linter errors in trust package * Fix linter errors in upnp package * Fix linter errors in p2p package * Fix linter errors in proxy package * Fix linter errors in mock_test package * Fix linter error in client_test package * Fix linter errors in coretypes package * Fix linter errors in coregrpc package * Fix linter errors in rpcserver package * Fix linter errors in rpctypes package * Fix linter errors in rpctest package * Fix linter error in json2wal script * Fix linter error in wal2json script * Fix linter errors in kv package * Fix linter error in state package * Fix linter error in grpc_client * Fix linter errors in types package * Fix linter error in version package * Fix remaining errors * Address review comments * Fix broken tests * Reconcile package coregrpc * Fix golangci bot error * Fix new golint errors * Fix broken reference * Enable golint linter * minor changes to bring golint into line * fix failing test * fix pex reactor naming * address PR comments
5 years ago
lint: Enable Golint (#4212) * Fix many golint errors * Fix golint errors in the 'lite' package * Don't export Pool.store * Fix typo * Revert unwanted changes * Fix errors in counter package * Fix linter errors in kvstore package * Fix linter error in example package * Fix error in tests package * Fix linter errors in v2 package * Fix linter errors in consensus package * Fix linter errors in evidence package * Fix linter error in fail package * Fix linter errors in query package * Fix linter errors in core package * Fix linter errors in node package * Fix linter errors in mempool package * Fix linter error in conn package * Fix linter errors in pex package * Rename PEXReactor export to Reactor * Fix linter errors in trust package * Fix linter errors in upnp package * Fix linter errors in p2p package * Fix linter errors in proxy package * Fix linter errors in mock_test package * Fix linter error in client_test package * Fix linter errors in coretypes package * Fix linter errors in coregrpc package * Fix linter errors in rpcserver package * Fix linter errors in rpctypes package * Fix linter errors in rpctest package * Fix linter error in json2wal script * Fix linter error in wal2json script * Fix linter errors in kv package * Fix linter error in state package * Fix linter error in grpc_client * Fix linter errors in types package * Fix linter error in version package * Fix remaining errors * Address review comments * Fix broken tests * Reconcile package coregrpc * Fix golangci bot error * Fix new golint errors * Fix broken reference * Enable golint linter * minor changes to bring golint into line * fix failing test * fix pex reactor naming * address PR comments
5 years ago
  1. package ed25519
  2. import (
  3. "bytes"
  4. "crypto/ed25519"
  5. "crypto/subtle"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "github.com/hdevalence/ed25519consensus"
  10. "github.com/tendermint/tendermint/crypto"
  11. "github.com/tendermint/tendermint/crypto/tmhash"
  12. tmjson "github.com/tendermint/tendermint/libs/json"
  13. )
  14. //-------------------------------------
  15. var _ crypto.PrivKey = PrivKey{}
  16. const (
  17. PrivKeyName = "tendermint/PrivKeyEd25519"
  18. PubKeyName = "tendermint/PubKeyEd25519"
  19. // PubKeySize is is the size, in bytes, of public keys as used in this package.
  20. PubKeySize = 32
  21. // PrivateKeySize is the size, in bytes, of private keys as used in this package.
  22. PrivateKeySize = 64
  23. // Size of an Edwards25519 signature. Namely the size of a compressed
  24. // Edwards25519 point, and a field element. Both of which are 32 bytes.
  25. SignatureSize = 64
  26. // SeedSize is the size, in bytes, of private key seeds. These are the
  27. // private key representations used by RFC 8032.
  28. SeedSize = 32
  29. KeyType = "ed25519"
  30. )
  31. func init() {
  32. tmjson.RegisterType(PubKey{}, PubKeyName)
  33. tmjson.RegisterType(PrivKey{}, PrivKeyName)
  34. }
  35. // PrivKey implements crypto.PrivKey.
  36. type PrivKey []byte
  37. // Bytes returns the privkey byte format.
  38. func (privKey PrivKey) Bytes() []byte {
  39. return []byte(privKey)
  40. }
  41. // Sign produces a signature on the provided message.
  42. // This assumes the privkey is wellformed in the golang format.
  43. // The first 32 bytes should be random,
  44. // corresponding to the normal ed25519 private key.
  45. // The latter 32 bytes should be the compressed public key.
  46. // If these conditions aren't met, Sign will panic or produce an
  47. // incorrect signature.
  48. func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
  49. signatureBytes := ed25519.Sign(ed25519.PrivateKey(privKey), msg)
  50. return signatureBytes, nil
  51. }
  52. // PubKey gets the corresponding public key from the private key.
  53. //
  54. // Panics if the private key is not initialized.
  55. func (privKey PrivKey) PubKey() crypto.PubKey {
  56. // If the latter 32 bytes of the privkey are all zero, privkey is not
  57. // initialized.
  58. initialized := false
  59. for _, v := range privKey[32:] {
  60. if v != 0 {
  61. initialized = true
  62. break
  63. }
  64. }
  65. if !initialized {
  66. panic("Expected ed25519 PrivKey to include concatenated pubkey bytes")
  67. }
  68. pubkeyBytes := make([]byte, PubKeySize)
  69. copy(pubkeyBytes, privKey[32:])
  70. return PubKey(pubkeyBytes)
  71. }
  72. // Equals - you probably don't need to use this.
  73. // Runs in constant time based on length of the keys.
  74. func (privKey PrivKey) Equals(other crypto.PrivKey) bool {
  75. if otherEd, ok := other.(PrivKey); ok {
  76. return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1
  77. }
  78. return false
  79. }
  80. func (privKey PrivKey) Type() string {
  81. return KeyType
  82. }
  83. // GenPrivKey generates a new ed25519 private key.
  84. // It uses OS randomness in conjunction with the current global random seed
  85. // in tendermint/libs/common to generate the private key.
  86. func GenPrivKey() PrivKey {
  87. return genPrivKey(crypto.CReader())
  88. }
  89. // genPrivKey generates a new ed25519 private key using the provided reader.
  90. func genPrivKey(rand io.Reader) PrivKey {
  91. seed := make([]byte, SeedSize)
  92. _, err := io.ReadFull(rand, seed)
  93. if err != nil {
  94. panic(err)
  95. }
  96. return PrivKey(ed25519.NewKeyFromSeed(seed))
  97. }
  98. // GenPrivKeyFromSecret hashes the secret with SHA2, and uses
  99. // that 32 byte output to create the private key.
  100. // NOTE: secret should be the output of a KDF like bcrypt,
  101. // if it's derived from user input.
  102. func GenPrivKeyFromSecret(secret []byte) PrivKey {
  103. seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes.
  104. return PrivKey(ed25519.NewKeyFromSeed(seed))
  105. }
  106. //-------------------------------------
  107. var _ crypto.PubKey = PubKey{}
  108. // PubKeyEd25519 implements crypto.PubKey for the Ed25519 signature scheme.
  109. type PubKey []byte
  110. // Address is the SHA256-20 of the raw pubkey bytes.
  111. func (pubKey PubKey) Address() crypto.Address {
  112. if len(pubKey) != PubKeySize {
  113. panic("pubkey is incorrect size")
  114. }
  115. return crypto.Address(tmhash.SumTruncated(pubKey))
  116. }
  117. // Bytes returns the PubKey byte format.
  118. func (pubKey PubKey) Bytes() []byte {
  119. return []byte(pubKey)
  120. }
  121. func (pubKey PubKey) VerifySignature(msg []byte, sig []byte) bool {
  122. // make sure we use the same algorithm to sign
  123. if len(sig) != SignatureSize {
  124. return false
  125. }
  126. return ed25519consensus.Verify(ed25519.PublicKey(pubKey), msg, sig)
  127. }
  128. func (pubKey PubKey) String() string {
  129. return fmt.Sprintf("PubKeyEd25519{%X}", []byte(pubKey))
  130. }
  131. func (pubKey PubKey) Type() string {
  132. return KeyType
  133. }
  134. func (pubKey PubKey) Equals(other crypto.PubKey) bool {
  135. if otherEd, ok := other.(PubKey); ok {
  136. return bytes.Equal(pubKey[:], otherEd[:])
  137. }
  138. return false
  139. }
  140. var _ crypto.BatchVerifier = &BatchVerifier{}
  141. // BatchVerifier implements batch verification for ed25519.
  142. // https://github.com/hdevalence/ed25519consensus is used for batch verification
  143. type BatchVerifier struct {
  144. ed25519consensus.BatchVerifier
  145. }
  146. func NewBatchVerifier() crypto.BatchVerifier {
  147. return &BatchVerifier{ed25519consensus.NewBatchVerifier()}
  148. }
  149. func (b *BatchVerifier) Add(key crypto.PubKey, msg, signature []byte) error {
  150. if l := len(key.Bytes()); l != PubKeySize {
  151. return fmt.Errorf("pubkey size is incorrect; expected: %d, got %d", PubKeySize, l)
  152. }
  153. // check that the signature is the correct length & the last byte is set correctly
  154. if len(signature) != SignatureSize || signature[63]&224 != 0 {
  155. return errors.New("invalid signature")
  156. }
  157. b.BatchVerifier.Add(ed25519.PublicKey(key.Bytes()), msg, signature)
  158. return nil
  159. }
  160. func (b *BatchVerifier) Verify() bool {
  161. return b.BatchVerifier.Verify()
  162. }