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