github.com/core-coin/go-core/v2@v2.1.9/p2p/rlpx/rlpx.go (about)

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