github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/whisper/whisperv6/message.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:51</date>
    10  //</624342690795884544>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  //
    29  
    30  package whisperv6
    31  
    32  import (
    33  	"crypto/aes"
    34  	"crypto/cipher"
    35  	"crypto/ecdsa"
    36  	crand "crypto/rand"
    37  	"encoding/binary"
    38  	"errors"
    39  	mrand "math/rand"
    40  	"strconv"
    41  
    42  	"github.com/ethereum/go-ethereum/common"
    43  	"github.com/ethereum/go-ethereum/crypto"
    44  	"github.com/ethereum/go-ethereum/crypto/ecies"
    45  	"github.com/ethereum/go-ethereum/log"
    46  )
    47  
    48  //
    49  //
    50  type MessageParams struct {
    51  	TTL      uint32
    52  	Src      *ecdsa.PrivateKey
    53  	Dst      *ecdsa.PublicKey
    54  	KeySym   []byte
    55  	Topic    TopicType
    56  	WorkTime uint32
    57  	PoW      float64
    58  	Payload  []byte
    59  	Padding  []byte
    60  }
    61  
    62  //
    63  //
    64  //
    65  type sentMessage struct {
    66  	Raw []byte
    67  }
    68  
    69  //
    70  //
    71  type ReceivedMessage struct {
    72  	Raw []byte
    73  
    74  	Payload   []byte
    75  	Padding   []byte
    76  	Signature []byte
    77  	Salt      []byte
    78  
    79  PoW   float64          //
    80  Sent  uint32           //
    81  TTL   uint32           //
    82  Src   *ecdsa.PublicKey //
    83  Dst   *ecdsa.PublicKey //
    84  	Topic TopicType
    85  
    86  SymKeyHash   common.Hash //
    87  EnvelopeHash common.Hash //
    88  }
    89  
    90  func isMessageSigned(flags byte) bool {
    91  	return (flags & signatureFlag) != 0
    92  }
    93  
    94  func (msg *ReceivedMessage) isSymmetricEncryption() bool {
    95  	return msg.SymKeyHash != common.Hash{}
    96  }
    97  
    98  func (msg *ReceivedMessage) isAsymmetricEncryption() bool {
    99  	return msg.Dst != nil
   100  }
   101  
   102  //
   103  func NewSentMessage(params *MessageParams) (*sentMessage, error) {
   104  	const payloadSizeFieldMaxSize = 4
   105  	msg := sentMessage{}
   106  	msg.Raw = make([]byte, 1,
   107  		flagsLength+payloadSizeFieldMaxSize+len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit)
   108  msg.Raw[0] = 0 //
   109  	msg.addPayloadSizeField(params.Payload)
   110  	msg.Raw = append(msg.Raw, params.Payload...)
   111  	err := msg.appendPadding(params)
   112  	return &msg, err
   113  }
   114  
   115  //
   116  func (msg *sentMessage) addPayloadSizeField(payload []byte) {
   117  	fieldSize := getSizeOfPayloadSizeField(payload)
   118  	field := make([]byte, 4)
   119  	binary.LittleEndian.PutUint32(field, uint32(len(payload)))
   120  	field = field[:fieldSize]
   121  	msg.Raw = append(msg.Raw, field...)
   122  	msg.Raw[0] |= byte(fieldSize)
   123  }
   124  
   125  //
   126  func getSizeOfPayloadSizeField(payload []byte) int {
   127  	s := 1
   128  	for i := len(payload); i >= 256; i /= 256 {
   129  		s++
   130  	}
   131  	return s
   132  }
   133  
   134  //
   135  //
   136  func (msg *sentMessage) appendPadding(params *MessageParams) error {
   137  	if len(params.Padding) != 0 {
   138  //
   139  		msg.Raw = append(msg.Raw, params.Padding...)
   140  		return nil
   141  	}
   142  
   143  	rawSize := flagsLength + getSizeOfPayloadSizeField(params.Payload) + len(params.Payload)
   144  	if params.Src != nil {
   145  		rawSize += signatureLength
   146  	}
   147  	odd := rawSize % padSizeLimit
   148  	paddingSize := padSizeLimit - odd
   149  	pad := make([]byte, paddingSize)
   150  	_, err := crand.Read(pad)
   151  	if err != nil {
   152  		return err
   153  	}
   154  	if !validateDataIntegrity(pad, paddingSize) {
   155  		return errors.New("failed to generate random padding of size " + strconv.Itoa(paddingSize))
   156  	}
   157  	msg.Raw = append(msg.Raw, pad...)
   158  	return nil
   159  }
   160  
   161  //
   162  //
   163  func (msg *sentMessage) sign(key *ecdsa.PrivateKey) error {
   164  	if isMessageSigned(msg.Raw[0]) {
   165  //
   166  		log.Error("failed to sign the message: already signed")
   167  		return nil
   168  	}
   169  
   170  msg.Raw[0] |= signatureFlag //
   171  	hash := crypto.Keccak256(msg.Raw)
   172  	signature, err := crypto.Sign(hash, key)
   173  	if err != nil {
   174  msg.Raw[0] &= (0xFF ^ signatureFlag) //
   175  		return err
   176  	}
   177  	msg.Raw = append(msg.Raw, signature...)
   178  	return nil
   179  }
   180  
   181  //
   182  func (msg *sentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error {
   183  	if !ValidatePublicKey(key) {
   184  		return errors.New("invalid public key provided for asymmetric encryption")
   185  	}
   186  	encrypted, err := ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), msg.Raw, nil, nil)
   187  	if err == nil {
   188  		msg.Raw = encrypted
   189  	}
   190  	return err
   191  }
   192  
   193  //
   194  //
   195  func (msg *sentMessage) encryptSymmetric(key []byte) (err error) {
   196  	if !validateDataIntegrity(key, aesKeyLength) {
   197  		return errors.New("invalid key provided for symmetric encryption, size: " + strconv.Itoa(len(key)))
   198  	}
   199  	block, err := aes.NewCipher(key)
   200  	if err != nil {
   201  		return err
   202  	}
   203  	aesgcm, err := cipher.NewGCM(block)
   204  	if err != nil {
   205  		return err
   206  	}
   207  salt, err := generateSecureRandomData(aesNonceLength) //
   208  	if err != nil {
   209  		return err
   210  	}
   211  	encrypted := aesgcm.Seal(nil, salt, msg.Raw, nil)
   212  	msg.Raw = append(encrypted, salt...)
   213  	return nil
   214  }
   215  
   216  //
   217  //
   218  //
   219  //
   220  //
   221  func generateSecureRandomData(length int) ([]byte, error) {
   222  	x := make([]byte, length)
   223  	y := make([]byte, length)
   224  	res := make([]byte, length)
   225  
   226  	_, err := crand.Read(x)
   227  	if err != nil {
   228  		return nil, err
   229  	} else if !validateDataIntegrity(x, length) {
   230  		return nil, errors.New("crypto/rand failed to generate secure random data")
   231  	}
   232  	_, err = mrand.Read(y)
   233  	if err != nil {
   234  		return nil, err
   235  	} else if !validateDataIntegrity(y, length) {
   236  		return nil, errors.New("math/rand failed to generate secure random data")
   237  	}
   238  	for i := 0; i < length; i++ {
   239  		res[i] = x[i] ^ y[i]
   240  	}
   241  	if !validateDataIntegrity(res, length) {
   242  		return nil, errors.New("failed to generate secure random data")
   243  	}
   244  	return res, nil
   245  }
   246  
   247  //
   248  func (msg *sentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) {
   249  	if options.TTL == 0 {
   250  		options.TTL = DefaultTTL
   251  	}
   252  	if options.Src != nil {
   253  		if err = msg.sign(options.Src); err != nil {
   254  			return nil, err
   255  		}
   256  	}
   257  	if options.Dst != nil {
   258  		err = msg.encryptAsymmetric(options.Dst)
   259  	} else if options.KeySym != nil {
   260  		err = msg.encryptSymmetric(options.KeySym)
   261  	} else {
   262  		err = errors.New("unable to encrypt the message: neither symmetric nor assymmetric key provided")
   263  	}
   264  	if err != nil {
   265  		return nil, err
   266  	}
   267  
   268  	envelope = NewEnvelope(options.TTL, options.Topic, msg)
   269  	if err = envelope.Seal(options); err != nil {
   270  		return nil, err
   271  	}
   272  	return envelope, nil
   273  }
   274  
   275  //
   276  //
   277  func (msg *ReceivedMessage) decryptSymmetric(key []byte) error {
   278  //
   279  	if len(msg.Raw) < aesNonceLength {
   280  		return errors.New("missing salt or invalid payload in symmetric message")
   281  	}
   282  	salt := msg.Raw[len(msg.Raw)-aesNonceLength:]
   283  
   284  	block, err := aes.NewCipher(key)
   285  	if err != nil {
   286  		return err
   287  	}
   288  	aesgcm, err := cipher.NewGCM(block)
   289  	if err != nil {
   290  		return err
   291  	}
   292  	decrypted, err := aesgcm.Open(nil, salt, msg.Raw[:len(msg.Raw)-aesNonceLength], nil)
   293  	if err != nil {
   294  		return err
   295  	}
   296  	msg.Raw = decrypted
   297  	msg.Salt = salt
   298  	return nil
   299  }
   300  
   301  //
   302  func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
   303  	decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil)
   304  	if err == nil {
   305  		msg.Raw = decrypted
   306  	}
   307  	return err
   308  }
   309  
   310  //
   311  func (msg *ReceivedMessage) ValidateAndParse() bool {
   312  	end := len(msg.Raw)
   313  	if end < 1 {
   314  		return false
   315  	}
   316  
   317  	if isMessageSigned(msg.Raw[0]) {
   318  		end -= signatureLength
   319  		if end <= 1 {
   320  			return false
   321  		}
   322  		msg.Signature = msg.Raw[end : end+signatureLength]
   323  		msg.Src = msg.SigToPubKey()
   324  		if msg.Src == nil {
   325  			return false
   326  		}
   327  	}
   328  
   329  	beg := 1
   330  	payloadSize := 0
   331  sizeOfPayloadSizeField := int(msg.Raw[0] & SizeMask) //
   332  	if sizeOfPayloadSizeField != 0 {
   333  		payloadSize = int(bytesToUintLittleEndian(msg.Raw[beg : beg+sizeOfPayloadSizeField]))
   334  		if payloadSize+1 > end {
   335  			return false
   336  		}
   337  		beg += sizeOfPayloadSizeField
   338  		msg.Payload = msg.Raw[beg : beg+payloadSize]
   339  	}
   340  
   341  	beg += payloadSize
   342  	msg.Padding = msg.Raw[beg:end]
   343  	return true
   344  }
   345  
   346  //
   347  //
   348  func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
   349  defer func() { recover() }() //
   350  
   351  	pub, err := crypto.SigToPub(msg.hash(), msg.Signature)
   352  	if err != nil {
   353  		log.Error("failed to recover public key from signature", "err", err)
   354  		return nil
   355  	}
   356  	return pub
   357  }
   358  
   359  //
   360  func (msg *ReceivedMessage) hash() []byte {
   361  	if isMessageSigned(msg.Raw[0]) {
   362  		sz := len(msg.Raw) - signatureLength
   363  		return crypto.Keccak256(msg.Raw[:sz])
   364  	}
   365  	return crypto.Keccak256(msg.Raw)
   366  }
   367