github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/handshake.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 pss
    28  
    29  import (
    30  	"context"
    31  	"errors"
    32  	"fmt"
    33  	"sync"
    34  	"time"
    35  
    36  	"github.com/ethereum/go-ethereum/common"
    37  	"github.com/ethereum/go-ethereum/common/hexutil"
    38  	"github.com/ethereum/go-ethereum/crypto"
    39  	"github.com/ethereum/go-ethereum/p2p"
    40  	"github.com/ethereum/go-ethereum/rlp"
    41  	"github.com/ethereum/go-ethereum/rpc"
    42  	"github.com/ethereum/go-ethereum/swarm/log"
    43  )
    44  
    45  const (
    46  	IsActiveHandshake = true
    47  )
    48  
    49  var (
    50  	ctrlSingleton *HandshakeController
    51  )
    52  
    53  const (
    54  defaultSymKeyRequestTimeout = 1000 * 8  //
    55  defaultSymKeyExpiryTimeout  = 1000 * 10 //
    56  defaultSymKeySendLimit      = 256       //
    57  defaultSymKeyCapacity       = 4         //
    58  )
    59  
    60  //
    61  type handshakeMsg struct {
    62  	From    []byte
    63  	Limit   uint16
    64  	Keys    [][]byte
    65  	Request uint8
    66  	Topic   Topic
    67  }
    68  
    69  //
    70  type handshakeKey struct {
    71  	symKeyID  *string
    72  	pubKeyID  *string
    73  	limit     uint16
    74  	count     uint16
    75  	expiredAt time.Time
    76  }
    77  
    78  //
    79  //
    80  type handshake struct {
    81  	outKeys []handshakeKey
    82  	inKeys  []handshakeKey
    83  }
    84  
    85  //
    86  //
    87  //
    88  //
    89  //
    90  //
    91  //
    92  //
    93  //
    94  //
    95  type HandshakeParams struct {
    96  	SymKeyRequestTimeout time.Duration
    97  	SymKeyExpiryTimeout  time.Duration
    98  	SymKeySendLimit      uint16
    99  	SymKeyCapacity       uint8
   100  }
   101  
   102  //
   103  func NewHandshakeParams() *HandshakeParams {
   104  	return &HandshakeParams{
   105  		SymKeyRequestTimeout: defaultSymKeyRequestTimeout * time.Millisecond,
   106  		SymKeyExpiryTimeout:  defaultSymKeyExpiryTimeout * time.Millisecond,
   107  		SymKeySendLimit:      defaultSymKeySendLimit,
   108  		SymKeyCapacity:       defaultSymKeyCapacity,
   109  	}
   110  }
   111  
   112  //
   113  //
   114  type HandshakeController struct {
   115  	pss                  *Pss
   116  keyC                 map[string]chan []string //
   117  	lock                 sync.Mutex
   118  	symKeyRequestTimeout time.Duration
   119  	symKeyExpiryTimeout  time.Duration
   120  	symKeySendLimit      uint16
   121  	symKeyCapacity       uint8
   122  	symKeyIndex          map[string]*handshakeKey
   123  	handshakes           map[string]map[Topic]*handshake
   124  	deregisterFuncs      map[Topic]func()
   125  }
   126  
   127  //
   128  //
   129  //
   130  func SetHandshakeController(pss *Pss, params *HandshakeParams) error {
   131  	ctrl := &HandshakeController{
   132  		pss:                  pss,
   133  		keyC:                 make(map[string]chan []string),
   134  		symKeyRequestTimeout: params.SymKeyRequestTimeout,
   135  		symKeyExpiryTimeout:  params.SymKeyExpiryTimeout,
   136  		symKeySendLimit:      params.SymKeySendLimit,
   137  		symKeyCapacity:       params.SymKeyCapacity,
   138  		symKeyIndex:          make(map[string]*handshakeKey),
   139  		handshakes:           make(map[string]map[Topic]*handshake),
   140  		deregisterFuncs:      make(map[Topic]func()),
   141  	}
   142  	api := &HandshakeAPI{
   143  		namespace: "pss",
   144  		ctrl:      ctrl,
   145  	}
   146  	pss.addAPI(rpc.API{
   147  		Namespace: api.namespace,
   148  		Version:   "0.2",
   149  		Service:   api,
   150  		Public:    true,
   151  	})
   152  	ctrlSingleton = ctrl
   153  	return nil
   154  }
   155  
   156  //
   157  //
   158  func (ctl *HandshakeController) validKeys(pubkeyid string, topic *Topic, in bool) (validkeys []*string) {
   159  	ctl.lock.Lock()
   160  	defer ctl.lock.Unlock()
   161  	now := time.Now()
   162  	if _, ok := ctl.handshakes[pubkeyid]; !ok {
   163  		return []*string{}
   164  	} else if _, ok := ctl.handshakes[pubkeyid][*topic]; !ok {
   165  		return []*string{}
   166  	}
   167  	var keystore *[]handshakeKey
   168  	if in {
   169  		keystore = &(ctl.handshakes[pubkeyid][*topic].inKeys)
   170  	} else {
   171  		keystore = &(ctl.handshakes[pubkeyid][*topic].outKeys)
   172  	}
   173  
   174  	for _, key := range *keystore {
   175  		if key.limit <= key.count {
   176  			ctl.releaseKey(*key.symKeyID, topic)
   177  		} else if !key.expiredAt.IsZero() && key.expiredAt.Before(now) {
   178  			ctl.releaseKey(*key.symKeyID, topic)
   179  		} else {
   180  			validkeys = append(validkeys, key.symKeyID)
   181  		}
   182  	}
   183  	return
   184  }
   185  
   186  //
   187  //
   188  func (ctl *HandshakeController) updateKeys(pubkeyid string, topic *Topic, in bool, symkeyids []string, limit uint16) {
   189  	ctl.lock.Lock()
   190  	defer ctl.lock.Unlock()
   191  	if _, ok := ctl.handshakes[pubkeyid]; !ok {
   192  		ctl.handshakes[pubkeyid] = make(map[Topic]*handshake)
   193  
   194  	}
   195  	if ctl.handshakes[pubkeyid][*topic] == nil {
   196  		ctl.handshakes[pubkeyid][*topic] = &handshake{}
   197  	}
   198  	var keystore *[]handshakeKey
   199  	expire := time.Now()
   200  	if in {
   201  		keystore = &(ctl.handshakes[pubkeyid][*topic].inKeys)
   202  	} else {
   203  		keystore = &(ctl.handshakes[pubkeyid][*topic].outKeys)
   204  		expire = expire.Add(time.Millisecond * ctl.symKeyExpiryTimeout)
   205  	}
   206  	for _, storekey := range *keystore {
   207  		storekey.expiredAt = expire
   208  	}
   209  	for i := 0; i < len(symkeyids); i++ {
   210  		storekey := handshakeKey{
   211  			symKeyID: &symkeyids[i],
   212  			pubKeyID: &pubkeyid,
   213  			limit:    limit,
   214  		}
   215  		*keystore = append(*keystore, storekey)
   216  		ctl.pss.symKeyPool[*storekey.symKeyID][*topic].protected = true
   217  	}
   218  	for i := 0; i < len(*keystore); i++ {
   219  		ctl.symKeyIndex[*(*keystore)[i].symKeyID] = &((*keystore)[i])
   220  	}
   221  }
   222  
   223  //
   224  func (ctl *HandshakeController) releaseKey(symkeyid string, topic *Topic) bool {
   225  	if ctl.symKeyIndex[symkeyid] == nil {
   226  		log.Debug("no symkey", "symkeyid", symkeyid)
   227  		return false
   228  	}
   229  	ctl.symKeyIndex[symkeyid].expiredAt = time.Now()
   230  	log.Debug("handshake release", "symkeyid", symkeyid)
   231  	return true
   232  }
   233  
   234  //
   235  //
   236  //
   237  //
   238  //
   239  func (ctl *HandshakeController) cleanHandshake(pubkeyid string, topic *Topic, in bool, out bool) int {
   240  	ctl.lock.Lock()
   241  	defer ctl.lock.Unlock()
   242  	var deletecount int
   243  	var deletes []string
   244  	now := time.Now()
   245  	handshake := ctl.handshakes[pubkeyid][*topic]
   246  	log.Debug("handshake clean", "pubkey", pubkeyid, "topic", topic)
   247  	if in {
   248  		for i, key := range handshake.inKeys {
   249  			if key.expiredAt.Before(now) || (key.expiredAt.IsZero() && key.limit <= key.count) {
   250  				log.Trace("handshake in clean remove", "symkeyid", *key.symKeyID)
   251  				deletes = append(deletes, *key.symKeyID)
   252  				handshake.inKeys[deletecount] = handshake.inKeys[i]
   253  				deletecount++
   254  			}
   255  		}
   256  		handshake.inKeys = handshake.inKeys[:len(handshake.inKeys)-deletecount]
   257  	}
   258  	if out {
   259  		deletecount = 0
   260  		for i, key := range handshake.outKeys {
   261  			if key.expiredAt.Before(now) && (key.expiredAt.IsZero() && key.limit <= key.count) {
   262  				log.Trace("handshake out clean remove", "symkeyid", *key.symKeyID)
   263  				deletes = append(deletes, *key.symKeyID)
   264  				handshake.outKeys[deletecount] = handshake.outKeys[i]
   265  				deletecount++
   266  			}
   267  		}
   268  		handshake.outKeys = handshake.outKeys[:len(handshake.outKeys)-deletecount]
   269  	}
   270  	for _, keyid := range deletes {
   271  		delete(ctl.symKeyIndex, keyid)
   272  		ctl.pss.symKeyPool[keyid][*topic].protected = false
   273  	}
   274  	return len(deletes)
   275  }
   276  
   277  //
   278  func (ctl *HandshakeController) clean() {
   279  	peerpubkeys := ctl.handshakes
   280  	for pubkeyid, peertopics := range peerpubkeys {
   281  		for topic := range peertopics {
   282  			ctl.cleanHandshake(pubkeyid, &topic, true, true)
   283  		}
   284  	}
   285  }
   286  
   287  //
   288  //
   289  //
   290  //
   291  func (ctl *HandshakeController) handler(msg []byte, p *p2p.Peer, asymmetric bool, symkeyid string) error {
   292  	if !asymmetric {
   293  		if ctl.symKeyIndex[symkeyid] != nil {
   294  			if ctl.symKeyIndex[symkeyid].count >= ctl.symKeyIndex[symkeyid].limit {
   295  				return fmt.Errorf("discarding message using expired key: %s", symkeyid)
   296  			}
   297  			ctl.symKeyIndex[symkeyid].count++
   298  			log.Trace("increment symkey recv use", "symsymkeyid", symkeyid, "count", ctl.symKeyIndex[symkeyid].count, "limit", ctl.symKeyIndex[symkeyid].limit, "receiver", common.ToHex(crypto.FromECDSAPub(ctl.pss.PublicKey())))
   299  		}
   300  		return nil
   301  	}
   302  	keymsg := &handshakeMsg{}
   303  	err := rlp.DecodeBytes(msg, keymsg)
   304  	if err == nil {
   305  		err := ctl.handleKeys(symkeyid, keymsg)
   306  		if err != nil {
   307  			log.Error("handlekeys fail", "error", err)
   308  		}
   309  		return err
   310  	}
   311  	return nil
   312  }
   313  
   314  //
   315  //
   316  //
   317  //
   318  //
   319  //
   320  //
   321  //
   322  //
   323  //
   324  func (ctl *HandshakeController) handleKeys(pubkeyid string, keymsg *handshakeMsg) error {
   325  //
   326  	if len(keymsg.Keys) > 0 {
   327  		log.Debug("received handshake keys", "pubkeyid", pubkeyid, "from", keymsg.From, "count", len(keymsg.Keys))
   328  		var sendsymkeyids []string
   329  		for _, key := range keymsg.Keys {
   330  			sendsymkey := make([]byte, len(key))
   331  			copy(sendsymkey, key)
   332  			var address PssAddress
   333  			copy(address[:], keymsg.From)
   334  			sendsymkeyid, err := ctl.pss.setSymmetricKey(sendsymkey, keymsg.Topic, &address, false, false)
   335  			if err != nil {
   336  				return err
   337  			}
   338  			sendsymkeyids = append(sendsymkeyids, sendsymkeyid)
   339  		}
   340  		if len(sendsymkeyids) > 0 {
   341  			ctl.updateKeys(pubkeyid, &keymsg.Topic, false, sendsymkeyids, keymsg.Limit)
   342  
   343  			ctl.alertHandshake(pubkeyid, sendsymkeyids)
   344  		}
   345  	}
   346  
   347  //
   348  	if keymsg.Request > 0 {
   349  		_, err := ctl.sendKey(pubkeyid, &keymsg.Topic, keymsg.Request)
   350  		if err != nil {
   351  			return err
   352  		}
   353  	}
   354  
   355  	return nil
   356  }
   357  
   358  //
   359  //
   360  //
   361  //
   362  //
   363  //
   364  func (ctl *HandshakeController) sendKey(pubkeyid string, topic *Topic, keycount uint8) ([]string, error) {
   365  
   366  	var requestcount uint8
   367  	to := &PssAddress{}
   368  	if _, ok := ctl.pss.pubKeyPool[pubkeyid]; !ok {
   369  		return []string{}, errors.New("Invalid public key")
   370  	} else if psp, ok := ctl.pss.pubKeyPool[pubkeyid][*topic]; ok {
   371  		to = psp.address
   372  	}
   373  
   374  	recvkeys := make([][]byte, keycount)
   375  	recvkeyids := make([]string, keycount)
   376  	ctl.lock.Lock()
   377  	if _, ok := ctl.handshakes[pubkeyid]; !ok {
   378  		ctl.handshakes[pubkeyid] = make(map[Topic]*handshake)
   379  	}
   380  	ctl.lock.Unlock()
   381  
   382  //
   383  	outkeys := ctl.validKeys(pubkeyid, topic, false)
   384  	if len(outkeys) < int(ctl.symKeyCapacity) {
   385  //
   386  		requestcount = ctl.symKeyCapacity
   387  	}
   388  //
   389  	if requestcount == 0 && keycount == 0 {
   390  		return []string{}, nil
   391  	}
   392  
   393  //
   394  	for i := 0; i < len(recvkeyids); i++ {
   395  		var err error
   396  		recvkeyids[i], err = ctl.pss.GenerateSymmetricKey(*topic, to, true)
   397  		if err != nil {
   398  			return []string{}, fmt.Errorf("set receive symkey fail (pubkey %x topic %x): %v", pubkeyid, topic, err)
   399  		}
   400  		recvkeys[i], err = ctl.pss.GetSymmetricKey(recvkeyids[i])
   401  		if err != nil {
   402  			return []string{}, fmt.Errorf("GET Generated outgoing symkey fail (pubkey %x topic %x): %v", pubkeyid, topic, err)
   403  		}
   404  	}
   405  	ctl.updateKeys(pubkeyid, topic, true, recvkeyids, ctl.symKeySendLimit)
   406  
   407  //
   408  	recvkeymsg := &handshakeMsg{
   409  		From:    ctl.pss.BaseAddr(),
   410  		Keys:    recvkeys,
   411  		Request: requestcount,
   412  		Limit:   ctl.symKeySendLimit,
   413  		Topic:   *topic,
   414  	}
   415  	log.Debug("sending our symkeys", "pubkey", pubkeyid, "symkeys", recvkeyids, "limit", ctl.symKeySendLimit, "requestcount", requestcount, "keycount", len(recvkeys))
   416  	recvkeybytes, err := rlp.EncodeToBytes(recvkeymsg)
   417  	if err != nil {
   418  		return []string{}, fmt.Errorf("rlp keymsg encode fail: %v", err)
   419  	}
   420  //
   421  	err = ctl.pss.SendAsym(pubkeyid, *topic, recvkeybytes)
   422  	if err != nil {
   423  		return []string{}, fmt.Errorf("Send symkey failed: %v", err)
   424  	}
   425  	return recvkeyids, nil
   426  }
   427  
   428  //
   429  func (ctl *HandshakeController) alertHandshake(pubkeyid string, symkeys []string) chan []string {
   430  	if len(symkeys) > 0 {
   431  		if _, ok := ctl.keyC[pubkeyid]; ok {
   432  			ctl.keyC[pubkeyid] <- symkeys
   433  			close(ctl.keyC[pubkeyid])
   434  			delete(ctl.keyC, pubkeyid)
   435  		}
   436  		return nil
   437  	}
   438  	if _, ok := ctl.keyC[pubkeyid]; !ok {
   439  		ctl.keyC[pubkeyid] = make(chan []string)
   440  	}
   441  	return ctl.keyC[pubkeyid]
   442  }
   443  
   444  type HandshakeAPI struct {
   445  	namespace string
   446  	ctrl      *HandshakeController
   447  }
   448  
   449  //
   450  //
   451  //
   452  //
   453  //
   454  //
   455  //
   456  //
   457  //
   458  //
   459  //
   460  //
   461  //
   462  //
   463  func (api *HandshakeAPI) Handshake(pubkeyid string, topic Topic, sync bool, flush bool) (keys []string, err error) {
   464  	var hsc chan []string
   465  	var keycount uint8
   466  	if flush {
   467  		keycount = api.ctrl.symKeyCapacity
   468  	} else {
   469  		validkeys := api.ctrl.validKeys(pubkeyid, &topic, false)
   470  		keycount = api.ctrl.symKeyCapacity - uint8(len(validkeys))
   471  	}
   472  	if keycount == 0 {
   473  		return keys, errors.New("Incoming symmetric key store is already full")
   474  	}
   475  	if sync {
   476  		hsc = api.ctrl.alertHandshake(pubkeyid, []string{})
   477  	}
   478  	_, err = api.ctrl.sendKey(pubkeyid, &topic, keycount)
   479  	if err != nil {
   480  		return keys, err
   481  	}
   482  	if sync {
   483  		ctx, cancel := context.WithTimeout(context.Background(), api.ctrl.symKeyRequestTimeout)
   484  		defer cancel()
   485  		select {
   486  		case keys = <-hsc:
   487  			log.Trace("sync handshake response receive", "key", keys)
   488  		case <-ctx.Done():
   489  			return []string{}, errors.New("timeout")
   490  		}
   491  	}
   492  	return keys, nil
   493  }
   494  
   495  //
   496  func (api *HandshakeAPI) AddHandshake(topic Topic) error {
   497  	api.ctrl.deregisterFuncs[topic] = api.ctrl.pss.Register(&topic, api.ctrl.handler)
   498  	return nil
   499  }
   500  
   501  //
   502  func (api *HandshakeAPI) RemoveHandshake(topic *Topic) error {
   503  	if _, ok := api.ctrl.deregisterFuncs[*topic]; ok {
   504  		api.ctrl.deregisterFuncs[*topic]()
   505  	}
   506  	return nil
   507  }
   508  
   509  //
   510  //
   511  //
   512  //
   513  //
   514  //
   515  func (api *HandshakeAPI) GetHandshakeKeys(pubkeyid string, topic Topic, in bool, out bool) (keys []string, err error) {
   516  	if in {
   517  		for _, inkey := range api.ctrl.validKeys(pubkeyid, &topic, true) {
   518  			keys = append(keys, *inkey)
   519  		}
   520  	}
   521  	if out {
   522  		for _, outkey := range api.ctrl.validKeys(pubkeyid, &topic, false) {
   523  			keys = append(keys, *outkey)
   524  		}
   525  	}
   526  	return keys, nil
   527  }
   528  
   529  //
   530  //
   531  func (api *HandshakeAPI) GetHandshakeKeyCapacity(symkeyid string) (uint16, error) {
   532  	storekey := api.ctrl.symKeyIndex[symkeyid]
   533  	if storekey == nil {
   534  		return 0, fmt.Errorf("invalid symkey id %s", symkeyid)
   535  	}
   536  	return storekey.limit - storekey.count, nil
   537  }
   538  
   539  //
   540  //
   541  func (api *HandshakeAPI) GetHandshakePublicKey(symkeyid string) (string, error) {
   542  	storekey := api.ctrl.symKeyIndex[symkeyid]
   543  	if storekey == nil {
   544  		return "", fmt.Errorf("invalid symkey id %s", symkeyid)
   545  	}
   546  	return *storekey.pubKeyID, nil
   547  }
   548  
   549  //
   550  //
   551  //
   552  //
   553  //
   554  func (api *HandshakeAPI) ReleaseHandshakeKey(pubkeyid string, topic Topic, symkeyid string, flush bool) (removed bool, err error) {
   555  	removed = api.ctrl.releaseKey(symkeyid, &topic)
   556  	if removed && flush {
   557  		api.ctrl.cleanHandshake(pubkeyid, &topic, true, true)
   558  	}
   559  	return
   560  }
   561  
   562  //
   563  //
   564  //
   565  //
   566  func (api *HandshakeAPI) SendSym(symkeyid string, topic Topic, msg hexutil.Bytes) (err error) {
   567  	err = api.ctrl.pss.SendSym(symkeyid, topic, msg[:])
   568  	if api.ctrl.symKeyIndex[symkeyid] != nil {
   569  		if api.ctrl.symKeyIndex[symkeyid].count >= api.ctrl.symKeyIndex[symkeyid].limit {
   570  			return errors.New("attempted send with expired key")
   571  		}
   572  		api.ctrl.symKeyIndex[symkeyid].count++
   573  		log.Trace("increment symkey send use", "symkeyid", symkeyid, "count", api.ctrl.symKeyIndex[symkeyid].count, "limit", api.ctrl.symKeyIndex[symkeyid].limit, "receiver", common.ToHex(crypto.FromECDSAPub(api.ctrl.pss.PublicKey())))
   574  	}
   575  	return
   576  }