github.com/Cleverse/go-ethereum@v0.0.0-20220927095127-45113064e7f2/p2p/rlpx/rlpx.go (about)

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