github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/swarm/pss/handshake_test.go (about)

     1  // Copyright 2018 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  // +build foo
    18  
    19  package pss
    20  
    21  import (
    22  	"strconv"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/ethereum/go-ethereum/swarm/log"
    28  )
    29  
    30  // asymmetrical key exchange between two directly connected peers
    31  // full address, partial address (8 bytes) and empty address
    32  func TestHandshake(t *testing.T) {
    33  	t.Run("32", testHandshake)
    34  	t.Run("8", testHandshake)
    35  	t.Run("0", testHandshake)
    36  }
    37  
    38  func testHandshake(t *testing.T) {
    39  
    40  	// how much of the address we will use
    41  	useHandshake = true
    42  	var addrsize int64
    43  	var err error
    44  	addrsizestring := strings.Split(t.Name(), "/")
    45  	addrsize, _ = strconv.ParseInt(addrsizestring[1], 10, 0)
    46  
    47  	// set up two nodes directly connected
    48  	// (we are not testing pss routing here)
    49  	clients, err := setupNetwork(2)
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	var topic string
    55  	err = clients[0].Call(&topic, "pss_stringToTopic", "foo:42")
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  
    60  	var loaddr string
    61  	err = clients[0].Call(&loaddr, "pss_baseAddr")
    62  	if err != nil {
    63  		t.Fatalf("rpc get node 1 baseaddr fail: %v", err)
    64  	}
    65  	// "0x" = 2 bytes + addrsize address bytes which in hex is 2x length
    66  	loaddr = loaddr[:2+(addrsize*2)]
    67  	var roaddr string
    68  	err = clients[1].Call(&roaddr, "pss_baseAddr")
    69  	if err != nil {
    70  		t.Fatalf("rpc get node 2 baseaddr fail: %v", err)
    71  	}
    72  	roaddr = roaddr[:2+(addrsize*2)]
    73  	log.Debug("addresses", "left", loaddr, "right", roaddr)
    74  
    75  	// retrieve public key from pss instance
    76  	// set this public key reciprocally
    77  	var lpubkey string
    78  	err = clients[0].Call(&lpubkey, "pss_getPublicKey")
    79  	if err != nil {
    80  		t.Fatalf("rpc get node 1 pubkey fail: %v", err)
    81  	}
    82  	var rpubkey string
    83  	err = clients[1].Call(&rpubkey, "pss_getPublicKey")
    84  	if err != nil {
    85  		t.Fatalf("rpc get node 2 pubkey fail: %v", err)
    86  	}
    87  
    88  	time.Sleep(time.Millisecond * 1000) // replace with hive healthy code
    89  
    90  	// give each node its peer's public key
    91  	err = clients[0].Call(nil, "pss_setPeerPublicKey", rpubkey, topic, roaddr)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	err = clients[1].Call(nil, "pss_setPeerPublicKey", lpubkey, topic, loaddr)
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  
   100  	// perform the handshake
   101  	// after this each side will have defaultSymKeyBufferCapacity symkeys each for in- and outgoing messages:
   102  	// L -> request 4 keys -> R
   103  	// L <- send 4 keys, request 4 keys <- R
   104  	// L -> send 4 keys -> R
   105  	// the call will fill the array with symkeys L needs for sending to R
   106  	err = clients[0].Call(nil, "pss_addHandshake", topic)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	err = clients[1].Call(nil, "pss_addHandshake", topic)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	var lhsendsymkeyids []string
   116  	err = clients[0].Call(&lhsendsymkeyids, "pss_handshake", rpubkey, topic, true, true)
   117  	if err != nil {
   118  		t.Fatal(err)
   119  	}
   120  
   121  	// make sure the r-node gets its keys
   122  	time.Sleep(time.Second)
   123  
   124  	// check if we have 6 outgoing keys stored, and they match what was received from R
   125  	var lsendsymkeyids []string
   126  	err = clients[0].Call(&lsendsymkeyids, "pss_getHandshakeKeys", rpubkey, topic, false, true)
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	m := 0
   131  	for _, hid := range lhsendsymkeyids {
   132  		for _, lid := range lsendsymkeyids {
   133  			if lid == hid {
   134  				m++
   135  			}
   136  		}
   137  	}
   138  	if m != defaultSymKeyCapacity {
   139  		t.Fatalf("buffer size mismatch, expected %d, have %d: %v", defaultSymKeyCapacity, m, lsendsymkeyids)
   140  	}
   141  
   142  	// check if in- and outgoing keys on l-node and r-node match up and are in opposite categories (l recv = r send, l send = r recv)
   143  	var rsendsymkeyids []string
   144  	err = clients[1].Call(&rsendsymkeyids, "pss_getHandshakeKeys", lpubkey, topic, false, true)
   145  	if err != nil {
   146  		t.Fatal(err)
   147  	}
   148  	var lrecvsymkeyids []string
   149  	err = clients[0].Call(&lrecvsymkeyids, "pss_getHandshakeKeys", rpubkey, topic, true, false)
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  	var rrecvsymkeyids []string
   154  	err = clients[1].Call(&rrecvsymkeyids, "pss_getHandshakeKeys", lpubkey, topic, true, false)
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	// get outgoing symkeys in byte form from both sides
   160  	var lsendsymkeys []string
   161  	for _, id := range lsendsymkeyids {
   162  		var key string
   163  		err = clients[0].Call(&key, "pss_getSymmetricKey", id)
   164  		if err != nil {
   165  			t.Fatal(err)
   166  		}
   167  		lsendsymkeys = append(lsendsymkeys, key)
   168  	}
   169  	var rsendsymkeys []string
   170  	for _, id := range rsendsymkeyids {
   171  		var key string
   172  		err = clients[1].Call(&key, "pss_getSymmetricKey", id)
   173  		if err != nil {
   174  			t.Fatal(err)
   175  		}
   176  		rsendsymkeys = append(rsendsymkeys, key)
   177  	}
   178  
   179  	// get incoming symkeys in byte form from both sides and compare
   180  	var lrecvsymkeys []string
   181  	for _, id := range lrecvsymkeyids {
   182  		var key string
   183  		err = clients[0].Call(&key, "pss_getSymmetricKey", id)
   184  		if err != nil {
   185  			t.Fatal(err)
   186  		}
   187  		match := false
   188  		for _, otherkey := range rsendsymkeys {
   189  			if otherkey == key {
   190  				match = true
   191  			}
   192  		}
   193  		if !match {
   194  			t.Fatalf("no match right send for left recv key %s", id)
   195  		}
   196  		lrecvsymkeys = append(lrecvsymkeys, key)
   197  	}
   198  	var rrecvsymkeys []string
   199  	for _, id := range rrecvsymkeyids {
   200  		var key string
   201  		err = clients[1].Call(&key, "pss_getSymmetricKey", id)
   202  		if err != nil {
   203  			t.Fatal(err)
   204  		}
   205  		match := false
   206  		for _, otherkey := range lsendsymkeys {
   207  			if otherkey == key {
   208  				match = true
   209  			}
   210  		}
   211  		if !match {
   212  			t.Fatalf("no match left send for right recv key %s", id)
   213  		}
   214  		rrecvsymkeys = append(rrecvsymkeys, key)
   215  	}
   216  
   217  	// send new handshake request, should send no keys
   218  	err = clients[0].Call(nil, "pss_handshake", rpubkey, topic, false)
   219  	if err == nil {
   220  		t.Fatal("expected full symkey buffer error")
   221  	}
   222  
   223  	// expire one key, send new handshake request
   224  	err = clients[0].Call(nil, "pss_releaseHandshakeKey", rpubkey, topic, lsendsymkeyids[0], true)
   225  	if err != nil {
   226  		t.Fatalf("release left send key %s fail: %v", lsendsymkeyids[0], err)
   227  	}
   228  
   229  	var newlhsendkeyids []string
   230  
   231  	// send new handshake request, should now receive one key
   232  	// check that it is not in previous right recv key array
   233  	err = clients[0].Call(&newlhsendkeyids, "pss_handshake", rpubkey, topic, true, false)
   234  	if err != nil {
   235  		t.Fatalf("handshake send fail: %v", err)
   236  	} else if len(newlhsendkeyids) != defaultSymKeyCapacity {
   237  		t.Fatalf("wrong receive count, expected 1, got %d", len(newlhsendkeyids))
   238  	}
   239  
   240  	var newlrecvsymkey string
   241  	err = clients[0].Call(&newlrecvsymkey, "pss_getSymmetricKey", newlhsendkeyids[0])
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	var rmatchsymkeyid *string
   246  	for i, id := range rrecvsymkeyids {
   247  		var key string
   248  		err = clients[1].Call(&key, "pss_getSymmetricKey", id)
   249  		if err != nil {
   250  			t.Fatal(err)
   251  		}
   252  		if newlrecvsymkey == key {
   253  			rmatchsymkeyid = &rrecvsymkeyids[i]
   254  		}
   255  	}
   256  	if rmatchsymkeyid != nil {
   257  		t.Fatalf("right sent old key id %s in second handshake", *rmatchsymkeyid)
   258  	}
   259  
   260  	// clean the pss core keystore. Should clean the key released earlier
   261  	var cleancount int
   262  	clients[0].Call(&cleancount, "psstest_clean")
   263  	if cleancount > 1 {
   264  		t.Fatalf("pss clean count mismatch; expected 1, got %d", cleancount)
   265  	}
   266  }