github.com/phillinzzz/newBsc@v1.1.6/p2p/rlpx/rlpx.go (about)

     1  // Copyright 2015 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  // Package rlpx implements the RLPx transport protocol.
    18  package rlpx
    19  
    20  import (
    21  	"bytes"
    22  	"crypto/aes"
    23  	"crypto/cipher"
    24  	"crypto/ecdsa"
    25  	"crypto/elliptic"
    26  	"crypto/hmac"
    27  	"crypto/rand"
    28  	"encoding/binary"
    29  	"errors"
    30  	"fmt"
    31  	"hash"
    32  	"io"
    33  	mrand "math/rand"
    34  	"net"
    35  	"time"
    36  
    37  	"github.com/VictoriaMetrics/fastcache"
    38  	"github.com/golang/snappy"
    39  	"github.com/oxtoacart/bpool"
    40  	"golang.org/x/crypto/sha3"
    41  
    42  	"github.com/phillinzzz/newBsc/crypto"
    43  	"github.com/phillinzzz/newBsc/crypto/ecies"
    44  	"github.com/phillinzzz/newBsc/rlp"
    45  )
    46  
    47  var snappyCache *fastcache.Cache
    48  
    49  func init() {
    50  	snappyCache = fastcache.New(50 * 1024 * 1024)
    51  }
    52  
    53  // Conn is an RLPx network connection. It wraps a low-level network connection. The
    54  // underlying connection should not be used for other activity when it is wrapped by Conn.
    55  //
    56  // Before sending messages, a handshake must be performed by calling the Handshake method.
    57  // This type is not generally safe for concurrent use, but reading and writing of messages
    58  // may happen concurrently after the handshake.
    59  type Conn struct {
    60  	dialDest  *ecdsa.PublicKey
    61  	conn      net.Conn
    62  	handshake *handshakeState
    63  	snappy    bool
    64  }
    65  
    66  type handshakeState struct {
    67  	enc cipher.Stream
    68  	dec cipher.Stream
    69  
    70  	macCipher  cipher.Block
    71  	egressMAC  hash.Hash
    72  	ingressMAC hash.Hash
    73  }
    74  
    75  // NewConn wraps the given network connection. If dialDest is non-nil, the connection
    76  // behaves as the initiator during the handshake.
    77  func NewConn(conn net.Conn, dialDest *ecdsa.PublicKey) *Conn {
    78  	return &Conn{
    79  		dialDest: dialDest,
    80  		conn:     conn,
    81  	}
    82  }
    83  
    84  // SetSnappy enables or disables snappy compression of messages. This is usually called
    85  // after the devp2p Hello message exchange when the negotiated version indicates that
    86  // compression is available on both ends of the connection.
    87  func (c *Conn) SetSnappy(snappy bool) {
    88  	c.snappy = snappy
    89  }
    90  
    91  // SetReadDeadline sets the deadline for all future read operations.
    92  func (c *Conn) SetReadDeadline(time time.Time) error {
    93  	return c.conn.SetReadDeadline(time)
    94  }
    95  
    96  // SetWriteDeadline sets the deadline for all future write operations.
    97  func (c *Conn) SetWriteDeadline(time time.Time) error {
    98  	return c.conn.SetWriteDeadline(time)
    99  }
   100  
   101  // SetDeadline sets the deadline for all future read and write operations.
   102  func (c *Conn) SetDeadline(time time.Time) error {
   103  	return c.conn.SetDeadline(time)
   104  }
   105  
   106  // Read reads a message from the connection.
   107  func (c *Conn) Read() (code uint64, data []byte, wireSize int, err error) {
   108  	if c.handshake == nil {
   109  		panic("can't ReadMsg before handshake")
   110  	}
   111  
   112  	frame, err := c.handshake.readFrame(c.conn)
   113  	if err != nil {
   114  		return 0, nil, 0, err
   115  	}
   116  	code, data, err = rlp.SplitUint64(frame)
   117  	if err != nil {
   118  		return 0, nil, 0, fmt.Errorf("invalid message code: %v", err)
   119  	}
   120  	wireSize = len(data)
   121  
   122  	// If snappy is enabled, verify and decompress message.
   123  	if c.snappy {
   124  		var actualSize int
   125  		actualSize, err = snappy.DecodedLen(data)
   126  		if err != nil {
   127  			return code, nil, 0, err
   128  		}
   129  		if actualSize > maxUint24 {
   130  			return code, nil, 0, errPlainMessageTooLarge
   131  		}
   132  		data, err = snappy.Decode(nil, data)
   133  	}
   134  	return code, data, wireSize, err
   135  }
   136  
   137  func (h *handshakeState) readFrame(conn io.Reader) ([]byte, error) {
   138  	// read the header
   139  	headbuf := make([]byte, 32)
   140  	if _, err := io.ReadFull(conn, headbuf); err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	// verify header mac
   145  	shouldMAC := updateMAC(h.ingressMAC, h.macCipher, headbuf[:16])
   146  	if !hmac.Equal(shouldMAC, headbuf[16:]) {
   147  		return nil, errors.New("bad header MAC")
   148  	}
   149  	h.dec.XORKeyStream(headbuf[:16], headbuf[:16]) // first half is now decrypted
   150  	fsize := readInt24(headbuf)
   151  	// ignore protocol type for now
   152  
   153  	// read the frame content
   154  	var rsize = fsize // frame size rounded up to 16 byte boundary
   155  	if padding := fsize % 16; padding > 0 {
   156  		rsize += 16 - padding
   157  	}
   158  	framebuf := make([]byte, rsize)
   159  	if _, err := io.ReadFull(conn, framebuf); err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	// read and validate frame MAC. we can re-use headbuf for that.
   164  	h.ingressMAC.Write(framebuf)
   165  	fmacseed := h.ingressMAC.Sum(nil)
   166  	if _, err := io.ReadFull(conn, headbuf[:16]); err != nil {
   167  		return nil, err
   168  	}
   169  	shouldMAC = updateMAC(h.ingressMAC, h.macCipher, fmacseed)
   170  	if !hmac.Equal(shouldMAC, headbuf[:16]) {
   171  		return nil, errors.New("bad frame MAC")
   172  	}
   173  
   174  	// decrypt frame content
   175  	h.dec.XORKeyStream(framebuf, framebuf)
   176  	return framebuf[:fsize], nil
   177  }
   178  
   179  // Write writes a message to the connection.
   180  //
   181  // Write returns the written size of the message data. This may be less than or equal to
   182  // len(data) depending on whether snappy compression is enabled.
   183  func (c *Conn) Write(code uint64, data []byte) (uint32, error) {
   184  	if c.handshake == nil {
   185  		panic("can't WriteMsg before handshake")
   186  	}
   187  	if len(data) > maxUint24 {
   188  		return 0, errPlainMessageTooLarge
   189  	}
   190  	if c.snappy {
   191  		if encodedResult, ok := snappyCache.HasGet(nil, data); ok {
   192  			data = encodedResult
   193  		} else {
   194  			encodedData := snappy.Encode(nil, data)
   195  			snappyCache.Set(data, encodedData)
   196  
   197  			data = encodedData
   198  		}
   199  	}
   200  
   201  	wireSize := uint32(len(data))
   202  	err := c.handshake.writeFrame(c.conn, code, data)
   203  	return wireSize, err
   204  }
   205  
   206  func (h *handshakeState) writeFrame(conn io.Writer, code uint64, data []byte) error {
   207  	ptype, _ := rlp.EncodeToBytes(code)
   208  
   209  	// write header
   210  	headbuf := make([]byte, 32)
   211  	fsize := len(ptype) + len(data)
   212  	if fsize > maxUint24 {
   213  		return errPlainMessageTooLarge
   214  	}
   215  	putInt24(uint32(fsize), headbuf)
   216  	copy(headbuf[3:], zeroHeader)
   217  	h.enc.XORKeyStream(headbuf[:16], headbuf[:16]) // first half is now encrypted
   218  
   219  	// write header MAC
   220  	copy(headbuf[16:], updateMAC(h.egressMAC, h.macCipher, headbuf[:16]))
   221  	if _, err := conn.Write(headbuf); err != nil {
   222  		return err
   223  	}
   224  
   225  	// write encrypted frame, updating the egress MAC hash with
   226  	// the data written to conn.
   227  	tee := cipher.StreamWriter{S: h.enc, W: io.MultiWriter(conn, h.egressMAC)}
   228  	if _, err := tee.Write(ptype); err != nil {
   229  		return err
   230  	}
   231  	if _, err := tee.Write(data); err != nil {
   232  		return err
   233  	}
   234  	if padding := fsize % 16; padding > 0 {
   235  		if _, err := tee.Write(zero16[:16-padding]); err != nil {
   236  			return err
   237  		}
   238  	}
   239  
   240  	// write frame MAC. egress MAC hash is up to date because
   241  	// frame content was written to it as well.
   242  	fmacseed := h.egressMAC.Sum(nil)
   243  	mac := updateMAC(h.egressMAC, h.macCipher, fmacseed)
   244  	_, err := conn.Write(mac)
   245  	return err
   246  }
   247  
   248  func readInt24(b []byte) uint32 {
   249  	return uint32(b[2]) | uint32(b[1])<<8 | uint32(b[0])<<16
   250  }
   251  
   252  func putInt24(v uint32, b []byte) {
   253  	b[0] = byte(v >> 16)
   254  	b[1] = byte(v >> 8)
   255  	b[2] = byte(v)
   256  }
   257  
   258  const BpoolMaxSize = 4
   259  
   260  var bytepool = bpool.NewBytePool(BpoolMaxSize, aes.BlockSize)
   261  
   262  // updateMAC reseeds the given hash with encrypted seed.
   263  // it returns the first 16 bytes of the hash sum after seeding.
   264  func updateMAC(mac hash.Hash, block cipher.Block, seed []byte) []byte {
   265  	aesbuf := bytepool.Get()
   266  	block.Encrypt(aesbuf, mac.Sum(nil))
   267  	for i := range aesbuf {
   268  		aesbuf[i] ^= seed[i]
   269  	}
   270  	mac.Write(aesbuf)
   271  	bytepool.Put(aesbuf)
   272  	return mac.Sum(nil)[:16]
   273  }
   274  
   275  // Handshake performs the handshake. This must be called before any data is written
   276  // or read from the connection.
   277  func (c *Conn) Handshake(prv *ecdsa.PrivateKey) (*ecdsa.PublicKey, error) {
   278  	var (
   279  		sec Secrets
   280  		err error
   281  	)
   282  	if c.dialDest != nil {
   283  		sec, err = initiatorEncHandshake(c.conn, prv, c.dialDest)
   284  	} else {
   285  		sec, err = receiverEncHandshake(c.conn, prv)
   286  	}
   287  	if err != nil {
   288  		return nil, err
   289  	}
   290  	c.InitWithSecrets(sec)
   291  	return sec.remote, err
   292  }
   293  
   294  // InitWithSecrets injects connection secrets as if a handshake had
   295  // been performed. This cannot be called after the handshake.
   296  func (c *Conn) InitWithSecrets(sec Secrets) {
   297  	if c.handshake != nil {
   298  		panic("can't handshake twice")
   299  	}
   300  	macc, err := aes.NewCipher(sec.MAC)
   301  	if err != nil {
   302  		panic("invalid MAC secret: " + err.Error())
   303  	}
   304  	encc, err := aes.NewCipher(sec.AES)
   305  	if err != nil {
   306  		panic("invalid AES secret: " + err.Error())
   307  	}
   308  	// we use an all-zeroes IV for AES because the key used
   309  	// for encryption is ephemeral.
   310  	iv := make([]byte, encc.BlockSize())
   311  	c.handshake = &handshakeState{
   312  		enc:        cipher.NewCTR(encc, iv),
   313  		dec:        cipher.NewCTR(encc, iv),
   314  		macCipher:  macc,
   315  		egressMAC:  sec.EgressMAC,
   316  		ingressMAC: sec.IngressMAC,
   317  	}
   318  }
   319  
   320  // Close closes the underlying network connection.
   321  func (c *Conn) Close() error {
   322  	return c.conn.Close()
   323  }
   324  
   325  // Constants for the handshake.
   326  const (
   327  	maxUint24 = int(^uint32(0) >> 8)
   328  
   329  	sskLen = 16                     // ecies.MaxSharedKeyLength(pubKey) / 2
   330  	sigLen = crypto.SignatureLength // elliptic S256
   331  	pubLen = 64                     // 512 bit pubkey in uncompressed representation without format byte
   332  	shaLen = 32                     // hash length (for nonce etc)
   333  
   334  	authMsgLen  = sigLen + shaLen + pubLen + shaLen + 1
   335  	authRespLen = pubLen + shaLen + 1
   336  
   337  	eciesOverhead = 65 /* pubkey */ + 16 /* IV */ + 32 /* MAC */
   338  
   339  	encAuthMsgLen  = authMsgLen + eciesOverhead  // size of encrypted pre-EIP-8 initiator handshake
   340  	encAuthRespLen = authRespLen + eciesOverhead // size of encrypted pre-EIP-8 handshake reply
   341  )
   342  
   343  var (
   344  	// this is used in place of actual frame header data.
   345  	// TODO: replace this when Msg contains the protocol type code.
   346  	zeroHeader = []byte{0xC2, 0x80, 0x80}
   347  	// sixteen zero bytes
   348  	zero16 = make([]byte, 16)
   349  
   350  	// errPlainMessageTooLarge is returned if a decompressed message length exceeds
   351  	// the allowed 24 bits (i.e. length >= 16MB).
   352  	errPlainMessageTooLarge = errors.New("message length >= 16MB")
   353  )
   354  
   355  // Secrets represents the connection secrets which are negotiated during the handshake.
   356  type Secrets struct {
   357  	AES, MAC              []byte
   358  	EgressMAC, IngressMAC hash.Hash
   359  	remote                *ecdsa.PublicKey
   360  }
   361  
   362  // encHandshake contains the state of the encryption handshake.
   363  type encHandshake struct {
   364  	initiator            bool
   365  	remote               *ecies.PublicKey  // remote-pubk
   366  	initNonce, respNonce []byte            // nonce
   367  	randomPrivKey        *ecies.PrivateKey // ecdhe-random
   368  	remoteRandomPub      *ecies.PublicKey  // ecdhe-random-pubk
   369  }
   370  
   371  // RLPx v4 handshake auth (defined in EIP-8).
   372  type authMsgV4 struct {
   373  	gotPlain bool // whether read packet had plain format.
   374  
   375  	Signature       [sigLen]byte
   376  	InitiatorPubkey [pubLen]byte
   377  	Nonce           [shaLen]byte
   378  	Version         uint
   379  
   380  	// Ignore additional fields (forward-compatibility)
   381  	Rest []rlp.RawValue `rlp:"tail"`
   382  }
   383  
   384  // RLPx v4 handshake response (defined in EIP-8).
   385  type authRespV4 struct {
   386  	RandomPubkey [pubLen]byte
   387  	Nonce        [shaLen]byte
   388  	Version      uint
   389  
   390  	// Ignore additional fields (forward-compatibility)
   391  	Rest []rlp.RawValue `rlp:"tail"`
   392  }
   393  
   394  // receiverEncHandshake negotiates a session token on conn.
   395  // it should be called on the listening side of the connection.
   396  //
   397  // prv is the local client's private key.
   398  func receiverEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey) (s Secrets, err error) {
   399  	authMsg := new(authMsgV4)
   400  	authPacket, err := readHandshakeMsg(authMsg, encAuthMsgLen, prv, conn)
   401  	if err != nil {
   402  		return s, err
   403  	}
   404  	h := new(encHandshake)
   405  	if err := h.handleAuthMsg(authMsg, prv); err != nil {
   406  		return s, err
   407  	}
   408  
   409  	authRespMsg, err := h.makeAuthResp()
   410  	if err != nil {
   411  		return s, err
   412  	}
   413  	var authRespPacket []byte
   414  	if authMsg.gotPlain {
   415  		authRespPacket, err = authRespMsg.sealPlain(h)
   416  	} else {
   417  		authRespPacket, err = sealEIP8(authRespMsg, h)
   418  	}
   419  	if err != nil {
   420  		return s, err
   421  	}
   422  	if _, err = conn.Write(authRespPacket); err != nil {
   423  		return s, err
   424  	}
   425  	return h.secrets(authPacket, authRespPacket)
   426  }
   427  
   428  func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) error {
   429  	// Import the remote identity.
   430  	rpub, err := importPublicKey(msg.InitiatorPubkey[:])
   431  	if err != nil {
   432  		return err
   433  	}
   434  	h.initNonce = msg.Nonce[:]
   435  	h.remote = rpub
   436  
   437  	// Generate random keypair for ECDH.
   438  	// If a private key is already set, use it instead of generating one (for testing).
   439  	if h.randomPrivKey == nil {
   440  		h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
   441  		if err != nil {
   442  			return err
   443  		}
   444  	}
   445  
   446  	// Check the signature.
   447  	token, err := h.staticSharedSecret(prv)
   448  	if err != nil {
   449  		return err
   450  	}
   451  	signedMsg := xor(token, h.initNonce)
   452  	remoteRandomPub, err := crypto.Ecrecover(signedMsg, msg.Signature[:])
   453  	if err != nil {
   454  		return err
   455  	}
   456  	h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
   457  	return nil
   458  }
   459  
   460  // secrets is called after the handshake is completed.
   461  // It extracts the connection secrets from the handshake values.
   462  func (h *encHandshake) secrets(auth, authResp []byte) (Secrets, error) {
   463  	ecdheSecret, err := h.randomPrivKey.GenerateShared(h.remoteRandomPub, sskLen, sskLen)
   464  	if err != nil {
   465  		return Secrets{}, err
   466  	}
   467  
   468  	// derive base secrets from ephemeral key agreement
   469  	sharedSecret := crypto.Keccak256(ecdheSecret, crypto.Keccak256(h.respNonce, h.initNonce))
   470  	aesSecret := crypto.Keccak256(ecdheSecret, sharedSecret)
   471  	s := Secrets{
   472  		remote: h.remote.ExportECDSA(),
   473  		AES:    aesSecret,
   474  		MAC:    crypto.Keccak256(ecdheSecret, aesSecret),
   475  	}
   476  
   477  	// setup sha3 instances for the MACs
   478  	mac1 := sha3.NewLegacyKeccak256()
   479  	mac1.Write(xor(s.MAC, h.respNonce))
   480  	mac1.Write(auth)
   481  	mac2 := sha3.NewLegacyKeccak256()
   482  	mac2.Write(xor(s.MAC, h.initNonce))
   483  	mac2.Write(authResp)
   484  	if h.initiator {
   485  		s.EgressMAC, s.IngressMAC = mac1, mac2
   486  	} else {
   487  		s.EgressMAC, s.IngressMAC = mac2, mac1
   488  	}
   489  
   490  	return s, nil
   491  }
   492  
   493  // staticSharedSecret returns the static shared secret, the result
   494  // of key agreement between the local and remote static node key.
   495  func (h *encHandshake) staticSharedSecret(prv *ecdsa.PrivateKey) ([]byte, error) {
   496  	return ecies.ImportECDSA(prv).GenerateShared(h.remote, sskLen, sskLen)
   497  }
   498  
   499  // initiatorEncHandshake negotiates a session token on conn.
   500  // it should be called on the dialing side of the connection.
   501  //
   502  // prv is the local client's private key.
   503  func initiatorEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, remote *ecdsa.PublicKey) (s Secrets, err error) {
   504  	h := &encHandshake{initiator: true, remote: ecies.ImportECDSAPublic(remote)}
   505  	authMsg, err := h.makeAuthMsg(prv)
   506  	if err != nil {
   507  		return s, err
   508  	}
   509  	authPacket, err := sealEIP8(authMsg, h)
   510  	if err != nil {
   511  		return s, err
   512  	}
   513  
   514  	if _, err = conn.Write(authPacket); err != nil {
   515  		return s, err
   516  	}
   517  
   518  	authRespMsg := new(authRespV4)
   519  	authRespPacket, err := readHandshakeMsg(authRespMsg, encAuthRespLen, prv, conn)
   520  	if err != nil {
   521  		return s, err
   522  	}
   523  	if err := h.handleAuthResp(authRespMsg); err != nil {
   524  		return s, err
   525  	}
   526  	return h.secrets(authPacket, authRespPacket)
   527  }
   528  
   529  // makeAuthMsg creates the initiator handshake message.
   530  func (h *encHandshake) makeAuthMsg(prv *ecdsa.PrivateKey) (*authMsgV4, error) {
   531  	// Generate random initiator nonce.
   532  	h.initNonce = make([]byte, shaLen)
   533  	_, err := rand.Read(h.initNonce)
   534  	if err != nil {
   535  		return nil, err
   536  	}
   537  	// Generate random keypair to for ECDH.
   538  	h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
   539  	if err != nil {
   540  		return nil, err
   541  	}
   542  
   543  	// Sign known message: static-shared-secret ^ nonce
   544  	token, err := h.staticSharedSecret(prv)
   545  	if err != nil {
   546  		return nil, err
   547  	}
   548  	signed := xor(token, h.initNonce)
   549  	signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA())
   550  	if err != nil {
   551  		return nil, err
   552  	}
   553  
   554  	msg := new(authMsgV4)
   555  	copy(msg.Signature[:], signature)
   556  	copy(msg.InitiatorPubkey[:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
   557  	copy(msg.Nonce[:], h.initNonce)
   558  	msg.Version = 4
   559  	return msg, nil
   560  }
   561  
   562  func (h *encHandshake) handleAuthResp(msg *authRespV4) (err error) {
   563  	h.respNonce = msg.Nonce[:]
   564  	h.remoteRandomPub, err = importPublicKey(msg.RandomPubkey[:])
   565  	return err
   566  }
   567  
   568  func (h *encHandshake) makeAuthResp() (msg *authRespV4, err error) {
   569  	// Generate random nonce.
   570  	h.respNonce = make([]byte, shaLen)
   571  	if _, err = rand.Read(h.respNonce); err != nil {
   572  		return nil, err
   573  	}
   574  
   575  	msg = new(authRespV4)
   576  	copy(msg.Nonce[:], h.respNonce)
   577  	copy(msg.RandomPubkey[:], exportPubkey(&h.randomPrivKey.PublicKey))
   578  	msg.Version = 4
   579  	return msg, nil
   580  }
   581  
   582  func (msg *authMsgV4) decodePlain(input []byte) {
   583  	n := copy(msg.Signature[:], input)
   584  	n += shaLen // skip sha3(initiator-ephemeral-pubk)
   585  	n += copy(msg.InitiatorPubkey[:], input[n:])
   586  	copy(msg.Nonce[:], input[n:])
   587  	msg.Version = 4
   588  	msg.gotPlain = true
   589  }
   590  
   591  func (msg *authRespV4) sealPlain(hs *encHandshake) ([]byte, error) {
   592  	buf := make([]byte, authRespLen)
   593  	n := copy(buf, msg.RandomPubkey[:])
   594  	copy(buf[n:], msg.Nonce[:])
   595  	return ecies.Encrypt(rand.Reader, hs.remote, buf, nil, nil)
   596  }
   597  
   598  func (msg *authRespV4) decodePlain(input []byte) {
   599  	n := copy(msg.RandomPubkey[:], input)
   600  	copy(msg.Nonce[:], input[n:])
   601  	msg.Version = 4
   602  }
   603  
   604  var padSpace = make([]byte, 300)
   605  
   606  func sealEIP8(msg interface{}, h *encHandshake) ([]byte, error) {
   607  	buf := new(bytes.Buffer)
   608  	if err := rlp.Encode(buf, msg); err != nil {
   609  		return nil, err
   610  	}
   611  	// pad with random amount of data. the amount needs to be at least 100 bytes to make
   612  	// the message distinguishable from pre-EIP-8 handshakes.
   613  	pad := padSpace[:mrand.Intn(len(padSpace)-100)+100]
   614  	buf.Write(pad)
   615  	prefix := make([]byte, 2)
   616  	binary.BigEndian.PutUint16(prefix, uint16(buf.Len()+eciesOverhead))
   617  
   618  	enc, err := ecies.Encrypt(rand.Reader, h.remote, buf.Bytes(), nil, prefix)
   619  	return append(prefix, enc...), err
   620  }
   621  
   622  type plainDecoder interface {
   623  	decodePlain([]byte)
   624  }
   625  
   626  func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r io.Reader) ([]byte, error) {
   627  	buf := make([]byte, plainSize)
   628  	if _, err := io.ReadFull(r, buf); err != nil {
   629  		return buf, err
   630  	}
   631  	// Attempt decoding pre-EIP-8 "plain" format.
   632  	key := ecies.ImportECDSA(prv)
   633  	if dec, err := key.Decrypt(buf, nil, nil); err == nil {
   634  		msg.decodePlain(dec)
   635  		return buf, nil
   636  	}
   637  	// Could be EIP-8 format, try that.
   638  	prefix := buf[:2]
   639  	size := binary.BigEndian.Uint16(prefix)
   640  	if size < uint16(plainSize) {
   641  		return buf, fmt.Errorf("size underflow, need at least %d bytes", plainSize)
   642  	}
   643  	buf = append(buf, make([]byte, size-uint16(plainSize)+2)...)
   644  	if _, err := io.ReadFull(r, buf[plainSize:]); err != nil {
   645  		return buf, err
   646  	}
   647  	dec, err := key.Decrypt(buf[2:], nil, prefix)
   648  	if err != nil {
   649  		return buf, err
   650  	}
   651  	// Can't use rlp.DecodeBytes here because it rejects
   652  	// trailing data (forward-compatibility).
   653  	s := rlp.NewStream(bytes.NewReader(dec), 0)
   654  	return buf, s.Decode(msg)
   655  }
   656  
   657  // importPublicKey unmarshals 512 bit public keys.
   658  func importPublicKey(pubKey []byte) (*ecies.PublicKey, error) {
   659  	var pubKey65 []byte
   660  	switch len(pubKey) {
   661  	case 64:
   662  		// add 'uncompressed key' flag
   663  		pubKey65 = append([]byte{0x04}, pubKey...)
   664  	case 65:
   665  		pubKey65 = pubKey
   666  	default:
   667  		return nil, fmt.Errorf("invalid public key length %v (expect 64/65)", len(pubKey))
   668  	}
   669  	// TODO: fewer pointless conversions
   670  	pub, err := crypto.UnmarshalPubkey(pubKey65)
   671  	if err != nil {
   672  		return nil, err
   673  	}
   674  	return ecies.ImportECDSAPublic(pub), nil
   675  }
   676  
   677  func exportPubkey(pub *ecies.PublicKey) []byte {
   678  	if pub == nil {
   679  		panic("nil pubkey")
   680  	}
   681  	return elliptic.Marshal(pub.Curve, pub.X, pub.Y)[1:]
   682  }
   683  
   684  func xor(one, other []byte) (xor []byte) {
   685  	xor = make([]byte, len(one))
   686  	for i := 0; i < len(one); i++ {
   687  		xor[i] = one[i] ^ other[i]
   688  	}
   689  	return xor
   690  }