message.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Contains the Whisper protocol Message element. For formal details please see
  2. // the specs at https://github.com/ethereum/wiki/wiki/Whisper-PoC-1-Protocol-Spec#messages.
  3. package whisper
  4. import (
  5. "crypto/ecdsa"
  6. "math/rand"
  7. "time"
  8. "github.com/ethereum/go-ethereum/common"
  9. "github.com/ethereum/go-ethereum/crypto"
  10. "github.com/ethereum/go-ethereum/logger"
  11. "github.com/ethereum/go-ethereum/logger/glog"
  12. )
  13. // Message represents an end-user data packet to transmit through the Whisper
  14. // protocol. These are wrapped into Envelopes that need not be understood by
  15. // intermediate nodes, just forwarded.
  16. type Message struct {
  17. Flags byte // First bit is signature presence, rest reserved and should be random
  18. Signature []byte
  19. Payload []byte
  20. Sent time.Time // Time when the message was posted into the network
  21. TTL time.Duration // Maximum time to live allowed for the message
  22. To *ecdsa.PublicKey // Message recipient (identity used to decode the message)
  23. Hash common.Hash // Message envelope hash to act as a unique id
  24. }
  25. // Options specifies the exact way a message should be wrapped into an Envelope.
  26. type Options struct {
  27. From *ecdsa.PrivateKey
  28. To *ecdsa.PublicKey
  29. TTL time.Duration
  30. Topics []Topic
  31. }
  32. // NewMessage creates and initializes a non-signed, non-encrypted Whisper message.
  33. func NewMessage(payload []byte) *Message {
  34. // Construct an initial flag set: no signature, rest random
  35. flags := byte(rand.Intn(256))
  36. flags &= ^signatureFlag
  37. // Assemble and return the message
  38. return &Message{
  39. Flags: flags,
  40. Payload: payload,
  41. Sent: time.Now(),
  42. }
  43. }
  44. // Wrap bundles the message into an Envelope to transmit over the network.
  45. //
  46. // pow (Proof Of Work) controls how much time to spend on hashing the message,
  47. // inherently controlling its priority through the network (smaller hash, bigger
  48. // priority).
  49. //
  50. // The user can control the amount of identity, privacy and encryption through
  51. // the options parameter as follows:
  52. // - options.From == nil && options.To == nil: anonymous broadcast
  53. // - options.From != nil && options.To == nil: signed broadcast (known sender)
  54. // - options.From == nil && options.To != nil: encrypted anonymous message
  55. // - options.From != nil && options.To != nil: encrypted signed message
  56. func (self *Message) Wrap(pow time.Duration, options Options) (*Envelope, error) {
  57. // Use the default TTL if non was specified
  58. if options.TTL == 0 {
  59. options.TTL = DefaultTTL
  60. }
  61. self.TTL = options.TTL
  62. // Sign and encrypt the message if requested
  63. if options.From != nil {
  64. if err := self.sign(options.From); err != nil {
  65. return nil, err
  66. }
  67. }
  68. if options.To != nil {
  69. if err := self.encrypt(options.To); err != nil {
  70. return nil, err
  71. }
  72. }
  73. // Wrap the processed message, seal it and return
  74. envelope := NewEnvelope(options.TTL, options.Topics, self)
  75. envelope.Seal(pow)
  76. return envelope, nil
  77. }
  78. // sign calculates and sets the cryptographic signature for the message , also
  79. // setting the sign flag.
  80. func (self *Message) sign(key *ecdsa.PrivateKey) (err error) {
  81. self.Flags |= signatureFlag
  82. self.Signature, err = crypto.Sign(self.hash(), key)
  83. return
  84. }
  85. // Recover retrieves the public key of the message signer.
  86. func (self *Message) Recover() *ecdsa.PublicKey {
  87. defer func() { recover() }() // in case of invalid signature
  88. // Short circuit if no signature is present
  89. if self.Signature == nil {
  90. return nil
  91. }
  92. // Otherwise try and recover the signature
  93. pub, err := crypto.SigToPub(self.hash(), self.Signature)
  94. if err != nil {
  95. glog.V(logger.Error).Infof("Could not get public key from signature: %v", err)
  96. return nil
  97. }
  98. return pub
  99. }
  100. // encrypt encrypts a message payload with a public key.
  101. func (self *Message) encrypt(key *ecdsa.PublicKey) (err error) {
  102. self.Payload, err = crypto.Encrypt(key, self.Payload)
  103. return
  104. }
  105. // decrypt decrypts an encrypted payload with a private key.
  106. func (self *Message) decrypt(key *ecdsa.PrivateKey) error {
  107. cleartext, err := crypto.Decrypt(key, self.Payload)
  108. if err == nil {
  109. self.Payload = cleartext
  110. }
  111. return err
  112. }
  113. // hash calculates the SHA3 checksum of the message flags and payload.
  114. func (self *Message) hash() []byte {
  115. return crypto.Sha3(append([]byte{self.Flags}, self.Payload...))
  116. }
  117. // bytes flattens the message contents (flags, signature and payload) into a
  118. // single binary blob.
  119. func (self *Message) bytes() []byte {
  120. return append([]byte{self.Flags}, append(self.Signature, self.Payload...)...)
  121. }