github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/whisper/whisperv5/message.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  //
    26  
    27  package whisperv5
    28  
    29  import (
    30  	"crypto/aes"
    31  	"crypto/cipher"
    32  	"crypto/ecdsa"
    33  	crand "crypto/rand"
    34  	"encoding/binary"
    35  	"errors"
    36  	"strconv"
    37  
    38  	"github.com/ethereum/go-ethereum/common"
    39  	"github.com/ethereum/go-ethereum/crypto"
    40  	"github.com/ethereum/go-ethereum/crypto/ecies"
    41  	"github.com/ethereum/go-ethereum/log"
    42  )
    43  
    44  //
    45  type MessageParams struct {
    46  	TTL      uint32
    47  	Src      *ecdsa.PrivateKey
    48  	Dst      *ecdsa.PublicKey
    49  	KeySym   []byte
    50  	Topic    TopicType
    51  	WorkTime uint32
    52  	PoW      float64
    53  	Payload  []byte
    54  	Padding  []byte
    55  }
    56  
    57  //
    58  //
    59  //
    60  type sentMessage struct {
    61  	Raw []byte
    62  }
    63  
    64  //
    65  //
    66  type ReceivedMessage struct {
    67  	Raw []byte
    68  
    69  	Payload   []byte
    70  	Padding   []byte
    71  	Signature []byte
    72  
    73  PoW   float64          //
    74  Sent  uint32           //
    75  TTL   uint32           //
    76  Src   *ecdsa.PublicKey //
    77  Dst   *ecdsa.PublicKey //
    78  	Topic TopicType
    79  
    80  SymKeyHash      common.Hash //
    81  EnvelopeHash    common.Hash //
    82  	EnvelopeVersion uint64
    83  }
    84  
    85  func isMessageSigned(flags byte) bool {
    86  	return (flags & signatureFlag) != 0
    87  }
    88  
    89  func (msg *ReceivedMessage) isSymmetricEncryption() bool {
    90  	return msg.SymKeyHash != common.Hash{}
    91  }
    92  
    93  func (msg *ReceivedMessage) isAsymmetricEncryption() bool {
    94  	return msg.Dst != nil
    95  }
    96  
    97  //
    98  func NewSentMessage(params *MessageParams) (*sentMessage, error) {
    99  	msg := sentMessage{}
   100  	msg.Raw = make([]byte, 1, len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit)
   101  msg.Raw[0] = 0 //
   102  	err := msg.appendPadding(params)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  	msg.Raw = append(msg.Raw, params.Payload...)
   107  	return &msg, nil
   108  }
   109  
   110  //
   111  func getSizeOfLength(b []byte) (sz int, err error) {
   112  sz = intSize(len(b))      //
   113  sz = intSize(len(b) + sz) //
   114  	if sz > 3 {
   115  		err = errors.New("oversized padding parameter")
   116  	}
   117  	return sz, err
   118  }
   119  
   120  //
   121  func intSize(i int) (s int) {
   122  	for s = 1; i >= 256; s++ {
   123  		i /= 256
   124  	}
   125  	return s
   126  }
   127  
   128  //
   129  //
   130  func (msg *sentMessage) appendPadding(params *MessageParams) error {
   131  	rawSize := len(params.Payload) + 1
   132  	if params.Src != nil {
   133  		rawSize += signatureLength
   134  	}
   135  	odd := rawSize % padSizeLimit
   136  
   137  	if len(params.Padding) != 0 {
   138  		padSize := len(params.Padding)
   139  		padLengthSize, err := getSizeOfLength(params.Padding)
   140  		if err != nil {
   141  			return err
   142  		}
   143  		totalPadSize := padSize + padLengthSize
   144  		buf := make([]byte, 8)
   145  		binary.LittleEndian.PutUint32(buf, uint32(totalPadSize))
   146  		buf = buf[:padLengthSize]
   147  		msg.Raw = append(msg.Raw, buf...)
   148  		msg.Raw = append(msg.Raw, params.Padding...)
   149  msg.Raw[0] |= byte(padLengthSize) //
   150  	} else if odd != 0 {
   151  		totalPadSize := padSizeLimit - odd
   152  		if totalPadSize > 255 {
   153  //
   154  //
   155  //
   156  			panic("please fix the padding algorithm before releasing new version")
   157  		}
   158  		buf := make([]byte, totalPadSize)
   159  		_, err := crand.Read(buf[1:])
   160  		if err != nil {
   161  			return err
   162  		}
   163  		if totalPadSize > 6 && !validateSymmetricKey(buf) {
   164  			return errors.New("failed to generate random padding of size " + strconv.Itoa(totalPadSize))
   165  		}
   166  		buf[0] = byte(totalPadSize)
   167  		msg.Raw = append(msg.Raw, buf...)
   168  msg.Raw[0] |= byte(0x1) //
   169  	}
   170  	return nil
   171  }
   172  
   173  //
   174  //
   175  func (msg *sentMessage) sign(key *ecdsa.PrivateKey) error {
   176  	if isMessageSigned(msg.Raw[0]) {
   177  //
   178  		log.Error("failed to sign the message: already signed")
   179  		return nil
   180  	}
   181  
   182  	msg.Raw[0] |= signatureFlag
   183  	hash := crypto.Keccak256(msg.Raw)
   184  	signature, err := crypto.Sign(hash, key)
   185  	if err != nil {
   186  msg.Raw[0] &= ^signatureFlag //
   187  		return err
   188  	}
   189  	msg.Raw = append(msg.Raw, signature...)
   190  	return nil
   191  }
   192  
   193  //
   194  func (msg *sentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error {
   195  	if !ValidatePublicKey(key) {
   196  		return errors.New("invalid public key provided for asymmetric encryption")
   197  	}
   198  	encrypted, err := ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), msg.Raw, nil, nil)
   199  	if err == nil {
   200  		msg.Raw = encrypted
   201  	}
   202  	return err
   203  }
   204  
   205  //
   206  //
   207  func (msg *sentMessage) encryptSymmetric(key []byte) (nonce []byte, err error) {
   208  	if !validateSymmetricKey(key) {
   209  		return nil, errors.New("invalid key provided for symmetric encryption")
   210  	}
   211  
   212  	block, err := aes.NewCipher(key)
   213  	if err != nil {
   214  		return nil, err
   215  	}
   216  	aesgcm, err := cipher.NewGCM(block)
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  
   221  //
   222  	nonce = make([]byte, aesgcm.NonceSize())
   223  	_, err = crand.Read(nonce)
   224  	if err != nil {
   225  		return nil, err
   226  	} else if !validateSymmetricKey(nonce) {
   227  		return nil, errors.New("crypto/rand failed to generate nonce")
   228  	}
   229  
   230  	msg.Raw = aesgcm.Seal(nil, nonce, msg.Raw, nil)
   231  	return nonce, nil
   232  }
   233  
   234  //
   235  func (msg *sentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) {
   236  	if options.TTL == 0 {
   237  		options.TTL = DefaultTTL
   238  	}
   239  	if options.Src != nil {
   240  		if err = msg.sign(options.Src); err != nil {
   241  			return nil, err
   242  		}
   243  	}
   244  	var nonce []byte
   245  	if options.Dst != nil {
   246  		err = msg.encryptAsymmetric(options.Dst)
   247  	} else if options.KeySym != nil {
   248  		nonce, err = msg.encryptSymmetric(options.KeySym)
   249  	} else {
   250  		err = errors.New("unable to encrypt the message: neither symmetric nor assymmetric key provided")
   251  	}
   252  	if err != nil {
   253  		return nil, err
   254  	}
   255  
   256  	envelope = NewEnvelope(options.TTL, options.Topic, nonce, msg)
   257  	if err = envelope.Seal(options); err != nil {
   258  		return nil, err
   259  	}
   260  	return envelope, nil
   261  }
   262  
   263  //
   264  //
   265  func (msg *ReceivedMessage) decryptSymmetric(key []byte, nonce []byte) error {
   266  	block, err := aes.NewCipher(key)
   267  	if err != nil {
   268  		return err
   269  	}
   270  	aesgcm, err := cipher.NewGCM(block)
   271  	if err != nil {
   272  		return err
   273  	}
   274  	if len(nonce) != aesgcm.NonceSize() {
   275  		log.Error("decrypting the message", "AES nonce size", len(nonce))
   276  		return errors.New("wrong AES nonce size")
   277  	}
   278  	decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil)
   279  	if err != nil {
   280  		return err
   281  	}
   282  	msg.Raw = decrypted
   283  	return nil
   284  }
   285  
   286  //
   287  func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
   288  	decrypted, err := ecies.ImportECDSA(key).Decrypt(msg.Raw, nil, nil)
   289  	if err == nil {
   290  		msg.Raw = decrypted
   291  	}
   292  	return err
   293  }
   294  
   295  //
   296  func (msg *ReceivedMessage) Validate() bool {
   297  	end := len(msg.Raw)
   298  	if end < 1 {
   299  		return false
   300  	}
   301  
   302  	if isMessageSigned(msg.Raw[0]) {
   303  		end -= signatureLength
   304  		if end <= 1 {
   305  			return false
   306  		}
   307  		msg.Signature = msg.Raw[end:]
   308  		msg.Src = msg.SigToPubKey()
   309  		if msg.Src == nil {
   310  			return false
   311  		}
   312  	}
   313  
   314  	padSize, ok := msg.extractPadding(end)
   315  	if !ok {
   316  		return false
   317  	}
   318  
   319  	msg.Payload = msg.Raw[1+padSize : end]
   320  	return true
   321  }
   322  
   323  //
   324  //
   325  //
   326  //
   327  func (msg *ReceivedMessage) extractPadding(end int) (int, bool) {
   328  	paddingSize := 0
   329  sz := int(msg.Raw[0] & paddingMask) //
   330  //
   331  	if sz != 0 {
   332  		paddingSize = int(bytesToUintLittleEndian(msg.Raw[1 : 1+sz]))
   333  		if paddingSize < sz || paddingSize+1 > end {
   334  			return 0, false
   335  		}
   336  		msg.Padding = msg.Raw[1+sz : 1+paddingSize]
   337  	}
   338  	return paddingSize, true
   339  }
   340  
   341  //
   342  func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey {
   343  defer func() { recover() }() //
   344  
   345  	pub, err := crypto.SigToPub(msg.hash(), msg.Signature)
   346  	if err != nil {
   347  		log.Error("failed to recover public key from signature", "err", err)
   348  		return nil
   349  	}
   350  	return pub
   351  }
   352  
   353  //
   354  func (msg *ReceivedMessage) hash() []byte {
   355  	if isMessageSigned(msg.Raw[0]) {
   356  		sz := len(msg.Raw) - signatureLength
   357  		return crypto.Keccak256(msg.Raw[:sz])
   358  	}
   359  	return crypto.Keccak256(msg.Raw)
   360  }