github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/whisper/whisperv5/message.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Contains the Whisper protocol Message element.
    18  
    19  package whisperv5
    20  
    21  import (
    22  	"crypto/aes"
    23  	"crypto/cipher"
    24  	"crypto/ecdsa"
    25  	crand "crypto/rand"
    26  	"crypto/sha256"
    27  	"errors"
    28  	"fmt"
    29  	mrand "math/rand"
    30  
    31  	"github.com/atheioschain/go-atheios/common"
    32  	"github.com/atheioschain/go-atheios/crypto"
    33  	"github.com/atheioschain/go-atheios/logger"
    34  	"github.com/atheioschain/go-atheios/logger/glog"
    35  	"golang.org/x/crypto/pbkdf2"
    36  )
    37  
    38  // Options specifies the exact way a message should be wrapped into an Envelope.
    39  type MessageParams struct {
    40  	TTL      uint32
    41  	Src      *ecdsa.PrivateKey
    42  	Dst      *ecdsa.PublicKey
    43  	KeySym   []byte
    44  	Topic    TopicType
    45  	WorkTime uint32
    46  	PoW      float64
    47  	Payload  []byte
    48  	Padding  []byte
    49  }
    50  
    51  // SentMessage represents an end-user data packet to transmit through the
    52  // Whisper protocol. These are wrapped into Envelopes that need not be
    53  // understood by intermediate nodes, just forwarded.
    54  type SentMessage struct {
    55  	Raw []byte
    56  }
    57  
    58  // ReceivedMessage represents a data packet to be received through the
    59  // Whisper protocol.
    60  type ReceivedMessage struct {
    61  	Raw []byte
    62  
    63  	Payload   []byte
    64  	Padding   []byte
    65  	Signature []byte
    66  
    67  	PoW   float64          // Proof of work as described in the Whisper spec
    68  	Sent  uint32           // Time when the message was posted into the network
    69  	TTL   uint32           // Maximum time to live allowed for the message
    70  	Src   *ecdsa.PublicKey // Message recipient (identity used to decode the message)
    71  	Dst   *ecdsa.PublicKey // Message recipient (identity used to decode the message)
    72  	Topic TopicType
    73  
    74  	SymKeyHash      common.Hash // The Keccak256Hash of the key, associated with the Topic
    75  	EnvelopeHash    common.Hash // Message envelope hash to act as a unique id
    76  	EnvelopeVersion uint64
    77  }
    78  
    79  func isMessageSigned(flags byte) bool {
    80  	return (flags & signatureFlag) != 0
    81  }
    82  
    83  func (msg *ReceivedMessage) isSymmetricEncryption() bool {
    84  	return msg.SymKeyHash != common.Hash{}
    85  }
    86  
    87  func (msg *ReceivedMessage) isAsymmetricEncryption() bool {
    88  	return msg.Dst != nil
    89  }
    90  
    91  func DeriveOneTimeKey(key []byte, salt []byte, version uint64) ([]byte, error) {
    92  	if version == 0 {
    93  		derivedKey := pbkdf2.Key(key, salt, 8, aesKeyLength, sha256.New)
    94  		return derivedKey, nil
    95  	} else {
    96  		return nil, unknownVersionError(version)
    97  	}
    98  }
    99  
   100  // NewMessage creates and initializes a non-signed, non-encrypted Whisper message.
   101  func NewSentMessage(params *MessageParams) *SentMessage {
   102  	msg := SentMessage{}
   103  	msg.Raw = make([]byte, 1, len(params.Payload)+len(params.Payload)+signatureLength+padSizeLimitUpper)
   104  	msg.Raw[0] = 0 // set all the flags to zero
   105  	msg.appendPadding(params)
   106  	msg.Raw = append(msg.Raw, params.Payload...)
   107  	return &msg
   108  }
   109  
   110  // appendPadding appends the pseudorandom padding bytes and sets the padding flag.
   111  // The last byte contains the size of padding (thus, its size must not exceed 256).
   112  func (msg *SentMessage) appendPadding(params *MessageParams) {
   113  	total := len(params.Payload) + 1
   114  	if params.Src != nil {
   115  		total += signatureLength
   116  	}
   117  	padChunk := padSizeLimitUpper
   118  	if total <= padSizeLimitLower {
   119  		padChunk = padSizeLimitLower
   120  	}
   121  	odd := total % padChunk
   122  	if odd > 0 {
   123  		padSize := padChunk - odd
   124  		if padSize > 255 {
   125  			// this algorithm is only valid if padSizeLimitUpper <= 256.
   126  			// if padSizeLimitUpper will ever change, please fix the algorithm
   127  			// (for more information see ReceivedMessage.extractPadding() function).
   128  			panic("please fix the padding algorithm before releasing new version")
   129  		}
   130  		buf := make([]byte, padSize)
   131  		randomize(buf[1:])
   132  		buf[0] = byte(padSize)
   133  		if params.Padding != nil {
   134  			copy(buf[1:], params.Padding)
   135  		}
   136  		msg.Raw = append(msg.Raw, buf...)
   137  		msg.Raw[0] |= byte(0x1) // number of bytes indicating the padding size
   138  	}
   139  }
   140  
   141  // sign calculates and sets the cryptographic signature for the message,
   142  // also setting the sign flag.
   143  func (msg *SentMessage) sign(key *ecdsa.PrivateKey) error {
   144  	if isMessageSigned(msg.Raw[0]) {
   145  		// this should not happen, but no reason to panic
   146  		glog.V(logger.Error).Infof("Trying to sign a message which was already signed")
   147  		return nil
   148  	}
   149  
   150  	msg.Raw[0] |= signatureFlag
   151  	hash := crypto.Keccak256(msg.Raw)
   152  	signature, err := crypto.Sign(hash, key)
   153  	if err != nil {
   154  		msg.Raw[0] &= ^signatureFlag // clear the flag
   155  		return err
   156  	}
   157  	msg.Raw = append(msg.Raw, signature...)
   158  	return nil
   159  }
   160  
   161  // encryptAsymmetric encrypts a message with a public key.
   162  func (msg *SentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error {
   163  	if !ValidatePublicKey(key) {
   164  		return fmt.Errorf("Invalid public key provided for asymmetric encryption")
   165  	}
   166  	encrypted, err := crypto.Encrypt(key, msg.Raw)
   167  	if err == nil {
   168  		msg.Raw = encrypted
   169  	}
   170  	return err
   171  }
   172  
   173  // encryptSymmetric encrypts a message with a topic key, using AES-GCM-256.
   174  // nonce size should be 12 bytes (see cipher.gcmStandardNonceSize).
   175  func (msg *SentMessage) encryptSymmetric(key []byte) (salt []byte, nonce []byte, err error) {
   176  	if !validateSymmetricKey(key) {
   177  		return nil, nil, errors.New("invalid key provided for symmetric encryption")
   178  	}
   179  
   180  	salt = make([]byte, saltLength)
   181  	_, err = crand.Read(salt)
   182  	if err != nil {
   183  		return nil, nil, err
   184  	} else if !validateSymmetricKey(salt) {
   185  		return nil, nil, errors.New("crypto/rand failed to generate salt")
   186  	}
   187  
   188  	derivedKey, err := DeriveOneTimeKey(key, salt, EnvelopeVersion)
   189  	if err != nil {
   190  		return nil, nil, err
   191  	}
   192  	if !validateSymmetricKey(derivedKey) {
   193  		return nil, nil, errors.New("failed to derive one-time key")
   194  	}
   195  	block, err := aes.NewCipher(derivedKey)
   196  	if err != nil {
   197  		return nil, nil, err
   198  	}
   199  	aesgcm, err := cipher.NewGCM(block)
   200  	if err != nil {
   201  		return nil, nil, err
   202  	}
   203  
   204  	// never use more than 2^32 random nonces with a given key
   205  	nonce = make([]byte, aesgcm.NonceSize())
   206  	_, err = crand.Read(nonce)
   207  	if err != nil {
   208  		return nil, nil, err
   209  	} else if !validateSymmetricKey(nonce) {
   210  		return nil, nil, errors.New("crypto/rand failed to generate nonce")
   211  	}
   212  
   213  	msg.Raw = aesgcm.Seal(nil, nonce, msg.Raw, nil)
   214  	return salt, nonce, nil
   215  }
   216  
   217  // Wrap bundles the message into an Envelope to transmit over the network.
   218  //
   219  // pow (Proof Of Work) controls how much time to spend on hashing the message,
   220  // inherently controlling its priority through the network (smaller hash, bigger
   221  // priority).
   222  //
   223  // The user can control the amount of identity, privacy and encryption through
   224  // the options parameter as follows:
   225  //   - options.From == nil && options.To == nil: anonymous broadcast
   226  //   - options.From != nil && options.To == nil: signed broadcast (known sender)
   227  //   - options.From == nil && options.To != nil: encrypted anonymous message
   228  //   - options.From != nil && options.To != nil: encrypted signed message
   229  func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) {
   230  	if options.TTL == 0 {
   231  		options.TTL = DefaultTTL
   232  	}
   233  	if options.Src != nil {
   234  		err = msg.sign(options.Src)
   235  		if err != nil {
   236  			return nil, err
   237  		}
   238  	}
   239  	if len(msg.Raw) > MaxMessageLength {
   240  		glog.V(logger.Error).Infof("Message size must not exceed %d bytes", MaxMessageLength)
   241  		return nil, errors.New("Oversized message")
   242  	}
   243  	var salt, nonce []byte
   244  	if options.Dst != nil {
   245  		err = msg.encryptAsymmetric(options.Dst)
   246  	} else if options.KeySym != nil {
   247  		salt, nonce, err = msg.encryptSymmetric(options.KeySym)
   248  	} else {
   249  		err = errors.New("Unable to encrypt the message: neither Dst nor Key")
   250  	}
   251  
   252  	if err != nil {
   253  		return nil, err
   254  	}
   255  
   256  	envelope = NewEnvelope(options.TTL, options.Topic, salt, nonce, msg)
   257  	err = envelope.Seal(options)
   258  	if err != nil {
   259  		return nil, err
   260  	}
   261  
   262  	return envelope, nil
   263  }
   264  
   265  // decryptSymmetric decrypts a message with a topic key, using AES-GCM-256.
   266  // nonce size should be 12 bytes (see cipher.gcmStandardNonceSize).
   267  func (msg *ReceivedMessage) decryptSymmetric(key []byte, salt []byte, nonce []byte) error {
   268  	derivedKey, err := DeriveOneTimeKey(key, salt, msg.EnvelopeVersion)
   269  	if err != nil {
   270  		return err
   271  	}
   272  
   273  	block, err := aes.NewCipher(derivedKey)
   274  	if err != nil {
   275  		return err
   276  	}
   277  	aesgcm, err := cipher.NewGCM(block)
   278  	if err != nil {
   279  		return err
   280  	}
   281  	if len(nonce) != aesgcm.NonceSize() {
   282  		info := fmt.Sprintf("Wrong AES nonce size - want: %d, got: %d", len(nonce), aesgcm.NonceSize())
   283  		glog.V(logger.Error).Infof(info)
   284  		return errors.New(info)
   285  	}
   286  	decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil)
   287  	if err != nil {
   288  		return err
   289  	}
   290  	msg.Raw = decrypted
   291  	return nil
   292  }
   293  
   294  // decryptAsymmetric decrypts an encrypted payload with a private key.
   295  func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
   296  	decrypted, err := crypto.Decrypt(key, msg.Raw)
   297  	if err == nil {
   298  		msg.Raw = decrypted
   299  	}
   300  	return err
   301  }
   302  
   303  // Validate checks the validity and extracts the fields in case of success
   304  func (msg *ReceivedMessage) Validate() bool {
   305  	end := len(msg.Raw)
   306  	if end < 1 {
   307  		return false
   308  	}
   309  
   310  	if isMessageSigned(msg.Raw[0]) {
   311  		end -= signatureLength
   312  		if end <= 1 {
   313  			return false
   314  		}
   315  		msg.Signature = msg.Raw[end:]
   316  		msg.Src = msg.SigToPubKey()
   317  		if msg.Src == nil {
   318  			return false
   319  		}
   320  	}
   321  
   322  	padSize, ok := msg.extractPadding(end)
   323  	if !ok {
   324  		return false
   325  	}
   326  
   327  	msg.Payload = msg.Raw[1+padSize : end]
   328  	return true
   329  }
   330  
   331  // extractPadding extracts the padding from raw message.
   332  // although we don't support sending messages with padding size
   333  // exceeding 255 bytes, such messages are perfectly valid, and
   334  // can be successfully decrypted.
   335  func (msg *ReceivedMessage) extractPadding(end int) (int, bool) {
   336  	paddingSize := 0
   337  	sz := int(msg.Raw[0] & paddingMask) // number of bytes containing the entire size of padding, could be zero
   338  	if sz != 0 {
   339  		paddingSize = int(bytesToIntLittleEndian(msg.Raw[1 : 1+sz]))
   340  		if paddingSize < sz || paddingSize+1 > end {
   341  			return 0, false
   342  		}
   343  		msg.Padding = msg.Raw[1+sz : 1+paddingSize]
   344  	}
   345  	return paddingSize, true
   346  }
   347  
   348  // Recover retrieves the public key of the message signer.
   349  func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
   350  	defer func() { recover() }() // in case of invalid signature
   351  
   352  	pub, err := crypto.SigToPub(msg.hash(), msg.Signature)
   353  	if err != nil {
   354  		glog.V(logger.Error).Infof("Could not get public key from signature: %v", err)
   355  		return nil
   356  	}
   357  	return pub
   358  }
   359  
   360  // hash calculates the SHA3 checksum of the message flags, payload and padding.
   361  func (msg *ReceivedMessage) hash() []byte {
   362  	if isMessageSigned(msg.Raw[0]) {
   363  		sz := len(msg.Raw) - signatureLength
   364  		return crypto.Keccak256(msg.Raw[:sz])
   365  	}
   366  	return crypto.Keccak256(msg.Raw)
   367  }
   368  
   369  // rand.Rand provides a Read method in Go 1.7 and later,
   370  // but we can't use it yet.
   371  func randomize(b []byte) {
   372  	cnt := 0
   373  	val := mrand.Int63()
   374  	for n := 0; n < len(b); n++ {
   375  		b[n] = byte(val)
   376  		val >>= 8
   377  		cnt++
   378  		if cnt >= 7 {
   379  			cnt = 0
   380  			val = mrand.Int63()
   381  		}
   382  	}
   383  }