github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/network/p2p/rlpx.go (about) 1 package p2p 2 3 import ( 4 "bytes" 5 "crypto/aes" 6 "crypto/cipher" 7 "crypto/ecdsa" 8 "crypto/elliptic" 9 "crypto/hmac" 10 "crypto/rand" 11 "encoding/binary" 12 "errors" 13 "fmt" 14 "hash" 15 "io" 16 "io/ioutil" 17 mrand "math/rand" 18 "net" 19 "sync" 20 "time" 21 22 "github.com/golang/snappy" 23 "github.com/neatio-net/neatio/network/p2p/discover" 24 "github.com/neatio-net/neatio/utilities/crypto" 25 "github.com/neatio-net/neatio/utilities/crypto/ecies" 26 "github.com/neatio-net/neatio/utilities/crypto/secp256k1" 27 "github.com/neatio-net/neatio/utilities/rlp" 28 "golang.org/x/crypto/sha3" 29 ) 30 31 const ( 32 maxUint24 = ^uint32(0) >> 8 33 34 sskLen = 16 35 sigLen = 65 36 pubLen = 64 37 shaLen = 32 38 39 authMsgLen = sigLen + shaLen + pubLen + shaLen + 1 40 authRespLen = pubLen + shaLen + 1 41 42 eciesOverhead = 65 + 16 + 32 43 44 encAuthMsgLen = authMsgLen + eciesOverhead 45 encAuthRespLen = authRespLen + eciesOverhead 46 47 handshakeTimeout = 5 * time.Second 48 49 discWriteTimeout = 1 * time.Second 50 ) 51 52 var errPlainMessageTooLarge = errors.New("message length >= 16MB") 53 54 type rlpx struct { 55 fd net.Conn 56 57 rmu, wmu sync.Mutex 58 rw *rlpxFrameRW 59 } 60 61 func newRLPX(fd net.Conn) transport { 62 fd.SetDeadline(time.Now().Add(handshakeTimeout)) 63 return &rlpx{fd: fd} 64 } 65 66 func (t *rlpx) ReadMsg() (Msg, error) { 67 t.rmu.Lock() 68 defer t.rmu.Unlock() 69 t.fd.SetReadDeadline(time.Now().Add(frameReadTimeout)) 70 return t.rw.ReadMsg() 71 } 72 73 func (t *rlpx) WriteMsg(msg Msg) error { 74 t.wmu.Lock() 75 defer t.wmu.Unlock() 76 t.fd.SetWriteDeadline(time.Now().Add(frameWriteTimeout)) 77 return t.rw.WriteMsg(msg) 78 } 79 80 func (t *rlpx) close(err error) { 81 t.wmu.Lock() 82 defer t.wmu.Unlock() 83 84 if t.rw != nil { 85 if r, ok := err.(DiscReason); ok && r != DiscNetworkError { 86 87 if err := t.fd.SetWriteDeadline(time.Now().Add(discWriteTimeout)); err == nil { 88 SendItems(t.rw, discMsg, r) 89 } 90 } 91 } 92 t.fd.Close() 93 } 94 95 func (t *rlpx) doProtoHandshake(our *protoHandshake) (their *protoHandshake, err error) { 96 97 werr := make(chan error, 1) 98 go func() { werr <- Send(t.rw, handshakeMsg, our) }() 99 if their, err = readProtocolHandshake(t.rw, our); err != nil { 100 <-werr 101 return nil, err 102 } 103 if err := <-werr; err != nil { 104 return nil, fmt.Errorf("write error: %v", err) 105 } 106 107 t.rw.snappy = their.Version >= snappyProtocolVersion 108 109 return their, nil 110 } 111 112 func readProtocolHandshake(rw MsgReader, our *protoHandshake) (*protoHandshake, error) { 113 msg, err := rw.ReadMsg() 114 if err != nil { 115 return nil, err 116 } 117 if msg.Size > baseProtocolMaxMsgSize { 118 return nil, fmt.Errorf("message too big") 119 } 120 if msg.Code == discMsg { 121 122 var reason [1]DiscReason 123 rlp.Decode(msg.Payload, &reason) 124 return nil, reason[0] 125 } 126 if msg.Code != handshakeMsg { 127 return nil, fmt.Errorf("expected handshake, got %x", msg.Code) 128 } 129 var hs protoHandshake 130 if err := msg.Decode(&hs); err != nil { 131 return nil, err 132 } 133 if (hs.ID == discover.NodeID{}) { 134 return nil, DiscInvalidIdentity 135 } 136 return &hs, nil 137 } 138 139 func (t *rlpx) doEncHandshake(prv *ecdsa.PrivateKey, dial *discover.Node) (discover.NodeID, error) { 140 var ( 141 sec secrets 142 err error 143 ) 144 if dial == nil { 145 sec, err = receiverEncHandshake(t.fd, prv, nil) 146 } else { 147 sec, err = initiatorEncHandshake(t.fd, prv, dial.ID, nil) 148 } 149 if err != nil { 150 return discover.NodeID{}, err 151 } 152 t.wmu.Lock() 153 t.rw = newRLPXFrameRW(t.fd, sec) 154 t.wmu.Unlock() 155 return sec.RemoteID, nil 156 } 157 158 type encHandshake struct { 159 initiator bool 160 remoteID discover.NodeID 161 162 remotePub *ecies.PublicKey 163 initNonce, respNonce []byte 164 randomPrivKey *ecies.PrivateKey 165 remoteRandomPub *ecies.PublicKey 166 } 167 168 type secrets struct { 169 RemoteID discover.NodeID 170 AES, MAC []byte 171 EgressMAC, IngressMAC hash.Hash 172 Token []byte 173 } 174 175 type authMsgV4 struct { 176 gotPlain bool 177 178 Signature [sigLen]byte 179 InitiatorPubkey [pubLen]byte 180 Nonce [shaLen]byte 181 Version uint 182 183 Rest []rlp.RawValue `rlp:"tail"` 184 } 185 186 type authRespV4 struct { 187 RandomPubkey [pubLen]byte 188 Nonce [shaLen]byte 189 Version uint 190 191 Rest []rlp.RawValue `rlp:"tail"` 192 } 193 194 func (h *encHandshake) secrets(auth, authResp []byte) (secrets, error) { 195 ecdheSecret, err := h.randomPrivKey.GenerateShared(h.remoteRandomPub, sskLen, sskLen) 196 if err != nil { 197 return secrets{}, err 198 } 199 200 sharedSecret := crypto.Keccak256(ecdheSecret, crypto.Keccak256(h.respNonce, h.initNonce)) 201 aesSecret := crypto.Keccak256(ecdheSecret, sharedSecret) 202 s := secrets{ 203 RemoteID: h.remoteID, 204 AES: aesSecret, 205 MAC: crypto.Keccak256(ecdheSecret, aesSecret), 206 } 207 208 mac1 := sha3.NewLegacyKeccak256() 209 mac1.Write(xor(s.MAC, h.respNonce)) 210 mac1.Write(auth) 211 mac2 := sha3.NewLegacyKeccak256() 212 mac2.Write(xor(s.MAC, h.initNonce)) 213 mac2.Write(authResp) 214 if h.initiator { 215 s.EgressMAC, s.IngressMAC = mac1, mac2 216 } else { 217 s.EgressMAC, s.IngressMAC = mac2, mac1 218 } 219 220 return s, nil 221 } 222 223 func (h *encHandshake) staticSharedSecret(prv *ecdsa.PrivateKey) ([]byte, error) { 224 return ecies.ImportECDSA(prv).GenerateShared(h.remotePub, sskLen, sskLen) 225 } 226 227 func initiatorEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, remoteID discover.NodeID, token []byte) (s secrets, err error) { 228 h := &encHandshake{initiator: true, remoteID: remoteID} 229 authMsg, err := h.makeAuthMsg(prv, token) 230 if err != nil { 231 return s, err 232 } 233 authPacket, err := sealEIP8(authMsg, h) 234 if err != nil { 235 return s, err 236 } 237 if _, err = conn.Write(authPacket); err != nil { 238 return s, err 239 } 240 241 authRespMsg := new(authRespV4) 242 authRespPacket, err := readHandshakeMsg(authRespMsg, encAuthRespLen, prv, conn) 243 if err != nil { 244 return s, err 245 } 246 if err := h.handleAuthResp(authRespMsg); err != nil { 247 return s, err 248 } 249 return h.secrets(authPacket, authRespPacket) 250 } 251 252 func (h *encHandshake) makeAuthMsg(prv *ecdsa.PrivateKey, token []byte) (*authMsgV4, error) { 253 rpub, err := h.remoteID.Pubkey() 254 if err != nil { 255 return nil, fmt.Errorf("bad remoteID: %v", err) 256 } 257 h.remotePub = ecies.ImportECDSAPublic(rpub) 258 259 h.initNonce = make([]byte, shaLen) 260 if _, err := rand.Read(h.initNonce); err != nil { 261 return nil, err 262 } 263 264 h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil) 265 if err != nil { 266 return nil, err 267 } 268 269 token, err = h.staticSharedSecret(prv) 270 if err != nil { 271 return nil, err 272 } 273 signed := xor(token, h.initNonce) 274 signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA()) 275 if err != nil { 276 return nil, err 277 } 278 279 msg := new(authMsgV4) 280 copy(msg.Signature[:], signature) 281 copy(msg.InitiatorPubkey[:], crypto.FromECDSAPub(&prv.PublicKey)[1:]) 282 copy(msg.Nonce[:], h.initNonce) 283 msg.Version = 4 284 return msg, nil 285 } 286 287 func (h *encHandshake) handleAuthResp(msg *authRespV4) (err error) { 288 h.respNonce = msg.Nonce[:] 289 h.remoteRandomPub, err = importPublicKey(msg.RandomPubkey[:]) 290 return err 291 } 292 293 func receiverEncHandshake(conn io.ReadWriter, prv *ecdsa.PrivateKey, token []byte) (s secrets, err error) { 294 authMsg := new(authMsgV4) 295 authPacket, err := readHandshakeMsg(authMsg, encAuthMsgLen, prv, conn) 296 if err != nil { 297 return s, err 298 } 299 h := new(encHandshake) 300 if err := h.handleAuthMsg(authMsg, prv); err != nil { 301 return s, err 302 } 303 304 authRespMsg, err := h.makeAuthResp() 305 if err != nil { 306 return s, err 307 } 308 var authRespPacket []byte 309 if authMsg.gotPlain { 310 authRespPacket, err = authRespMsg.sealPlain(h) 311 } else { 312 authRespPacket, err = sealEIP8(authRespMsg, h) 313 } 314 if err != nil { 315 return s, err 316 } 317 if _, err = conn.Write(authRespPacket); err != nil { 318 return s, err 319 } 320 return h.secrets(authPacket, authRespPacket) 321 } 322 323 func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) error { 324 325 h.initNonce = msg.Nonce[:] 326 h.remoteID = msg.InitiatorPubkey 327 rpub, err := h.remoteID.Pubkey() 328 if err != nil { 329 return fmt.Errorf("bad remoteID: %#v", err) 330 } 331 h.remotePub = ecies.ImportECDSAPublic(rpub) 332 333 if h.randomPrivKey == nil { 334 h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil) 335 if err != nil { 336 return err 337 } 338 } 339 340 token, err := h.staticSharedSecret(prv) 341 if err != nil { 342 return err 343 } 344 signedMsg := xor(token, h.initNonce) 345 remoteRandomPub, err := secp256k1.RecoverPubkey(signedMsg, msg.Signature[:]) 346 if err != nil { 347 return err 348 } 349 h.remoteRandomPub, _ = importPublicKey(remoteRandomPub) 350 return nil 351 } 352 353 func (h *encHandshake) makeAuthResp() (msg *authRespV4, err error) { 354 355 h.respNonce = make([]byte, shaLen) 356 if _, err = rand.Read(h.respNonce); err != nil { 357 return nil, err 358 } 359 360 msg = new(authRespV4) 361 copy(msg.Nonce[:], h.respNonce) 362 copy(msg.RandomPubkey[:], exportPubkey(&h.randomPrivKey.PublicKey)) 363 msg.Version = 4 364 return msg, nil 365 } 366 367 func (msg *authMsgV4) sealPlain(h *encHandshake) ([]byte, error) { 368 buf := make([]byte, authMsgLen) 369 n := copy(buf, msg.Signature[:]) 370 n += copy(buf[n:], crypto.Keccak256(exportPubkey(&h.randomPrivKey.PublicKey))) 371 n += copy(buf[n:], msg.InitiatorPubkey[:]) 372 n += copy(buf[n:], msg.Nonce[:]) 373 buf[n] = 0 374 return ecies.Encrypt(rand.Reader, h.remotePub, buf, nil, nil) 375 } 376 377 func (msg *authMsgV4) decodePlain(input []byte) { 378 n := copy(msg.Signature[:], input) 379 n += shaLen 380 n += copy(msg.InitiatorPubkey[:], input[n:]) 381 copy(msg.Nonce[:], input[n:]) 382 msg.Version = 4 383 msg.gotPlain = true 384 } 385 386 func (msg *authRespV4) sealPlain(hs *encHandshake) ([]byte, error) { 387 buf := make([]byte, authRespLen) 388 n := copy(buf, msg.RandomPubkey[:]) 389 copy(buf[n:], msg.Nonce[:]) 390 return ecies.Encrypt(rand.Reader, hs.remotePub, buf, nil, nil) 391 } 392 393 func (msg *authRespV4) decodePlain(input []byte) { 394 n := copy(msg.RandomPubkey[:], input) 395 copy(msg.Nonce[:], input[n:]) 396 msg.Version = 4 397 } 398 399 var padSpace = make([]byte, 300) 400 401 func sealEIP8(msg interface{}, h *encHandshake) ([]byte, error) { 402 buf := new(bytes.Buffer) 403 if err := rlp.Encode(buf, msg); err != nil { 404 return nil, err 405 } 406 407 pad := padSpace[:mrand.Intn(len(padSpace)-100)+100] 408 buf.Write(pad) 409 prefix := make([]byte, 2) 410 binary.BigEndian.PutUint16(prefix, uint16(buf.Len()+eciesOverhead)) 411 412 enc, err := ecies.Encrypt(rand.Reader, h.remotePub, buf.Bytes(), nil, prefix) 413 return append(prefix, enc...), err 414 } 415 416 type plainDecoder interface { 417 decodePlain([]byte) 418 } 419 420 func readHandshakeMsg(msg plainDecoder, plainSize int, prv *ecdsa.PrivateKey, r io.Reader) ([]byte, error) { 421 buf := make([]byte, plainSize) 422 if _, err := io.ReadFull(r, buf); err != nil { 423 return buf, err 424 } 425 426 key := ecies.ImportECDSA(prv) 427 if dec, err := key.Decrypt(rand.Reader, buf, nil, nil); err == nil { 428 msg.decodePlain(dec) 429 return buf, nil 430 } 431 432 prefix := buf[:2] 433 size := binary.BigEndian.Uint16(prefix) 434 if size < uint16(plainSize) { 435 return buf, fmt.Errorf("size underflow, need at least %d bytes", plainSize) 436 } 437 buf = append(buf, make([]byte, size-uint16(plainSize)+2)...) 438 if _, err := io.ReadFull(r, buf[plainSize:]); err != nil { 439 return buf, err 440 } 441 dec, err := key.Decrypt(rand.Reader, buf[2:], nil, prefix) 442 if err != nil { 443 return buf, err 444 } 445 446 s := rlp.NewStream(bytes.NewReader(dec), 0) 447 return buf, s.Decode(msg) 448 } 449 450 func importPublicKey(pubKey []byte) (*ecies.PublicKey, error) { 451 var pubKey65 []byte 452 switch len(pubKey) { 453 case 64: 454 455 pubKey65 = append([]byte{0x04}, pubKey...) 456 case 65: 457 pubKey65 = pubKey 458 default: 459 return nil, fmt.Errorf("invalid public key length %v (expect 64/65)", len(pubKey)) 460 } 461 462 pub, err := crypto.UnmarshalPubkey(pubKey65) 463 if err != nil { 464 return nil, err 465 } 466 return ecies.ImportECDSAPublic(pub), nil 467 } 468 469 func exportPubkey(pub *ecies.PublicKey) []byte { 470 if pub == nil { 471 panic("nil pubkey") 472 } 473 return elliptic.Marshal(pub.Curve, pub.X, pub.Y)[1:] 474 } 475 476 func xor(one, other []byte) (xor []byte) { 477 xor = make([]byte, len(one)) 478 for i := 0; i < len(one); i++ { 479 xor[i] = one[i] ^ other[i] 480 } 481 return xor 482 } 483 484 var ( 485 zeroHeader = []byte{0xC2, 0x80, 0x80} 486 487 zero16 = make([]byte, 16) 488 ) 489 490 type rlpxFrameRW struct { 491 conn io.ReadWriter 492 enc cipher.Stream 493 dec cipher.Stream 494 495 macCipher cipher.Block 496 egressMAC hash.Hash 497 ingressMAC hash.Hash 498 499 snappy bool 500 } 501 502 func newRLPXFrameRW(conn io.ReadWriter, s secrets) *rlpxFrameRW { 503 macc, err := aes.NewCipher(s.MAC) 504 if err != nil { 505 panic("invalid MAC secret: " + err.Error()) 506 } 507 encc, err := aes.NewCipher(s.AES) 508 if err != nil { 509 panic("invalid AES secret: " + err.Error()) 510 } 511 512 iv := make([]byte, encc.BlockSize()) 513 return &rlpxFrameRW{ 514 conn: conn, 515 enc: cipher.NewCTR(encc, iv), 516 dec: cipher.NewCTR(encc, iv), 517 macCipher: macc, 518 egressMAC: s.EgressMAC, 519 ingressMAC: s.IngressMAC, 520 } 521 } 522 523 func (rw *rlpxFrameRW) WriteMsg(msg Msg) error { 524 ptype, _ := rlp.EncodeToBytes(msg.Code) 525 526 if rw.snappy { 527 if msg.Size > maxUint24 { 528 return errPlainMessageTooLarge 529 } 530 payload, _ := ioutil.ReadAll(msg.Payload) 531 payload = snappy.Encode(nil, payload) 532 533 msg.Payload = bytes.NewReader(payload) 534 msg.Size = uint32(len(payload)) 535 } 536 537 headbuf := make([]byte, 32) 538 fsize := uint32(len(ptype)) + msg.Size 539 if fsize > maxUint24 { 540 return errors.New("message size overflows uint24") 541 } 542 putInt24(fsize, headbuf) 543 copy(headbuf[3:], zeroHeader) 544 rw.enc.XORKeyStream(headbuf[:16], headbuf[:16]) 545 546 copy(headbuf[16:], updateMAC(rw.egressMAC, rw.macCipher, headbuf[:16])) 547 if _, err := rw.conn.Write(headbuf); err != nil { 548 return err 549 } 550 551 tee := cipher.StreamWriter{S: rw.enc, W: io.MultiWriter(rw.conn, rw.egressMAC)} 552 if _, err := tee.Write(ptype); err != nil { 553 return err 554 } 555 if _, err := io.Copy(tee, msg.Payload); err != nil { 556 return err 557 } 558 if padding := fsize % 16; padding > 0 { 559 if _, err := tee.Write(zero16[:16-padding]); err != nil { 560 return err 561 } 562 } 563 564 fmacseed := rw.egressMAC.Sum(nil) 565 mac := updateMAC(rw.egressMAC, rw.macCipher, fmacseed) 566 _, err := rw.conn.Write(mac) 567 return err 568 } 569 570 func (rw *rlpxFrameRW) ReadMsg() (msg Msg, err error) { 571 572 headbuf := make([]byte, 32) 573 if _, err := io.ReadFull(rw.conn, headbuf); err != nil { 574 return msg, err 575 } 576 577 shouldMAC := updateMAC(rw.ingressMAC, rw.macCipher, headbuf[:16]) 578 if !hmac.Equal(shouldMAC, headbuf[16:]) { 579 return msg, errors.New("bad header MAC") 580 } 581 rw.dec.XORKeyStream(headbuf[:16], headbuf[:16]) 582 fsize := readInt24(headbuf) 583 584 var rsize = fsize 585 if padding := fsize % 16; padding > 0 { 586 rsize += 16 - padding 587 } 588 framebuf := make([]byte, rsize) 589 if _, err := io.ReadFull(rw.conn, framebuf); err != nil { 590 return msg, err 591 } 592 593 rw.ingressMAC.Write(framebuf) 594 fmacseed := rw.ingressMAC.Sum(nil) 595 if _, err := io.ReadFull(rw.conn, headbuf[:16]); err != nil { 596 return msg, err 597 } 598 shouldMAC = updateMAC(rw.ingressMAC, rw.macCipher, fmacseed) 599 if !hmac.Equal(shouldMAC, headbuf[:16]) { 600 return msg, errors.New("bad frame MAC") 601 } 602 603 rw.dec.XORKeyStream(framebuf, framebuf) 604 605 content := bytes.NewReader(framebuf[:fsize]) 606 if err := rlp.Decode(content, &msg.Code); err != nil { 607 return msg, err 608 } 609 msg.Size = uint32(content.Len()) 610 msg.Payload = content 611 612 if rw.snappy { 613 payload, err := ioutil.ReadAll(msg.Payload) 614 if err != nil { 615 return msg, err 616 } 617 size, err := snappy.DecodedLen(payload) 618 if err != nil { 619 return msg, err 620 } 621 if size > int(maxUint24) { 622 return msg, errPlainMessageTooLarge 623 } 624 payload, err = snappy.Decode(nil, payload) 625 if err != nil { 626 return msg, err 627 } 628 msg.Size, msg.Payload = uint32(size), bytes.NewReader(payload) 629 } 630 return msg, nil 631 } 632 633 func updateMAC(mac hash.Hash, block cipher.Block, seed []byte) []byte { 634 aesbuf := make([]byte, aes.BlockSize) 635 block.Encrypt(aesbuf, mac.Sum(nil)) 636 for i := range aesbuf { 637 aesbuf[i] ^= seed[i] 638 } 639 mac.Write(aesbuf) 640 return mac.Sum(nil)[:16] 641 } 642 643 func readInt24(b []byte) uint32 { 644 return uint32(b[2]) | uint32(b[1])<<8 | uint32(b[0])<<16 645 } 646 647 func putInt24(v uint32, b []byte) { 648 b[0] = byte(v >> 16) 649 b[1] = byte(v >> 8) 650 b[2] = byte(v) 651 }