v5_encoding.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. // Copyright 2019 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. package discover
  17. import (
  18. "bytes"
  19. "crypto/aes"
  20. "crypto/cipher"
  21. "crypto/ecdsa"
  22. "crypto/elliptic"
  23. crand "crypto/rand"
  24. "crypto/sha256"
  25. "errors"
  26. "fmt"
  27. "hash"
  28. "net"
  29. "time"
  30. "github.com/ethereum/go-ethereum/common/math"
  31. "github.com/ethereum/go-ethereum/common/mclock"
  32. "github.com/ethereum/go-ethereum/crypto"
  33. "github.com/ethereum/go-ethereum/p2p/enode"
  34. "github.com/ethereum/go-ethereum/p2p/enr"
  35. "github.com/ethereum/go-ethereum/rlp"
  36. "golang.org/x/crypto/hkdf"
  37. )
  38. // TODO concurrent WHOAREYOU tie-breaker
  39. // TODO deal with WHOAREYOU amplification factor (min packet size?)
  40. // TODO add counter to nonce
  41. // TODO rehandshake after X packets
  42. // Discovery v5 packet types.
  43. const (
  44. p_pingV5 byte = iota + 1
  45. p_pongV5
  46. p_findnodeV5
  47. p_nodesV5
  48. p_requestTicketV5
  49. p_ticketV5
  50. p_regtopicV5
  51. p_regconfirmationV5
  52. p_topicqueryV5
  53. p_unknownV5 = byte(255) // any non-decryptable packet
  54. p_whoareyouV5 = byte(254) // the WHOAREYOU packet
  55. )
  56. // Discovery v5 packet structures.
  57. type (
  58. // unknownV5 represents any packet that can't be decrypted.
  59. unknownV5 struct {
  60. AuthTag []byte
  61. }
  62. // WHOAREYOU contains the handshake challenge.
  63. whoareyouV5 struct {
  64. AuthTag []byte
  65. IDNonce [32]byte // To be signed by recipient.
  66. RecordSeq uint64 // ENR sequence number of recipient
  67. node *enode.Node
  68. sent mclock.AbsTime
  69. }
  70. // PING is sent during liveness checks.
  71. pingV5 struct {
  72. ReqID []byte
  73. ENRSeq uint64
  74. }
  75. // PONG is the reply to PING.
  76. pongV5 struct {
  77. ReqID []byte
  78. ENRSeq uint64
  79. ToIP net.IP // These fields should mirror the UDP envelope address of the ping
  80. ToPort uint16 // packet, which provides a way to discover the the external address (after NAT).
  81. }
  82. // FINDNODE is a query for nodes in the given bucket.
  83. findnodeV5 struct {
  84. ReqID []byte
  85. Distance uint
  86. }
  87. // NODES is the reply to FINDNODE and TOPICQUERY.
  88. nodesV5 struct {
  89. ReqID []byte
  90. Total uint8
  91. Nodes []*enr.Record
  92. }
  93. // REQUESTTICKET requests a ticket for a topic queue.
  94. requestTicketV5 struct {
  95. ReqID []byte
  96. Topic []byte
  97. }
  98. // TICKET is the response to REQUESTTICKET.
  99. ticketV5 struct {
  100. ReqID []byte
  101. Ticket []byte
  102. }
  103. // REGTOPIC registers the sender in a topic queue using a ticket.
  104. regtopicV5 struct {
  105. ReqID []byte
  106. Ticket []byte
  107. ENR *enr.Record
  108. }
  109. // REGCONFIRMATION is the reply to REGTOPIC.
  110. regconfirmationV5 struct {
  111. ReqID []byte
  112. Registered bool
  113. }
  114. // TOPICQUERY asks for nodes with the given topic.
  115. topicqueryV5 struct {
  116. ReqID []byte
  117. Topic []byte
  118. }
  119. )
  120. const (
  121. // Encryption/authentication parameters.
  122. authSchemeName = "gcm"
  123. aesKeySize = 16
  124. gcmNonceSize = 12
  125. idNoncePrefix = "discovery-id-nonce"
  126. handshakeTimeout = time.Second
  127. )
  128. var (
  129. errTooShort = errors.New("packet too short")
  130. errUnexpectedHandshake = errors.New("unexpected auth response, not in handshake")
  131. errHandshakeNonceMismatch = errors.New("wrong nonce in auth response")
  132. errInvalidAuthKey = errors.New("invalid ephemeral pubkey")
  133. errUnknownAuthScheme = errors.New("unknown auth scheme in handshake")
  134. errNoRecord = errors.New("expected ENR in handshake but none sent")
  135. errInvalidNonceSig = errors.New("invalid ID nonce signature")
  136. zeroNonce = make([]byte, gcmNonceSize)
  137. )
  138. // wireCodec encodes and decodes discovery v5 packets.
  139. type wireCodec struct {
  140. sha256 hash.Hash
  141. localnode *enode.LocalNode
  142. privkey *ecdsa.PrivateKey
  143. myChtagHash enode.ID
  144. myWhoareyouMagic []byte
  145. sc *sessionCache
  146. }
  147. type handshakeSecrets struct {
  148. writeKey, readKey, authRespKey []byte
  149. }
  150. type authHeader struct {
  151. authHeaderList
  152. isHandshake bool
  153. }
  154. type authHeaderList struct {
  155. Auth []byte // authentication info of packet
  156. IDNonce [32]byte // IDNonce of WHOAREYOU
  157. Scheme string // name of encryption/authentication scheme
  158. EphemeralKey []byte // ephemeral public key
  159. Response []byte // encrypted authResponse
  160. }
  161. type authResponse struct {
  162. Version uint
  163. Signature []byte
  164. Record *enr.Record `rlp:"nil"` // sender's record
  165. }
  166. func (h *authHeader) DecodeRLP(r *rlp.Stream) error {
  167. k, _, err := r.Kind()
  168. if err != nil {
  169. return err
  170. }
  171. if k == rlp.Byte || k == rlp.String {
  172. return r.Decode(&h.Auth)
  173. }
  174. h.isHandshake = true
  175. return r.Decode(&h.authHeaderList)
  176. }
  177. // ephemeralKey decodes the ephemeral public key in the header.
  178. func (h *authHeaderList) ephemeralKey(curve elliptic.Curve) *ecdsa.PublicKey {
  179. var key encPubkey
  180. copy(key[:], h.EphemeralKey)
  181. pubkey, _ := decodePubkey(curve, key)
  182. return pubkey
  183. }
  184. // newWireCodec creates a wire codec.
  185. func newWireCodec(ln *enode.LocalNode, key *ecdsa.PrivateKey, clock mclock.Clock) *wireCodec {
  186. c := &wireCodec{
  187. sha256: sha256.New(),
  188. localnode: ln,
  189. privkey: key,
  190. sc: newSessionCache(1024, clock),
  191. }
  192. // Create magic strings for packet matching.
  193. self := ln.ID()
  194. c.myWhoareyouMagic = c.sha256sum(self[:], []byte("WHOAREYOU"))
  195. copy(c.myChtagHash[:], c.sha256sum(self[:]))
  196. return c
  197. }
  198. // encode encodes a packet to a node. 'id' and 'addr' specify the destination node. The
  199. // 'challenge' parameter should be the most recently received WHOAREYOU packet from that
  200. // node.
  201. func (c *wireCodec) encode(id enode.ID, addr string, packet packetV5, challenge *whoareyouV5) ([]byte, []byte, error) {
  202. if packet.kind() == p_whoareyouV5 {
  203. p := packet.(*whoareyouV5)
  204. enc, err := c.encodeWhoareyou(id, p)
  205. if err == nil {
  206. c.sc.storeSentHandshake(id, addr, p)
  207. }
  208. return enc, nil, err
  209. }
  210. // Ensure calling code sets node if needed.
  211. if challenge != nil && challenge.node == nil {
  212. panic("BUG: missing challenge.node in encode")
  213. }
  214. writeKey := c.sc.writeKey(id, addr)
  215. if writeKey != nil || challenge != nil {
  216. return c.encodeEncrypted(id, addr, packet, writeKey, challenge)
  217. }
  218. return c.encodeRandom(id)
  219. }
  220. // encodeRandom encodes a random packet.
  221. func (c *wireCodec) encodeRandom(toID enode.ID) ([]byte, []byte, error) {
  222. tag := xorTag(c.sha256sum(toID[:]), c.localnode.ID())
  223. r := make([]byte, 44) // TODO randomize size
  224. if _, err := crand.Read(r); err != nil {
  225. return nil, nil, err
  226. }
  227. nonce := make([]byte, gcmNonceSize)
  228. if _, err := crand.Read(nonce); err != nil {
  229. return nil, nil, fmt.Errorf("can't get random data: %v", err)
  230. }
  231. b := new(bytes.Buffer)
  232. b.Write(tag[:])
  233. rlp.Encode(b, nonce)
  234. b.Write(r)
  235. return b.Bytes(), nonce, nil
  236. }
  237. // encodeWhoareyou encodes WHOAREYOU.
  238. func (c *wireCodec) encodeWhoareyou(toID enode.ID, packet *whoareyouV5) ([]byte, error) {
  239. // Sanity check node field to catch misbehaving callers.
  240. if packet.RecordSeq > 0 && packet.node == nil {
  241. panic("BUG: missing node in whoareyouV5 with non-zero seq")
  242. }
  243. b := new(bytes.Buffer)
  244. b.Write(c.sha256sum(toID[:], []byte("WHOAREYOU")))
  245. err := rlp.Encode(b, packet)
  246. return b.Bytes(), err
  247. }
  248. // encodeEncrypted encodes an encrypted packet.
  249. func (c *wireCodec) encodeEncrypted(toID enode.ID, toAddr string, packet packetV5, writeKey []byte, challenge *whoareyouV5) (enc []byte, authTag []byte, err error) {
  250. nonce := make([]byte, gcmNonceSize)
  251. if _, err := crand.Read(nonce); err != nil {
  252. return nil, nil, fmt.Errorf("can't get random data: %v", err)
  253. }
  254. var headEnc []byte
  255. if challenge == nil {
  256. // Regular packet, use existing key and simply encode nonce.
  257. headEnc, _ = rlp.EncodeToBytes(nonce)
  258. } else {
  259. // We're answering WHOAREYOU, generate new keys and encrypt with those.
  260. header, sec, err := c.makeAuthHeader(nonce, challenge)
  261. if err != nil {
  262. return nil, nil, err
  263. }
  264. if headEnc, err = rlp.EncodeToBytes(header); err != nil {
  265. return nil, nil, err
  266. }
  267. c.sc.storeNewSession(toID, toAddr, sec.readKey, sec.writeKey)
  268. writeKey = sec.writeKey
  269. }
  270. // Encode the packet.
  271. body := new(bytes.Buffer)
  272. body.WriteByte(packet.kind())
  273. if err := rlp.Encode(body, packet); err != nil {
  274. return nil, nil, err
  275. }
  276. tag := xorTag(c.sha256sum(toID[:]), c.localnode.ID())
  277. headsize := len(tag) + len(headEnc)
  278. headbuf := make([]byte, headsize)
  279. copy(headbuf[:], tag[:])
  280. copy(headbuf[len(tag):], headEnc)
  281. // Encrypt the body.
  282. enc, err = encryptGCM(headbuf, writeKey, nonce, body.Bytes(), tag[:])
  283. return enc, nonce, err
  284. }
  285. // encodeAuthHeader creates the auth header on a call packet following WHOAREYOU.
  286. func (c *wireCodec) makeAuthHeader(nonce []byte, challenge *whoareyouV5) (*authHeaderList, *handshakeSecrets, error) {
  287. resp := &authResponse{Version: 5}
  288. // Add our record to response if it's newer than what remote
  289. // side has.
  290. ln := c.localnode.Node()
  291. if challenge.RecordSeq < ln.Seq() {
  292. resp.Record = ln.Record()
  293. }
  294. // Create the ephemeral key. This needs to be first because the
  295. // key is part of the ID nonce signature.
  296. var remotePubkey = new(ecdsa.PublicKey)
  297. if err := challenge.node.Load((*enode.Secp256k1)(remotePubkey)); err != nil {
  298. return nil, nil, fmt.Errorf("can't find secp256k1 key for recipient")
  299. }
  300. ephkey, err := crypto.GenerateKey()
  301. if err != nil {
  302. return nil, nil, fmt.Errorf("can't generate ephemeral key")
  303. }
  304. ephpubkey := encodePubkey(&ephkey.PublicKey)
  305. // Add ID nonce signature to response.
  306. idsig, err := c.signIDNonce(challenge.IDNonce[:], ephpubkey[:])
  307. if err != nil {
  308. return nil, nil, fmt.Errorf("can't sign: %v", err)
  309. }
  310. resp.Signature = idsig
  311. // Create session keys.
  312. sec := c.deriveKeys(c.localnode.ID(), challenge.node.ID(), ephkey, remotePubkey, challenge)
  313. if sec == nil {
  314. return nil, nil, fmt.Errorf("key derivation failed")
  315. }
  316. // Encrypt the authentication response and assemble the auth header.
  317. respRLP, err := rlp.EncodeToBytes(resp)
  318. if err != nil {
  319. return nil, nil, fmt.Errorf("can't encode auth response: %v", err)
  320. }
  321. respEnc, err := encryptGCM(nil, sec.authRespKey, zeroNonce, respRLP, nil)
  322. if err != nil {
  323. return nil, nil, fmt.Errorf("can't encrypt auth response: %v", err)
  324. }
  325. head := &authHeaderList{
  326. Auth: nonce,
  327. Scheme: authSchemeName,
  328. IDNonce: challenge.IDNonce,
  329. EphemeralKey: ephpubkey[:],
  330. Response: respEnc,
  331. }
  332. return head, sec, err
  333. }
  334. // deriveKeys generates session keys using elliptic-curve Diffie-Hellman key agreement.
  335. func (c *wireCodec) deriveKeys(n1, n2 enode.ID, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, challenge *whoareyouV5) *handshakeSecrets {
  336. eph := ecdh(priv, pub)
  337. if eph == nil {
  338. return nil
  339. }
  340. info := []byte("discovery v5 key agreement")
  341. info = append(info, n1[:]...)
  342. info = append(info, n2[:]...)
  343. kdf := hkdf.New(sha256.New, eph, challenge.IDNonce[:], info)
  344. sec := handshakeSecrets{
  345. writeKey: make([]byte, aesKeySize),
  346. readKey: make([]byte, aesKeySize),
  347. authRespKey: make([]byte, aesKeySize),
  348. }
  349. kdf.Read(sec.writeKey)
  350. kdf.Read(sec.readKey)
  351. kdf.Read(sec.authRespKey)
  352. for i := range eph {
  353. eph[i] = 0
  354. }
  355. return &sec
  356. }
  357. // signIDNonce creates the ID nonce signature.
  358. func (c *wireCodec) signIDNonce(nonce, ephkey []byte) ([]byte, error) {
  359. idsig, err := crypto.Sign(c.idNonceHash(nonce, ephkey), c.privkey)
  360. if err != nil {
  361. return nil, fmt.Errorf("can't sign: %v", err)
  362. }
  363. return idsig[:len(idsig)-1], nil // remove recovery ID
  364. }
  365. // idNonceHash computes the hash of id nonce with prefix.
  366. func (c *wireCodec) idNonceHash(nonce, ephkey []byte) []byte {
  367. h := c.sha256reset()
  368. h.Write([]byte(idNoncePrefix))
  369. h.Write(nonce)
  370. h.Write(ephkey)
  371. return h.Sum(nil)
  372. }
  373. // decode decodes a discovery packet.
  374. func (c *wireCodec) decode(input []byte, addr string) (enode.ID, *enode.Node, packetV5, error) {
  375. // Delete timed-out handshakes. This must happen before decoding to avoid
  376. // processing the same handshake twice.
  377. c.sc.handshakeGC()
  378. if len(input) < 32 {
  379. return enode.ID{}, nil, nil, errTooShort
  380. }
  381. if bytes.HasPrefix(input, c.myWhoareyouMagic) {
  382. p, err := c.decodeWhoareyou(input)
  383. return enode.ID{}, nil, p, err
  384. }
  385. sender := xorTag(input[:32], c.myChtagHash)
  386. p, n, err := c.decodeEncrypted(sender, addr, input)
  387. return sender, n, p, err
  388. }
  389. // decodeWhoareyou decode a WHOAREYOU packet.
  390. func (c *wireCodec) decodeWhoareyou(input []byte) (packetV5, error) {
  391. packet := new(whoareyouV5)
  392. err := rlp.DecodeBytes(input[32:], packet)
  393. return packet, err
  394. }
  395. // decodeEncrypted decodes an encrypted discovery packet.
  396. func (c *wireCodec) decodeEncrypted(fromID enode.ID, fromAddr string, input []byte) (packetV5, *enode.Node, error) {
  397. // Decode packet header.
  398. var head authHeader
  399. r := bytes.NewReader(input[32:])
  400. err := rlp.Decode(r, &head)
  401. if err != nil {
  402. return nil, nil, err
  403. }
  404. // Decrypt and process auth response.
  405. readKey, node, err := c.decodeAuth(fromID, fromAddr, &head)
  406. if err != nil {
  407. return nil, nil, err
  408. }
  409. // Decrypt and decode the packet body.
  410. headsize := len(input) - r.Len()
  411. bodyEnc := input[headsize:]
  412. body, err := decryptGCM(readKey, head.Auth, bodyEnc, input[:32])
  413. if err != nil {
  414. if !head.isHandshake {
  415. // Can't decrypt, start handshake.
  416. return &unknownV5{AuthTag: head.Auth}, nil, nil
  417. }
  418. return nil, nil, fmt.Errorf("handshake failed: %v", err)
  419. }
  420. if len(body) == 0 {
  421. return nil, nil, errTooShort
  422. }
  423. p, err := decodePacketBodyV5(body[0], body[1:])
  424. return p, node, err
  425. }
  426. // decodeAuth processes an auth header.
  427. func (c *wireCodec) decodeAuth(fromID enode.ID, fromAddr string, head *authHeader) ([]byte, *enode.Node, error) {
  428. if !head.isHandshake {
  429. return c.sc.readKey(fromID, fromAddr), nil, nil
  430. }
  431. // Remote is attempting handshake. Verify against our last WHOAREYOU.
  432. challenge := c.sc.getHandshake(fromID, fromAddr)
  433. if challenge == nil {
  434. return nil, nil, errUnexpectedHandshake
  435. }
  436. if head.IDNonce != challenge.IDNonce {
  437. return nil, nil, errHandshakeNonceMismatch
  438. }
  439. sec, n, err := c.decodeAuthResp(fromID, fromAddr, &head.authHeaderList, challenge)
  440. if err != nil {
  441. return nil, n, err
  442. }
  443. // Swap keys to match remote.
  444. sec.readKey, sec.writeKey = sec.writeKey, sec.readKey
  445. c.sc.storeNewSession(fromID, fromAddr, sec.readKey, sec.writeKey)
  446. c.sc.deleteHandshake(fromID, fromAddr)
  447. return sec.readKey, n, err
  448. }
  449. // decodeAuthResp decodes and verifies an authentication response.
  450. func (c *wireCodec) decodeAuthResp(fromID enode.ID, fromAddr string, head *authHeaderList, challenge *whoareyouV5) (*handshakeSecrets, *enode.Node, error) {
  451. // Decrypt / decode the response.
  452. if head.Scheme != authSchemeName {
  453. return nil, nil, errUnknownAuthScheme
  454. }
  455. ephkey := head.ephemeralKey(c.privkey.Curve)
  456. if ephkey == nil {
  457. return nil, nil, errInvalidAuthKey
  458. }
  459. sec := c.deriveKeys(fromID, c.localnode.ID(), c.privkey, ephkey, challenge)
  460. respPT, err := decryptGCM(sec.authRespKey, zeroNonce, head.Response, nil)
  461. if err != nil {
  462. return nil, nil, fmt.Errorf("can't decrypt auth response header: %v", err)
  463. }
  464. var resp authResponse
  465. if err := rlp.DecodeBytes(respPT, &resp); err != nil {
  466. return nil, nil, fmt.Errorf("invalid auth response: %v", err)
  467. }
  468. // Verify response node record. The remote node should include the record
  469. // if we don't have one or if ours is older than the latest version.
  470. node := challenge.node
  471. if resp.Record != nil {
  472. if node == nil || node.Seq() < resp.Record.Seq() {
  473. n, err := enode.New(enode.ValidSchemes, resp.Record)
  474. if err != nil {
  475. return nil, nil, fmt.Errorf("invalid node record: %v", err)
  476. }
  477. if n.ID() != fromID {
  478. return nil, nil, fmt.Errorf("record in auth respose has wrong ID: %v", n.ID())
  479. }
  480. node = n
  481. }
  482. }
  483. if node == nil {
  484. return nil, nil, errNoRecord
  485. }
  486. // Verify ID nonce signature.
  487. err = c.verifyIDSignature(challenge.IDNonce[:], head.EphemeralKey, resp.Signature, node)
  488. if err != nil {
  489. return nil, nil, err
  490. }
  491. return sec, node, nil
  492. }
  493. // verifyIDSignature checks that signature over idnonce was made by the node with given record.
  494. func (c *wireCodec) verifyIDSignature(nonce, ephkey, sig []byte, n *enode.Node) error {
  495. switch idscheme := n.Record().IdentityScheme(); idscheme {
  496. case "v4":
  497. var pk ecdsa.PublicKey
  498. n.Load((*enode.Secp256k1)(&pk)) // cannot fail because record is valid
  499. if !crypto.VerifySignature(crypto.FromECDSAPub(&pk), c.idNonceHash(nonce, ephkey), sig) {
  500. return errInvalidNonceSig
  501. }
  502. return nil
  503. default:
  504. return fmt.Errorf("can't verify ID nonce signature against scheme %q", idscheme)
  505. }
  506. }
  507. // decodePacketBody decodes the body of an encrypted discovery packet.
  508. func decodePacketBodyV5(ptype byte, body []byte) (packetV5, error) {
  509. var dec packetV5
  510. switch ptype {
  511. case p_pingV5:
  512. dec = new(pingV5)
  513. case p_pongV5:
  514. dec = new(pongV5)
  515. case p_findnodeV5:
  516. dec = new(findnodeV5)
  517. case p_nodesV5:
  518. dec = new(nodesV5)
  519. case p_requestTicketV5:
  520. dec = new(requestTicketV5)
  521. case p_ticketV5:
  522. dec = new(ticketV5)
  523. case p_regtopicV5:
  524. dec = new(regtopicV5)
  525. case p_regconfirmationV5:
  526. dec = new(regconfirmationV5)
  527. case p_topicqueryV5:
  528. dec = new(topicqueryV5)
  529. default:
  530. return nil, fmt.Errorf("unknown packet type %d", ptype)
  531. }
  532. if err := rlp.DecodeBytes(body, dec); err != nil {
  533. return nil, err
  534. }
  535. return dec, nil
  536. }
  537. // sha256reset returns the shared hash instance.
  538. func (c *wireCodec) sha256reset() hash.Hash {
  539. c.sha256.Reset()
  540. return c.sha256
  541. }
  542. // sha256sum computes sha256 on the concatenation of inputs.
  543. func (c *wireCodec) sha256sum(inputs ...[]byte) []byte {
  544. c.sha256.Reset()
  545. for _, b := range inputs {
  546. c.sha256.Write(b)
  547. }
  548. return c.sha256.Sum(nil)
  549. }
  550. func xorTag(a []byte, b enode.ID) enode.ID {
  551. var r enode.ID
  552. for i := range r {
  553. r[i] = a[i] ^ b[i]
  554. }
  555. return r
  556. }
  557. // ecdh creates a shared secret.
  558. func ecdh(privkey *ecdsa.PrivateKey, pubkey *ecdsa.PublicKey) []byte {
  559. secX, secY := pubkey.ScalarMult(pubkey.X, pubkey.Y, privkey.D.Bytes())
  560. if secX == nil {
  561. return nil
  562. }
  563. sec := make([]byte, 33)
  564. sec[0] = 0x02 | byte(secY.Bit(0))
  565. math.ReadBits(secX, sec[1:])
  566. return sec
  567. }
  568. // encryptGCM encrypts pt using AES-GCM with the given key and nonce.
  569. func encryptGCM(dest, key, nonce, pt, authData []byte) ([]byte, error) {
  570. block, err := aes.NewCipher(key)
  571. if err != nil {
  572. panic(fmt.Errorf("can't create block cipher: %v", err))
  573. }
  574. aesgcm, err := cipher.NewGCMWithNonceSize(block, gcmNonceSize)
  575. if err != nil {
  576. panic(fmt.Errorf("can't create GCM: %v", err))
  577. }
  578. return aesgcm.Seal(dest, nonce, pt, authData), nil
  579. }
  580. // decryptGCM decrypts ct using AES-GCM with the given key and nonce.
  581. func decryptGCM(key, nonce, ct, authData []byte) ([]byte, error) {
  582. block, err := aes.NewCipher(key)
  583. if err != nil {
  584. return nil, fmt.Errorf("can't create block cipher: %v", err)
  585. }
  586. if len(nonce) != gcmNonceSize {
  587. return nil, fmt.Errorf("invalid GCM nonce size: %d", len(nonce))
  588. }
  589. aesgcm, err := cipher.NewGCMWithNonceSize(block, gcmNonceSize)
  590. if err != nil {
  591. return nil, fmt.Errorf("can't create GCM: %v", err)
  592. }
  593. pt := make([]byte, 0, len(ct))
  594. return aesgcm.Open(pt, nonce, ct, authData)
  595. }