github.com/annchain/OG@v0.0.9/p2p/rlpx_test.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 p2p
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/ecdsa"
    22  	"crypto/rand"
    23  	"encoding/hex"
    24  	"errors"
    25  	"fmt"
    26  	"github.com/annchain/OG/common/hexutil"
    27  	ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto"
    28  	msg2 "github.com/annchain/OG/types/msg"
    29  	"io"
    30  	"io/ioutil"
    31  	"net"
    32  	"reflect"
    33  	"strings"
    34  	"testing"
    35  	"time"
    36  
    37  	"github.com/annchain/OG/deprecated/ogcrypto/ecies"
    38  	"github.com/davecgh/go-spew/spew"
    39  	"golang.org/x/crypto/sha3"
    40  )
    41  
    42  func TestSharedSecret(t *testing.T) {
    43  	prv0, _ := ogcrypto2.GenerateKey() // = ecdsa.GenerateKey(ogcrypto.S256(), rand.Reader)
    44  	pub0 := &prv0.PublicKey
    45  	prv1, _ := ogcrypto2.GenerateKey()
    46  	pub1 := &prv1.PublicKey
    47  
    48  	ss0, err := ecies.ImportECDSA(prv0).GenerateShared(ecies.ImportECDSAPublic(pub1), sskLen, sskLen)
    49  	if err != nil {
    50  		return
    51  	}
    52  	ss1, err := ecies.ImportECDSA(prv1).GenerateShared(ecies.ImportECDSAPublic(pub0), sskLen, sskLen)
    53  	if err != nil {
    54  		return
    55  	}
    56  	t.Logf("Secret:\n%v %x\n%v %x", len(ss0), ss0, len(ss0), ss1)
    57  	if !bytes.Equal(ss0, ss1) {
    58  		t.Errorf("dont match :(")
    59  	}
    60  }
    61  
    62  func TestEncHandshake(t *testing.T) {
    63  	for i := 0; i < 10; i++ {
    64  		start := time.Now()
    65  		if err := testEncHandshake(nil); err != nil {
    66  			t.Fatalf("i=%d %v", i, err)
    67  		}
    68  		t.Logf("(without token) %d %v\n", i+1, time.Since(start))
    69  	}
    70  	for i := 0; i < 10; i++ {
    71  		tok := make([]byte, shaLen)
    72  		rand.Reader.Read(tok)
    73  		start := time.Now()
    74  		if err := testEncHandshake(tok); err != nil {
    75  			t.Fatalf("i=%d %v", i, err)
    76  		}
    77  		t.Logf("(with token) %d %v\n", i+1, time.Since(start))
    78  	}
    79  }
    80  
    81  func testEncHandshake(token []byte) error {
    82  	type result struct {
    83  		side   string
    84  		pubkey *ecdsa.PublicKey
    85  		err    error
    86  	}
    87  	var (
    88  		prv0, _  = ogcrypto2.GenerateKey()
    89  		prv1, _  = ogcrypto2.GenerateKey()
    90  		fd0, fd1 = net.Pipe()
    91  		c0, c1   = newRLPX(fd0).(*rlpx), newRLPX(fd1).(*rlpx)
    92  		output   = make(chan result)
    93  	)
    94  
    95  	go func() {
    96  		r := result{side: "initiator"}
    97  		defer func() { output <- r }()
    98  		defer fd0.Close()
    99  
   100  		r.pubkey, r.err = c0.doEncHandshake(prv0, &prv1.PublicKey)
   101  		if r.err != nil {
   102  			return
   103  		}
   104  		if !reflect.DeepEqual(r.pubkey, &prv1.PublicKey) {
   105  			r.err = fmt.Errorf("remote pubkey mismatch: got %v, want: %v", r.pubkey, &prv1.PublicKey)
   106  		}
   107  	}()
   108  	go func() {
   109  		r := result{side: "receiver"}
   110  		defer func() { output <- r }()
   111  		defer fd1.Close()
   112  
   113  		r.pubkey, r.err = c1.doEncHandshake(prv1, nil)
   114  		if r.err != nil {
   115  			return
   116  		}
   117  		if !reflect.DeepEqual(r.pubkey, &prv0.PublicKey) {
   118  			r.err = fmt.Errorf("remote ID mismatch: got %v, want: %v", r.pubkey, &prv0.PublicKey)
   119  		}
   120  	}()
   121  
   122  	// wait for results from both sides
   123  	r1, r2 := <-output, <-output
   124  	if r1.err != nil {
   125  		return fmt.Errorf("%s side error: %v", r1.side, r1.err)
   126  	}
   127  	if r2.err != nil {
   128  		return fmt.Errorf("%s side error: %v", r2.side, r2.err)
   129  	}
   130  
   131  	// compare derived secrets
   132  	if !reflect.DeepEqual(c0.rw.egressMAC, c1.rw.ingressMAC) {
   133  		return fmt.Errorf("egress mac mismatch:\n c0.rw: %#v\n c1.rw: %#v", c0.rw.egressMAC, c1.rw.ingressMAC)
   134  	}
   135  	if !reflect.DeepEqual(c0.rw.ingressMAC, c1.rw.egressMAC) {
   136  		return fmt.Errorf("ingress mac mismatch:\n c0.rw: %#v\n c1.rw: %#v", c0.rw.ingressMAC, c1.rw.egressMAC)
   137  	}
   138  	if !reflect.DeepEqual(c0.rw.enc, c1.rw.enc) {
   139  		return fmt.Errorf("enc cipher mismatch:\n c0.rw: %#v\n c1.rw: %#v", c0.rw.enc, c1.rw.enc)
   140  	}
   141  	if !reflect.DeepEqual(c0.rw.dec, c1.rw.dec) {
   142  		return fmt.Errorf("dec cipher mismatch:\n c0.rw: %#v\n c1.rw: %#v", c0.rw.dec, c1.rw.dec)
   143  	}
   144  	return nil
   145  }
   146  
   147  /*
   148  func TestProtocolHandshake(t *testing.T) {
   149  	var (
   150  		prv0, _ = ogcrypto.GenerateKey()
   151  		node0   = &discover.Node{ID: discover.PubkeyID(&prv0.PublicKey), IP: net.IP{1, 2, 3, 4}, TCP: 33}
   152  		hs0     = &protoHandshake{Version: 3, ID: node0.ID, Caps: []Cap{{"a", 0}, {"b", 2}}}
   153  
   154  		prv1, _ = ogcrypto.GenerateKey()
   155  		node1   = &discover.Node{ID: discover.PubkeyID(&prv1.PublicKey), IP: net.IP{5, 6, 7, 8}, TCP: 44}
   156  		hs1     = &protoHandshake{Version: 3, ID: node1.ID, Caps: []Cap{{"c", 1}, {"d", 3}}}
   157  
   158  		wg sync.WaitGroup
   159  	)
   160  
   161  	fd0, fd1, err := pipes.TCPPipe()
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  
   166  	wg.Add(2)
   167  	go func() {
   168  		defer wg.Done()
   169  		defer fd0.Close()
   170  		rlpx := newRLPX(fd0)
   171  		remid, err := rlpx.doEncHandshake(prv0, node1)
   172  		if err != nil {
   173  			t.Errorf("dial side enc handshake failed: %v", err)
   174  			return
   175  		}
   176  		if remid != node1.ID {
   177  			t.Errorf("dial side remote id mismatch: got %v, want %v", remid, node1.ID)
   178  			return
   179  		}
   180  
   181  		phs, err := rlpx.doProtoHandshake(hs0)
   182  		if err != nil {
   183  			t.Errorf("dial side proto handshake error: %v", err)
   184  			return
   185  		}
   186  		phs.Rest = nil
   187  		if !reflect.DeepEqual(phs, hs1) {
   188  			t.Errorf("dial side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs1))
   189  			return
   190  		}
   191  		rlpx.close(DiscQuitting)
   192  	}()
   193  	go func() {
   194  		defer wg.Done()
   195  		defer fd1.Close()
   196  		rlpx := newRLPX(fd1)
   197  		remid, err := rlpx.doEncHandshake(prv1, nil)
   198  		if err != nil {
   199  			t.Errorf("listen side enc handshake failed: %v", err)
   200  			return
   201  		}
   202  		if remid != node0.ID {
   203  			t.Errorf("listen side remote id mismatch: got %v, want %v", remid, node0.ID)
   204  			return
   205  		}
   206  
   207  		phs, err := rlpx.doProtoHandshake(hs1)
   208  		if err != nil {
   209  			t.Errorf("listen side proto handshake error: %v", err)
   210  			return
   211  		}
   212  		phs.Rest = nil
   213  		if !reflect.DeepEqual(phs, hs0) {
   214  			t.Errorf("listen side proto handshake mismatch:\ngot: %s\nwant: %s\n", spew.Sdump(phs), spew.Sdump(hs0))
   215  			return
   216  		}
   217  
   218  		if err := ExpectMsg(rlpx, discMsg, []DiscReason{DiscQuitting}); err != nil {
   219  			t.Errorf("error receiving disconnect: %v", err)
   220  		}
   221  	}()
   222  	wg.Wait()
   223  }
   224  */
   225  func TestProtocolHandshakeErrors(t *testing.T) {
   226  	our := &ProtoHandshake{Version: 3, Caps: []Cap{{"foo", 2}, {"bar", 3}}, Name: "quux"}
   227  	quitData, _ := DiscQuitting.MarshalMsg(nil)
   228  	pro := ProtoHandshake{Version: 3}
   229  	protoData, _ := pro.MarshalMsg(nil)
   230  	tests := []struct {
   231  		code MsgCodeType
   232  		//msg  interface{}
   233  		msg []byte
   234  		err error
   235  	}{
   236  		{
   237  			code: discMsg,
   238  			//msg:  []DiscReason{DiscQuitting},
   239  			msg: quitData,
   240  			err: DiscQuitting,
   241  		},
   242  		{
   243  			code: 0x9898,
   244  			msg:  []byte{1},
   245  			err:  errors.New("expected handshake, got 989898"),
   246  		},
   247  		{
   248  			code: handshakeMsg,
   249  			msg:  make([]byte, baseProtocolMaxMsgSize+2),
   250  			err:  errors.New("message too big"),
   251  		},
   252  		{
   253  			code: handshakeMsg,
   254  			msg:  []byte{1, 2, 3},
   255  			err:  newPeerError(errInvalidMsg, "(code 0) (size 3) msgp: attempted to decode type \"int\" with method for \"map\""),
   256  		},
   257  		{
   258  			code: handshakeMsg,
   259  			//msg:  &ProtoHandshake{Version: 3},
   260  			msg: protoData,
   261  			err: DiscInvalidIdentity,
   262  		},
   263  	}
   264  
   265  	for i, test := range tests {
   266  		p1, p2 := MsgPipe()
   267  		go Send(p1, test.code, test.msg)
   268  		_, err := readProtocolHandshake(p2, our)
   269  		if !reflect.DeepEqual(err, test.err) {
   270  			t.Errorf("test %d: error mismatch: got %q, want %q", i, err, test.err)
   271  		}
   272  	}
   273  }
   274  
   275  func TestRlpxFrameRW_ReadMsg(t *testing.T) {
   276  	buf := new(bytes.Buffer)
   277  	hash := fakeHash([]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})
   278  	rw := newRLPXFrameRW(buf, secrets{
   279  		AES:        ogcrypto2.Keccak256(),
   280  		MAC:        ogcrypto2.Keccak256(),
   281  		IngressMAC: hash,
   282  		EgressMAC:  hash,
   283  	})
   284  	golden := unhex(`0082bbdae471818bb0bfa6b551d1cb4201010101010101010101010101010101ba
   285  	62a6f3941e80e6674fccb640b769410ca260cb7b00
   286  	9e5b45d021af17dc638f146f174d0e5ff380abf27f3a87a6e4f101010101010101010101010101010101`)
   287  	// Check WriteMsg. This puts a message into the buffer.
   288  	a := msg2.Bytes(unhex("ba328a4ba590cb43f7848f41c438288500828ddae471818bb0bfa6b551d1cb42465456465485658686555555ab"))
   289  	b, _ := a.MarshalMsg(nil)
   290  	fmt.Println(hexutil.Encode(b), len(b))
   291  	if err := Send(rw, 8, b); err != nil {
   292  		t.Fatalf("WriteMsg error: %v", err)
   293  	}
   294  	var code MsgCodeType
   295  	code = 8
   296  	codeM, _ := code.MarshalMsg(nil)
   297  	fmt.Println(codeM, len(codeM))
   298  	written := buf.Bytes()
   299  	fmt.Println(len(written), hex.EncodeToString(written))
   300  	if !bytes.Equal(written, golden) {
   301  		t.Fatalf("output mismatch:\n  got:  %x\n  want: %x", written, golden)
   302  	}
   303  	// Check ReadMsg. It reads the message encoded by WriteMsg, which
   304  	// is equivalent to the golden message above.
   305  	msg, err := rw.ReadMsg()
   306  	if err != nil {
   307  		t.Fatalf("ReadMsg error: %v", err)
   308  	}
   309  	if msg.Size != 47 {
   310  		t.Errorf("msg size mismatch: got %d, want %d", msg.Size, 47)
   311  	}
   312  	fmt.Println("siez ", msg.Size)
   313  	if msg.Code != 8 {
   314  		t.Errorf("msg code mismatch: got %d, want %d", msg.Code, 8)
   315  	}
   316  	payload, _ := ioutil.ReadAll(msg.Payload)
   317  	wantPayload := unhex("c42dba328a4ba590cb43f7848f41c438288500828ddae471818bb0bfa6b551d1cb42465456465485658686555555ab")
   318  	if !bytes.Equal(payload, wantPayload) {
   319  		t.Errorf("msg payload mismatch:\ngot  %x\nwant %x", payload, wantPayload)
   320  	}
   321  }
   322  
   323  func TestRLPXFrameFake(t *testing.T) {
   324  	buf := new(bytes.Buffer)
   325  	hash := fakeHash([]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})
   326  	rw := newRLPXFrameRW(buf, secrets{
   327  		AES:        ogcrypto2.Keccak256(),
   328  		MAC:        ogcrypto2.Keccak256(),
   329  		IngressMAC: hash,
   330  		EgressMAC:  hash,
   331  	})
   332  
   333  	golden := unhex(`
   334  00828ddae471818bb0bfa6b551d1cb42
   335  01010101010101010101010101010101
   336  ba328a4ba590cb43f7848f41c4382885
   337  01010101010101010101010101010101
   338  `)
   339  
   340  	// Check WriteMsg. This puts a message into the buffer.
   341  	a := msg2.Uints{1, 2, 3, 4}
   342  	b, _ := a.MarshalMsg(nil)
   343  	if err := Send(rw, 8, b); err != nil {
   344  		t.Fatalf("WriteMsg error: %v", err)
   345  	}
   346  	written := buf.Bytes()
   347  	if !bytes.Equal(written, golden) {
   348  		t.Fatalf("output mismatch:\n  got:  %x\n  want: %x", written, golden)
   349  	}
   350  
   351  	// Check ReadMsg. It reads the message encoded by WriteMsg, which
   352  	// is equivalent to the golden message above.
   353  	msg, err := rw.ReadMsg()
   354  	if err != nil {
   355  		t.Fatalf("ReadMsg error: %v", err)
   356  	}
   357  	if msg.Size != 5 {
   358  		t.Errorf("msg size mismatch: got %d, want %d", msg.Size, 5)
   359  	}
   360  	if msg.Code != 8 {
   361  		t.Errorf("msg code mismatch: got %d, want %d", msg.Code, 8)
   362  	}
   363  	payload, _ := ioutil.ReadAll(msg.Payload)
   364  	wantPayload := unhex("9401020304")
   365  	if !bytes.Equal(payload, wantPayload) {
   366  		t.Errorf("msg payload mismatch:\ngot  %x\nwant %x", payload, wantPayload)
   367  	}
   368  }
   369  
   370  type fakeHash []byte
   371  
   372  func (fakeHash) Write(p []byte) (int, error) { return len(p), nil }
   373  func (fakeHash) Reset()                      {}
   374  func (fakeHash) BlockSize() int              { return 0 }
   375  
   376  func (h fakeHash) Size() int           { return len(h) }
   377  func (h fakeHash) Sum(b []byte) []byte { return append(b, h...) }
   378  
   379  func TestRLPXFrameRW(t *testing.T) {
   380  	var (
   381  		aesSecret      = make([]byte, 16)
   382  		macSecret      = make([]byte, 16)
   383  		egressMACinit  = make([]byte, 32)
   384  		ingressMACinit = make([]byte, 32)
   385  	)
   386  	for _, s := range [][]byte{aesSecret, macSecret, egressMACinit, ingressMACinit} {
   387  		rand.Read(s)
   388  	}
   389  	conn := new(bytes.Buffer)
   390  
   391  	s1 := secrets{
   392  		AES:        aesSecret,
   393  		MAC:        macSecret,
   394  		EgressMAC:  sha3.NewLagecyKeccak256()(),
   395  		IngressMAC: sha3.NewLegacyKeccak256(),
   396  	}
   397  	s1.EgressMAC.Write(egressMACinit)
   398  	s1.IngressMAC.Write(ingressMACinit)
   399  	rw1 := newRLPXFrameRW(conn, s1)
   400  
   401  	s2 := secrets{
   402  		AES:        aesSecret,
   403  		MAC:        macSecret,
   404  		EgressMAC:  sha3.NewLegacyKeccak256(),
   405  		IngressMAC: sha3.NewLegacyKeccak256(),
   406  	}
   407  	s2.EgressMAC.Write(ingressMACinit)
   408  	s2.IngressMAC.Write(egressMACinit)
   409  	rw2 := newRLPXFrameRW(conn, s2)
   410  
   411  	// send some messages
   412  	for i := 0; i < 10; i++ {
   413  		// write message into conn buffer
   414  		wmsg := msg2.Strings{"foo", "bar", strings.Repeat("test", i)}
   415  		b, _ := wmsg.MarshalMsg(nil)
   416  		err := Send(rw1, MsgCodeType(i), b)
   417  		if err != nil {
   418  			t.Fatalf("WriteMsg error (i=%d): %v", i, err)
   419  		}
   420  
   421  		// read message that rw1 just wrote
   422  		msg, err := rw2.ReadMsg()
   423  		if err != nil {
   424  			t.Fatalf("ReadMsg error (i=%d): %v", i, err)
   425  		}
   426  		if msg.Code != MsgCodeType(i) {
   427  			t.Fatalf("msg code mismatch: got %d, want %d", msg.Code, i)
   428  		}
   429  		payload, _ := ioutil.ReadAll(msg.Payload)
   430  		wantPayload, _ := wmsg.MarshalMsg(nil)
   431  		//wantPayload, _ := rlp.EncodeToBytes(wmsg)
   432  		if !bytes.Equal(payload, wantPayload) {
   433  			t.Fatalf("msg payload mismatch:\ngot  %x\nwant %x", payload, wantPayload)
   434  		}
   435  	}
   436  }
   437  
   438  type handshakeAuthTest struct {
   439  	input       string
   440  	isPlain     bool
   441  	wantVersion uint
   442  	wantRest    [][]byte
   443  }
   444  
   445  var eip8HandshakeAuthTests = []handshakeAuthTest{
   446  	// (Auth₁) RLPx v4 plain encoding
   447  	{
   448  		input: `
   449  			048ca79ad18e4b0659fab4853fe5bc58eb83992980f4c9cc147d2aa31532efd29a3d3dc6a3d89eaf
   450  			913150cfc777ce0ce4af2758bf4810235f6e6ceccfee1acc6b22c005e9e3a49d6448610a58e98744
   451  			ba3ac0399e82692d67c1f58849050b3024e21a52c9d3b01d871ff5f210817912773e610443a9ef14
   452  			2e91cdba0bd77b5fdf0769b05671fc35f83d83e4d3b0b000c6b2a1b1bba89e0fc51bf4e460df3105
   453  			c444f14be226458940d6061c296350937ffd5e3acaceeaaefd3c6f74be8e23e0f45163cc7ebd7622
   454  			0f0128410fd05250273156d548a414444ae2f7dea4dfca2d43c057adb701a715bf59f6fb66b2d1d2
   455  			0f2c703f851cbf5ac47396d9ca65b6260bd141ac4d53e2de585a73d1750780db4c9ee4cd4d225173
   456  			a4592ee77e2bd94d0be3691f3b406f9bba9b591fc63facc016bfa8
   457  		`,
   458  		isPlain:     true,
   459  		wantVersion: 4,
   460  	},
   461  	// (Auth₂) EIP-8 encoding
   462  	{
   463  		input: `
   464  		 01fd04e21891e689df83f64e0f6fd092c3060aeaebeae4abd52898524a6dde5167
   465  aeecce9bc44234c8953db2b084ee7f8f0773e43861469cc1021b2154aed092988d49ff079abe
   466  52b24069b344b08e0680dd0d388b53e2651f86259c91eaad261e09d5be94c070f91c0ae3cb1af
   467  fa11017aabdc223a5919596da1999260715eda05f3653623c05350fa7bf06dcde5a754066f8d4
   468  64a3fa99c47d50e0ff3b7b58ad43e85ceaca2646cc36206e0b0648b92604b6593559d202d1b294
   469  60af08d6818decf069118ded9eaabac157fa77494b90c23d94a3932694bbdd65abcfbe44000b
   470  1b5e19dec5345968756f7be241b614f239613bfd1b073d23f83bb9916013f02bd815800cdded
   471  09c429ced8526d0b433bf400e54eb30ec5ce9dc6f96a75dee773afbbb73d64ffc9dc5db4080a
   472  5571b3ad9122f67a24815e53d43522209606800d9ff8dd29411ce279d40ec12f202370356396
   473  62248f1ce553bab7b35aa13bd76a0ae435fc3515a5708b4f8f71af5bf96657e04d572850c6cb
   474  241fc2dccdfd4f9fc04ce5d53e6e502f2fc9477aabaa829ee26e2e2f377a434d5e2e6e6632b
   475  8100013c90c05828fa14e6dbc2d32a10eed51877ad5cf06396220bab227405f48dc725c2bc
   476  2281f762212dc192d672cb5bc3289ac50a0244c68d33f509d49d8789744464dc2909fffda0
   477  31155bad633ad7b30eb43263aa565c086f326a8cea4c5
   478  		`,
   479  		wantVersion: 4,
   480  		//wantRest:    [][]byte{},
   481  	},
   482  	// (Auth₃) RLPx v4 EIP-8 encoding with version 56, additional list elements
   483  	{
   484  		input: `
   485  		 020e0439c7b8803f6c8939c83ab2e024093a2ab2e5834512f47bf84aa33439f03539053a84cec7469803d
   486  		4edeeea66059be82d4fa0aa419d3ab77631c228f1936e27e57ce6c5dc9a785fd19892367ecb21a716fbf8d
   487       498280924d63c2b27977797ff71742fa9960f8e9f6571045c5a1e812644f541221aac59c5e27d5daba1f8119db944f
   488        1466d6c0e068bbd7621b18ec237be63ed26f0e5b664b3395d344a3c0c57d89653816329e9e2ffd79e01ce4b5614ea
   489        e80755e0aca3655eb3a435c1e7a443e0af36a9908b3dd076d01905d4c9224e0f941ebdd51e8d4
   490      7fb4f495ea88c928e176ced61917da8f18bcca3365970df65f357d099dc720fdaf4aa3aaaf779af0074425551c38222c2899353028d92bf
   491     ecf2b8003cf35d4bcc9ce2a25dcdc79d79cc0022835515938a59ee79bfbd78c6bef57fda03c0c42231783c7445015f247a248cdcd5a61a2
   492     e108929197d3e0e83bd6d2f025115fb21e890193b3c752880a6e1758e5ded5633d81de771f68659e77511b36bac3892868148a332c3d9fb
   493     1f6e060a94c10d6466ab43d44b7fde993aba6542a3d16ddbbf1308ff8b4ad04ec3b9856953931e3b18d15036deb415796fb3ec06cfb9341
   494      c0072a1d60d1f416b57fd7d7800ad6923b4497aeb3210f5af001f731c7c65a22b282eecfdc6da46fa9c482a22ffa9c86073a2caf2f4da1
   495           550fd79c43a03824a4932f032e8d3828844a02fab8eede2030c8d9fb0ea0a408699
   496  		`,
   497  		wantVersion: 56,
   498  		wantRest:    [][]byte{{0x01}, {0x02}, {0xC2, 0x04, 0x05}},
   499  	},
   500  }
   501  
   502  type handshakeAckTest struct {
   503  	input       string
   504  	wantVersion uint
   505  	wantRest    [][]byte
   506  }
   507  
   508  var eip8HandshakeRespTests = []handshakeAckTest{
   509  	// (Ack₁) RLPx v4 plain encoding
   510  	{
   511  		input: `
   512  			049f8abcfa9c0dc65b982e98af921bc0ba6e4243169348a236abe9df5f93aa69d99cadddaa387662
   513  			b0ff2c08e9006d5a11a278b1b3331e5aaabf0a32f01281b6f4ede0e09a2d5f585b26513cb794d963
   514  			5a57563921c04a9090b4f14ee42be1a5461049af4ea7a7f49bf4c97a352d39c8d02ee4acc416388c
   515  			1c66cec761d2bc1c72da6ba143477f049c9d2dde846c252c111b904f630ac98e51609b3b1f58168d
   516  			dca6505b7196532e5f85b259a20c45e1979491683fee108e9660edbf38f3add489ae73e3dda2c71b
   517  			d1497113d5c755e942d1
   518  		`,
   519  		wantVersion: 4,
   520  	},
   521  	// (Ack₂) EIP-8 encoding
   522  	{
   523  		input: `
   524  0197047250f566862bb97317b79c342e96f8b7ac4deedb677a687b6914dccdb7f283e0ae2ddff9efc799c8d0804ca6
   525  2fbc0681ae93d5e3d4fdbcf573e75bf0fb0237456335bccfeabb0de09cbab881fc055eb1a86b455df2fc0b75d88978
   526  9bb5c8887eed760079a6d0df3cee6947d3f58b6f7fb4a8999bb21bfbf218fdb06a43cc78d1bc48a513999860e8ea99
   527  ff3c1f5182fe89a4df4f3c5b3c578bdc4ec64334f09f78ee3158e6162da9515bb6dd30a9b9d48e78c5f2a6c076e212
   528  41b2a39ea04c439a3d9567ee27e76dc3b89484bf6305536a0485a5e4859c78370b315b57f9f72fd78e880bdbff1b13
   529  b4f750e0343056bed0190cab1da47af608d9fc6cc4f41f631b4a312e5541b89b57e5472407ba5543b1e624b266a597
   530  99a08595b0dbae70bde98718abe5bd361cb396f5e9fc0b04f0157cd9bf002075a27a4b7e86a6c8a6895831d4d366b3
   531  1204ef1112b53c1aac130a2a1477a952a3b346154f02cd609e90545a4e12a0df4f8a1cf39296ab2b319aa7d61952d6d9
   532  2f8173f5d8081e8c69e05ca50ec9e831bb3ce5301100ee9e975f0ef34db54a30
   533  		`,
   534  		wantVersion: 4,
   535  		//wantRest:    [][]byte{},
   536  	},
   537  	// (Ack₃) EIP-8 encoding with version 57, additional list elements
   538  	{
   539  		input: `
   540  			01b90454cd2aa35b7e6b4498bff8297dde8394fe1184cc72b4d09bfba53b5f23da6b7a265db5b6ff40e954f7
   541  f0fd4c4a5466ed7a1ac15d6d7904f8aafa9c3d965a84e405e7da79dd1150bd0b17036697a6dfcd6a36a5819b45a706a3955f
   542  bb247d9fb1d7a3fa2d93088d7d4f34f99a5dc889033251b953b41c4d3c89633947b0bdf836ea908d4e290db26b76b7d2a403
   543  25c3e54373d7a654cb6839cb42fccf815763db6800268a5609643cb43ff32f7e20ccfe2a448c726cf8196e4327a071abaee5
   544  255a6d9b42807e87a322d4dccd155ef9cd1f02ca38c5dc3a8cf12272247449e85760db4042ce08f94729a02c36bae454e99c
   545  ba0ec489dd9ebc747b41ae38854605bd40e92c758403dec8dbc3b76422970015f3a63b7fa5d077cfd353dc06a0d01263ad59
   546  da6da1acd564f9d4a062c5569e111950307f90cf594980cc0d5ee7daa1a85218c94759243a7a0510e32dc2ad4a23c4c201f7
   547  bab86a05baa126ce572b01d345f21c6011b9e2aebad983b3beaaa66c2a4c729012ca691b9fe38cbe2b97c0a7120b85fdcd27
   548  2343b4116b98a71d535b471bb61a704f553ba4bfb70dbd77f6226262ed90135b842c23ae152e84aac09feb991ba04aacbe
   549  		`,
   550  		wantVersion: 57,
   551  		wantRest:    [][]byte{{0x06}, {0xC2, 0x07, 0x08}, {0x81, 0xFA}},
   552  	},
   553  }
   554  
   555  func TestHandshakeForwardCompatibility(t *testing.T) {
   556  	var (
   557  		keyA, _       = ogcrypto2.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
   558  		keyB, _       = ogcrypto2.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
   559  		pubA          = ogcrypto2.FromECDSAPub(&keyA.PublicKey)[1:]
   560  		pubB          = ogcrypto2.FromECDSAPub(&keyB.PublicKey)[1:]
   561  		ephA, _       = ogcrypto2.HexToECDSA("869d6ecf5211f1cc60418a13b9d870b22959d0c16f02bec714c960dd2298a32d")
   562  		ephB, _       = ogcrypto2.HexToECDSA("e238eb8e04fee6511ab04c6dd3c89ce097b11f25d584863ac2b6d5b35b1847e4")
   563  		ephPubA       = ogcrypto2.FromECDSAPub(&ephA.PublicKey)[1:]
   564  		ephPubB       = ogcrypto2.FromECDSAPub(&ephB.PublicKey)[1:]
   565  		nonceA        = unhex("7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6")
   566  		nonceB        = unhex("559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd")
   567  		_, _, _, _    = pubA, pubB, ephPubA, ephPubB
   568  		authSignature = unhex("299ca6acfd35e3d72d8ba3d1e2b60b5561d5af5218eb5bc182045769eb4226910a301acae3b369fffc4a4899d6b02531e89fd4fe36a2cf0d93607ba470b50f7800")
   569  		_             = authSignature
   570  	)
   571  	makeAuth := func(test handshakeAuthTest) *AuthMsgV4 {
   572  		msg := &AuthMsgV4{Version: test.wantVersion, Rest: test.wantRest, gotPlain: test.isPlain}
   573  		copy(msg.Signature[:], authSignature)
   574  		copy(msg.InitiatorPubkey[:], pubA)
   575  		copy(msg.Nonce[:], nonceA)
   576  		return msg
   577  	}
   578  	makeAck := func(test handshakeAckTest) *AuthRespV4 {
   579  		msg := &AuthRespV4{Version: test.wantVersion, Rest: test.wantRest}
   580  		copy(msg.RandomPubkey[:], ephPubB)
   581  		copy(msg.Nonce[:], nonceB)
   582  		return msg
   583  	}
   584  
   585  	// check auth msg parsing
   586  	for _, test := range eip8HandshakeAuthTests {
   587  		r := bytes.NewReader(unhex(test.input))
   588  		msg := new(AuthMsgV4)
   589  		/*
   590  			var someText []byte
   591  			msg2 := makeAuth(test)
   592  			pub_b:=  ecies.ImportECDSAPublic(&keyB.PublicKey)
   593  			if !msg2.gotPlain{
   594  				someText,_= preEip8test(msg2,pub_b)
   595  				r2 := bytes.NewReader(someText)
   596  				fmt.Println(r2.Size())
   597  			}
   598  
   599  		*/
   600  		ciphertext, err := readHandshakeMsg(msg, encAuthMsgLen, keyB, r)
   601  		if err != nil {
   602  			t.Errorf("error for input %x:\n  %v ", unhex(test.input), err)
   603  			continue
   604  		}
   605  		if !bytes.Equal(ciphertext, unhex(test.input)) {
   606  			t.Errorf("wrong ciphertext for input %x:\n  %x", unhex(test.input), ciphertext)
   607  		}
   608  		want := makeAuth(test)
   609  		if !reflect.DeepEqual(msg, want) {
   610  			t.Errorf("wrong msg for input %x:\ngot %s\nwant %s", unhex(test.input), spew.Sdump(msg), spew.Sdump(want))
   611  			fmt.Println(msg.Version != want.Version, msg.gotPlain)
   612  		}
   613  	}
   614  
   615  	// check auth resp parsing
   616  	for _, test := range eip8HandshakeRespTests {
   617  		input := unhex(test.input)
   618  		r := bytes.NewReader(input)
   619  		msg := new(AuthRespV4)
   620  		/*
   621  			var someText []byte
   622  			msg2 := makeAck(test)
   623  			pub_a:=  ecies.ImportECDSAPublic(&keyA.PublicKey)
   624  
   625  				someText,_= preEip8Resptest(msg2,pub_a)
   626  				r = bytes.NewReader(someText)
   627  				fmt.Println(r.Size())
   628  
   629  		*/
   630  		ciphertext, err := readHandshakeMsgResp(msg, encAuthRespLen, keyA, r)
   631  		if err != nil {
   632  			t.Errorf("error for input %x:\n  %v", input, err)
   633  			continue
   634  		}
   635  		if !bytes.Equal(ciphertext, input) {
   636  			t.Errorf("wrong ciphertext for input %x:\n  %x", input, ciphertext)
   637  		}
   638  		want := makeAck(test)
   639  		if !reflect.DeepEqual(msg, want) {
   640  			t.Errorf("wrong msg for input %x:\ngot %s\nwant %s", input, spew.Sdump(msg), spew.Sdump(want))
   641  		}
   642  	}
   643  
   644  	// check derivation for (Auth₂, Ack₂) on recipient side
   645  	var (
   646  		hs = &encHandshake{
   647  			initiator:     false,
   648  			respNonce:     nonceB,
   649  			randomPrivKey: ecies.ImportECDSA(ephB),
   650  		}
   651  		authCiphertext     = unhex(eip8HandshakeAuthTests[1].input)
   652  		authRespCiphertext = unhex(eip8HandshakeRespTests[1].input)
   653  		authMsg            = makeAuth(eip8HandshakeAuthTests[1])
   654  		wantAES            = unhex("80e8632c05fed6fc2a13b0f8d31a3cf645366239170ea067065aba8e28bac487")
   655  		wantMAC            = unhex("2ea74ec5dae199227dff1af715362700e989d889d7a493cb0639691efb8e5f98")
   656  		//wantFooIngressHash = unhex("0c7ec6340062cc46f5e9f1e3cf86f8c8c403c5a0964f5df0ebd34a75ddc86db5")
   657  		wantFooIngressHash = unhex("d402a923042e8aab1f01f0783c343d574d3a0d70872e874168ea4d6174129e77")
   658  	)
   659  	if err := hs.handleAuthMsg(authMsg, keyB); err != nil {
   660  		t.Fatalf("handleAuthMsg: %v", err)
   661  	}
   662  	derived, err := hs.secrets(authCiphertext, authRespCiphertext)
   663  	if err != nil {
   664  		t.Fatalf("secrets: %v", err)
   665  	}
   666  	if !bytes.Equal(derived.AES, wantAES) {
   667  		t.Errorf("aes-secret mismatch:\ngot %x\nwant %x", derived.AES, wantAES)
   668  	}
   669  	if !bytes.Equal(derived.MAC, wantMAC) {
   670  		t.Errorf("mac-secret mismatch:\ngot %x\nwant %x", derived.MAC, wantMAC)
   671  	}
   672  	io.WriteString(derived.IngressMAC, "foo")
   673  	fooIngressHash := derived.IngressMAC.Sum(nil)
   674  	if !bytes.Equal(fooIngressHash, wantFooIngressHash) {
   675  		t.Errorf("ingress-mac('foo') mismatch:\ngot %x\nwant %x", fooIngressHash, wantFooIngressHash)
   676  	}
   677  }