github.com/jimmyx0x/go-ethereum@v1.10.28/p2p/discover/v5wire/encoding.go (about) 1 // Copyright 2020 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 v5wire 18 19 import ( 20 "bytes" 21 "crypto/aes" 22 "crypto/cipher" 23 "crypto/ecdsa" 24 crand "crypto/rand" 25 "crypto/sha256" 26 "encoding/binary" 27 "errors" 28 "fmt" 29 "hash" 30 31 "github.com/ethereum/go-ethereum/common/mclock" 32 "github.com/ethereum/go-ethereum/p2p/enode" 33 "github.com/ethereum/go-ethereum/p2p/enr" 34 "github.com/ethereum/go-ethereum/rlp" 35 ) 36 37 // TODO concurrent WHOAREYOU tie-breaker 38 // TODO rehandshake after X packets 39 40 // Header represents a packet header. 41 type Header struct { 42 IV [sizeofMaskingIV]byte 43 StaticHeader 44 AuthData []byte 45 46 src enode.ID // used by decoder 47 } 48 49 // StaticHeader contains the static fields of a packet header. 50 type StaticHeader struct { 51 ProtocolID [6]byte 52 Version uint16 53 Flag byte 54 Nonce Nonce 55 AuthSize uint16 56 } 57 58 // Authdata layouts. 59 type ( 60 whoareyouAuthData struct { 61 IDNonce [16]byte // ID proof data 62 RecordSeq uint64 // highest known ENR sequence of requester 63 } 64 65 handshakeAuthData struct { 66 h struct { 67 SrcID enode.ID 68 SigSize byte // signature data 69 PubkeySize byte // offset of 70 } 71 // Trailing variable-size data. 72 signature, pubkey, record []byte 73 } 74 75 messageAuthData struct { 76 SrcID enode.ID 77 } 78 ) 79 80 // Packet header flag values. 81 const ( 82 flagMessage = iota 83 flagWhoareyou 84 flagHandshake 85 ) 86 87 // Protocol constants. 88 const ( 89 version = 1 90 minVersion = 1 91 sizeofMaskingIV = 16 92 93 // The minimum size of any Discovery v5 packet is 63 bytes. 94 // Should reject packets smaller than minPacketSize. 95 minPacketSize = 63 96 97 minMessageSize = 48 // this refers to data after static headers 98 randomPacketMsgSize = 20 99 ) 100 101 var DefaultProtocolID = [6]byte{'d', 'i', 's', 'c', 'v', '5'} 102 103 // Errors. 104 var ( 105 errTooShort = errors.New("packet too short") 106 errInvalidHeader = errors.New("invalid packet header") 107 errInvalidFlag = errors.New("invalid flag value in header") 108 errMinVersion = errors.New("version of packet header below minimum") 109 errMsgTooShort = errors.New("message/handshake packet below minimum size") 110 errAuthSize = errors.New("declared auth size is beyond packet length") 111 errUnexpectedHandshake = errors.New("unexpected auth response, not in handshake") 112 errInvalidAuthKey = errors.New("invalid ephemeral pubkey") 113 errNoRecord = errors.New("expected ENR in handshake but none sent") 114 errInvalidNonceSig = errors.New("invalid ID nonce signature") 115 errMessageTooShort = errors.New("message contains no data") 116 errMessageDecrypt = errors.New("cannot decrypt message") 117 ) 118 119 // Public errors. 120 var ( 121 // ErrInvalidReqID represents error when the ID is invalid. 122 ErrInvalidReqID = errors.New("request ID larger than 8 bytes") 123 ) 124 125 // Packet sizes. 126 var ( 127 sizeofStaticHeader = binary.Size(StaticHeader{}) 128 sizeofWhoareyouAuthData = binary.Size(whoareyouAuthData{}) 129 sizeofHandshakeAuthData = binary.Size(handshakeAuthData{}.h) 130 sizeofMessageAuthData = binary.Size(messageAuthData{}) 131 sizeofStaticPacketData = sizeofMaskingIV + sizeofStaticHeader 132 ) 133 134 // Codec encodes and decodes Discovery v5 packets. 135 // This type is not safe for concurrent use. 136 type Codec struct { 137 sha256 hash.Hash 138 localnode *enode.LocalNode 139 privkey *ecdsa.PrivateKey 140 sc *SessionCache 141 protocolID [6]byte 142 143 // encoder buffers 144 buf bytes.Buffer // whole packet 145 headbuf bytes.Buffer // packet header 146 msgbuf bytes.Buffer // message RLP plaintext 147 msgctbuf []byte // message data ciphertext 148 149 // decoder buffer 150 reader bytes.Reader 151 } 152 153 // NewCodec creates a wire codec. 154 func NewCodec(ln *enode.LocalNode, key *ecdsa.PrivateKey, clock mclock.Clock, protocolID *[6]byte) *Codec { 155 c := &Codec{ 156 sha256: sha256.New(), 157 localnode: ln, 158 privkey: key, 159 sc: NewSessionCache(1024, clock), 160 protocolID: DefaultProtocolID, 161 } 162 if protocolID != nil { 163 c.protocolID = *protocolID 164 } 165 return c 166 } 167 168 // Encode encodes a packet to a node. 'id' and 'addr' specify the destination node. The 169 // 'challenge' parameter should be the most recently received WHOAREYOU packet from that 170 // node. 171 func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoareyou) ([]byte, Nonce, error) { 172 // Create the packet header. 173 var ( 174 head Header 175 session *session 176 msgData []byte 177 err error 178 ) 179 switch { 180 case packet.Kind() == WhoareyouPacket: 181 head, err = c.encodeWhoareyou(id, packet.(*Whoareyou)) 182 case challenge != nil: 183 // We have an unanswered challenge, send handshake. 184 head, session, err = c.encodeHandshakeHeader(id, addr, challenge) 185 default: 186 session = c.sc.session(id, addr) 187 if session != nil { 188 // There is a session, use it. 189 head, err = c.encodeMessageHeader(id, session) 190 } else { 191 // No keys, send random data to kick off the handshake. 192 head, msgData, err = c.encodeRandom(id) 193 } 194 } 195 if err != nil { 196 return nil, Nonce{}, err 197 } 198 199 // Generate masking IV. 200 if err := c.sc.maskingIVGen(head.IV[:]); err != nil { 201 return nil, Nonce{}, fmt.Errorf("can't generate masking IV: %v", err) 202 } 203 204 // Encode header data. 205 c.writeHeaders(&head) 206 207 // Store sent WHOAREYOU challenges. 208 if challenge, ok := packet.(*Whoareyou); ok { 209 challenge.ChallengeData = bytesCopy(&c.buf) 210 c.sc.storeSentHandshake(id, addr, challenge) 211 } else if msgData == nil { 212 headerData := c.buf.Bytes() 213 msgData, err = c.encryptMessage(session, packet, &head, headerData) 214 if err != nil { 215 return nil, Nonce{}, err 216 } 217 } 218 219 enc, err := c.EncodeRaw(id, head, msgData) 220 return enc, head.Nonce, err 221 } 222 223 // EncodeRaw encodes a packet with the given header. 224 func (c *Codec) EncodeRaw(id enode.ID, head Header, msgdata []byte) ([]byte, error) { 225 c.writeHeaders(&head) 226 227 // Apply masking. 228 masked := c.buf.Bytes()[sizeofMaskingIV:] 229 mask := head.mask(id) 230 mask.XORKeyStream(masked[:], masked[:]) 231 232 // Write message data. 233 c.buf.Write(msgdata) 234 return c.buf.Bytes(), nil 235 } 236 237 func (c *Codec) writeHeaders(head *Header) { 238 c.buf.Reset() 239 c.buf.Write(head.IV[:]) 240 binary.Write(&c.buf, binary.BigEndian, &head.StaticHeader) 241 c.buf.Write(head.AuthData) 242 } 243 244 // makeHeader creates a packet header. 245 func (c *Codec) makeHeader(toID enode.ID, flag byte, authsizeExtra int) Header { 246 var authsize int 247 switch flag { 248 case flagMessage: 249 authsize = sizeofMessageAuthData 250 case flagWhoareyou: 251 authsize = sizeofWhoareyouAuthData 252 case flagHandshake: 253 authsize = sizeofHandshakeAuthData 254 default: 255 panic(fmt.Errorf("BUG: invalid packet header flag %x", flag)) 256 } 257 authsize += authsizeExtra 258 if authsize > int(^uint16(0)) { 259 panic(fmt.Errorf("BUG: auth size %d overflows uint16", authsize)) 260 } 261 return Header{ 262 StaticHeader: StaticHeader{ 263 ProtocolID: c.protocolID, 264 Version: version, 265 Flag: flag, 266 AuthSize: uint16(authsize), 267 }, 268 } 269 } 270 271 // encodeRandom encodes a packet with random content. 272 func (c *Codec) encodeRandom(toID enode.ID) (Header, []byte, error) { 273 head := c.makeHeader(toID, flagMessage, 0) 274 275 // Encode auth data. 276 auth := messageAuthData{SrcID: c.localnode.ID()} 277 if _, err := crand.Read(head.Nonce[:]); err != nil { 278 return head, nil, fmt.Errorf("can't get random data: %v", err) 279 } 280 c.headbuf.Reset() 281 binary.Write(&c.headbuf, binary.BigEndian, auth) 282 head.AuthData = c.headbuf.Bytes() 283 284 // Fill message ciphertext buffer with random bytes. 285 c.msgctbuf = append(c.msgctbuf[:0], make([]byte, randomPacketMsgSize)...) 286 crand.Read(c.msgctbuf) 287 return head, c.msgctbuf, nil 288 } 289 290 // encodeWhoareyou encodes a WHOAREYOU packet. 291 func (c *Codec) encodeWhoareyou(toID enode.ID, packet *Whoareyou) (Header, error) { 292 // Sanity check node field to catch misbehaving callers. 293 if packet.RecordSeq > 0 && packet.Node == nil { 294 panic("BUG: missing node in whoareyou with non-zero seq") 295 } 296 297 // Create header. 298 head := c.makeHeader(toID, flagWhoareyou, 0) 299 head.AuthData = bytesCopy(&c.buf) 300 head.Nonce = packet.Nonce 301 302 // Encode auth data. 303 auth := &whoareyouAuthData{ 304 IDNonce: packet.IDNonce, 305 RecordSeq: packet.RecordSeq, 306 } 307 c.headbuf.Reset() 308 binary.Write(&c.headbuf, binary.BigEndian, auth) 309 head.AuthData = c.headbuf.Bytes() 310 return head, nil 311 } 312 313 // encodeHandshakeHeader encodes the handshake message packet header. 314 func (c *Codec) encodeHandshakeHeader(toID enode.ID, addr string, challenge *Whoareyou) (Header, *session, error) { 315 // Ensure calling code sets challenge.node. 316 if challenge.Node == nil { 317 panic("BUG: missing challenge.Node in encode") 318 } 319 320 // Generate new secrets. 321 auth, session, err := c.makeHandshakeAuth(toID, addr, challenge) 322 if err != nil { 323 return Header{}, nil, err 324 } 325 326 // Generate nonce for message. 327 nonce, err := c.sc.nextNonce(session) 328 if err != nil { 329 return Header{}, nil, fmt.Errorf("can't generate nonce: %v", err) 330 } 331 332 // TODO: this should happen when the first authenticated message is received 333 c.sc.storeNewSession(toID, addr, session) 334 335 // Encode the auth header. 336 var ( 337 authsizeExtra = len(auth.pubkey) + len(auth.signature) + len(auth.record) 338 head = c.makeHeader(toID, flagHandshake, authsizeExtra) 339 ) 340 c.headbuf.Reset() 341 binary.Write(&c.headbuf, binary.BigEndian, &auth.h) 342 c.headbuf.Write(auth.signature) 343 c.headbuf.Write(auth.pubkey) 344 c.headbuf.Write(auth.record) 345 head.AuthData = c.headbuf.Bytes() 346 head.Nonce = nonce 347 return head, session, err 348 } 349 350 // makeHandshakeAuth creates the auth header on a request packet following WHOAREYOU. 351 func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoareyou) (*handshakeAuthData, *session, error) { 352 auth := new(handshakeAuthData) 353 auth.h.SrcID = c.localnode.ID() 354 355 // Create the ephemeral key. This needs to be first because the 356 // key is part of the ID nonce signature. 357 var remotePubkey = new(ecdsa.PublicKey) 358 if err := challenge.Node.Load((*enode.Secp256k1)(remotePubkey)); err != nil { 359 return nil, nil, fmt.Errorf("can't find secp256k1 key for recipient") 360 } 361 ephkey, err := c.sc.ephemeralKeyGen() 362 if err != nil { 363 return nil, nil, fmt.Errorf("can't generate ephemeral key") 364 } 365 ephpubkey := EncodePubkey(&ephkey.PublicKey) 366 auth.pubkey = ephpubkey[:] 367 auth.h.PubkeySize = byte(len(auth.pubkey)) 368 369 // Add ID nonce signature to response. 370 cdata := challenge.ChallengeData 371 idsig, err := makeIDSignature(c.sha256, c.privkey, cdata, ephpubkey[:], toID) 372 if err != nil { 373 return nil, nil, fmt.Errorf("can't sign: %v", err) 374 } 375 auth.signature = idsig 376 auth.h.SigSize = byte(len(auth.signature)) 377 378 // Add our record to response if it's newer than what remote side has. 379 ln := c.localnode.Node() 380 if challenge.RecordSeq < ln.Seq() { 381 auth.record, _ = rlp.EncodeToBytes(ln.Record()) 382 } 383 384 // Create session keys. 385 sec := deriveKeys(sha256.New, ephkey, remotePubkey, c.localnode.ID(), challenge.Node.ID(), cdata) 386 if sec == nil { 387 return nil, nil, fmt.Errorf("key derivation failed") 388 } 389 return auth, sec, err 390 } 391 392 // encodeMessageHeader encodes an encrypted message packet. 393 func (c *Codec) encodeMessageHeader(toID enode.ID, s *session) (Header, error) { 394 head := c.makeHeader(toID, flagMessage, 0) 395 396 // Create the header. 397 nonce, err := c.sc.nextNonce(s) 398 if err != nil { 399 return Header{}, fmt.Errorf("can't generate nonce: %v", err) 400 } 401 auth := messageAuthData{SrcID: c.localnode.ID()} 402 c.buf.Reset() 403 binary.Write(&c.buf, binary.BigEndian, &auth) 404 head.AuthData = bytesCopy(&c.buf) 405 head.Nonce = nonce 406 return head, err 407 } 408 409 func (c *Codec) encryptMessage(s *session, p Packet, head *Header, headerData []byte) ([]byte, error) { 410 // Encode message plaintext. 411 c.msgbuf.Reset() 412 c.msgbuf.WriteByte(p.Kind()) 413 if err := rlp.Encode(&c.msgbuf, p); err != nil { 414 return nil, err 415 } 416 messagePT := c.msgbuf.Bytes() 417 418 // Encrypt into message ciphertext buffer. 419 messageCT, err := encryptGCM(c.msgctbuf[:0], s.writeKey, head.Nonce[:], messagePT, headerData) 420 if err == nil { 421 c.msgctbuf = messageCT 422 } 423 return messageCT, err 424 } 425 426 // Decode decodes a discovery packet. 427 func (c *Codec) Decode(input []byte, addr string) (src enode.ID, n *enode.Node, p Packet, err error) { 428 if len(input) < minPacketSize { 429 return enode.ID{}, nil, nil, errTooShort 430 } 431 // Unmask the static header. 432 var head Header 433 copy(head.IV[:], input[:sizeofMaskingIV]) 434 mask := head.mask(c.localnode.ID()) 435 staticHeader := input[sizeofMaskingIV:sizeofStaticPacketData] 436 mask.XORKeyStream(staticHeader, staticHeader) 437 438 // Decode and verify the static header. 439 c.reader.Reset(staticHeader) 440 binary.Read(&c.reader, binary.BigEndian, &head.StaticHeader) 441 remainingInput := len(input) - sizeofStaticPacketData 442 if err := head.checkValid(remainingInput, c.protocolID); err != nil { 443 return enode.ID{}, nil, nil, err 444 } 445 446 // Unmask auth data. 447 authDataEnd := sizeofStaticPacketData + int(head.AuthSize) 448 authData := input[sizeofStaticPacketData:authDataEnd] 449 mask.XORKeyStream(authData, authData) 450 head.AuthData = authData 451 452 // Delete timed-out handshakes. This must happen before decoding to avoid 453 // processing the same handshake twice. 454 c.sc.handshakeGC() 455 456 // Decode auth part and message. 457 headerData := input[:authDataEnd] 458 msgData := input[authDataEnd:] 459 switch head.Flag { 460 case flagWhoareyou: 461 p, err = c.decodeWhoareyou(&head, headerData) 462 case flagHandshake: 463 n, p, err = c.decodeHandshakeMessage(addr, &head, headerData, msgData) 464 case flagMessage: 465 p, err = c.decodeMessage(addr, &head, headerData, msgData) 466 default: 467 err = errInvalidFlag 468 } 469 return head.src, n, p, err 470 } 471 472 // decodeWhoareyou reads packet data after the header as a WHOAREYOU packet. 473 func (c *Codec) decodeWhoareyou(head *Header, headerData []byte) (Packet, error) { 474 if len(head.AuthData) != sizeofWhoareyouAuthData { 475 return nil, fmt.Errorf("invalid auth size %d for WHOAREYOU", len(head.AuthData)) 476 } 477 var auth whoareyouAuthData 478 c.reader.Reset(head.AuthData) 479 binary.Read(&c.reader, binary.BigEndian, &auth) 480 p := &Whoareyou{ 481 Nonce: head.Nonce, 482 IDNonce: auth.IDNonce, 483 RecordSeq: auth.RecordSeq, 484 ChallengeData: make([]byte, len(headerData)), 485 } 486 copy(p.ChallengeData, headerData) 487 return p, nil 488 } 489 490 func (c *Codec) decodeHandshakeMessage(fromAddr string, head *Header, headerData, msgData []byte) (n *enode.Node, p Packet, err error) { 491 node, auth, session, err := c.decodeHandshake(fromAddr, head) 492 if err != nil { 493 c.sc.deleteHandshake(auth.h.SrcID, fromAddr) 494 return nil, nil, err 495 } 496 497 // Decrypt the message using the new session keys. 498 msg, err := c.decryptMessage(msgData, head.Nonce[:], headerData, session.readKey) 499 if err != nil { 500 c.sc.deleteHandshake(auth.h.SrcID, fromAddr) 501 return node, msg, err 502 } 503 504 // Handshake OK, drop the challenge and store the new session keys. 505 c.sc.storeNewSession(auth.h.SrcID, fromAddr, session) 506 c.sc.deleteHandshake(auth.h.SrcID, fromAddr) 507 return node, msg, nil 508 } 509 510 func (c *Codec) decodeHandshake(fromAddr string, head *Header) (n *enode.Node, auth handshakeAuthData, s *session, err error) { 511 if auth, err = c.decodeHandshakeAuthData(head); err != nil { 512 return nil, auth, nil, err 513 } 514 515 // Verify against our last WHOAREYOU. 516 challenge := c.sc.getHandshake(auth.h.SrcID, fromAddr) 517 if challenge == nil { 518 return nil, auth, nil, errUnexpectedHandshake 519 } 520 // Get node record. 521 n, err = c.decodeHandshakeRecord(challenge.Node, auth.h.SrcID, auth.record) 522 if err != nil { 523 return nil, auth, nil, err 524 } 525 // Verify ID nonce signature. 526 sig := auth.signature 527 cdata := challenge.ChallengeData 528 err = verifyIDSignature(c.sha256, sig, n, cdata, auth.pubkey, c.localnode.ID()) 529 if err != nil { 530 return nil, auth, nil, err 531 } 532 // Verify ephemeral key is on curve. 533 ephkey, err := DecodePubkey(c.privkey.Curve, auth.pubkey) 534 if err != nil { 535 return nil, auth, nil, errInvalidAuthKey 536 } 537 // Derive session keys. 538 session := deriveKeys(sha256.New, c.privkey, ephkey, auth.h.SrcID, c.localnode.ID(), cdata) 539 session = session.keysFlipped() 540 return n, auth, session, nil 541 } 542 543 // decodeHandshakeAuthData reads the authdata section of a handshake packet. 544 func (c *Codec) decodeHandshakeAuthData(head *Header) (auth handshakeAuthData, err error) { 545 // Decode fixed size part. 546 if len(head.AuthData) < sizeofHandshakeAuthData { 547 return auth, fmt.Errorf("header authsize %d too low for handshake", head.AuthSize) 548 } 549 c.reader.Reset(head.AuthData) 550 binary.Read(&c.reader, binary.BigEndian, &auth.h) 551 head.src = auth.h.SrcID 552 553 // Decode variable-size part. 554 var ( 555 vardata = head.AuthData[sizeofHandshakeAuthData:] 556 sigAndKeySize = int(auth.h.SigSize) + int(auth.h.PubkeySize) 557 keyOffset = int(auth.h.SigSize) 558 recOffset = keyOffset + int(auth.h.PubkeySize) 559 ) 560 if len(vardata) < sigAndKeySize { 561 return auth, errTooShort 562 } 563 auth.signature = vardata[:keyOffset] 564 auth.pubkey = vardata[keyOffset:recOffset] 565 auth.record = vardata[recOffset:] 566 return auth, nil 567 } 568 569 // decodeHandshakeRecord verifies the node record contained in a handshake packet. The 570 // remote node should include the record if we don't have one or if ours is older than the 571 // latest sequence number. 572 func (c *Codec) decodeHandshakeRecord(local *enode.Node, wantID enode.ID, remote []byte) (*enode.Node, error) { 573 node := local 574 if len(remote) > 0 { 575 var record enr.Record 576 if err := rlp.DecodeBytes(remote, &record); err != nil { 577 return nil, err 578 } 579 if local == nil || local.Seq() < record.Seq() { 580 n, err := enode.New(enode.ValidSchemes, &record) 581 if err != nil { 582 return nil, fmt.Errorf("invalid node record: %v", err) 583 } 584 if n.ID() != wantID { 585 return nil, fmt.Errorf("record in handshake has wrong ID: %v", n.ID()) 586 } 587 node = n 588 } 589 } 590 if node == nil { 591 return nil, errNoRecord 592 } 593 return node, nil 594 } 595 596 // decodeMessage reads packet data following the header as an ordinary message packet. 597 func (c *Codec) decodeMessage(fromAddr string, head *Header, headerData, msgData []byte) (Packet, error) { 598 if len(head.AuthData) != sizeofMessageAuthData { 599 return nil, fmt.Errorf("invalid auth size %d for message packet", len(head.AuthData)) 600 } 601 var auth messageAuthData 602 c.reader.Reset(head.AuthData) 603 binary.Read(&c.reader, binary.BigEndian, &auth) 604 head.src = auth.SrcID 605 606 // Try decrypting the message. 607 key := c.sc.readKey(auth.SrcID, fromAddr) 608 msg, err := c.decryptMessage(msgData, head.Nonce[:], headerData, key) 609 if errors.Is(err, errMessageDecrypt) { 610 // It didn't work. Start the handshake since this is an ordinary message packet. 611 return &Unknown{Nonce: head.Nonce}, nil 612 } 613 return msg, err 614 } 615 616 func (c *Codec) decryptMessage(input, nonce, headerData, readKey []byte) (Packet, error) { 617 msgdata, err := decryptGCM(readKey, nonce, input, headerData) 618 if err != nil { 619 return nil, errMessageDecrypt 620 } 621 if len(msgdata) == 0 { 622 return nil, errMessageTooShort 623 } 624 return DecodeMessage(msgdata[0], msgdata[1:]) 625 } 626 627 // checkValid performs some basic validity checks on the header. 628 // The packetLen here is the length remaining after the static header. 629 func (h *StaticHeader) checkValid(packetLen int, protocolID [6]byte) error { 630 if h.ProtocolID != protocolID { 631 return errInvalidHeader 632 } 633 if h.Version < minVersion { 634 return errMinVersion 635 } 636 if h.Flag != flagWhoareyou && packetLen < minMessageSize { 637 return errMsgTooShort 638 } 639 if int(h.AuthSize) > packetLen { 640 return errAuthSize 641 } 642 return nil 643 } 644 645 // mask returns a cipher for 'masking' / 'unmasking' packet headers. 646 func (h *Header) mask(destID enode.ID) cipher.Stream { 647 block, err := aes.NewCipher(destID[:16]) 648 if err != nil { 649 panic("can't create cipher") 650 } 651 return cipher.NewCTR(block, h.IV[:]) 652 } 653 654 func bytesCopy(r *bytes.Buffer) []byte { 655 b := make([]byte, r.Len()) 656 copy(b, r.Bytes()) 657 return b 658 }