rlpx.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  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. // Package rlpx implements the RLPx transport protocol.
  17. package rlpx
  18. import (
  19. "bytes"
  20. "crypto/aes"
  21. "crypto/cipher"
  22. "crypto/ecdsa"
  23. "crypto/elliptic"
  24. "crypto/hmac"
  25. "crypto/rand"
  26. "encoding/binary"
  27. "errors"
  28. "fmt"
  29. "hash"
  30. "io"
  31. mrand "math/rand"
  32. "net"
  33. "time"
  34. "github.com/ethereum/go-ethereum/crypto"
  35. "github.com/ethereum/go-ethereum/crypto/ecies"
  36. "github.com/ethereum/go-ethereum/rlp"
  37. "github.com/golang/snappy"
  38. "golang.org/x/crypto/sha3"
  39. )
  40. // Conn is an RLPx network connection. It wraps a low-level network connection. The
  41. // underlying connection should not be used for other activity when it is wrapped by Conn.
  42. //
  43. // Before sending messages, a handshake must be performed by calling the Handshake method.
  44. // This type is not generally safe for concurrent use, but reading and writing of messages
  45. // may happen concurrently after the handshake.
  46. type Conn struct {
  47. dialDest *ecdsa.PublicKey
  48. conn net.Conn
  49. session *sessionState
  50. // These are the buffers for snappy compression.
  51. // Compression is enabled if they are non-nil.
  52. snappyReadBuffer []byte
  53. snappyWriteBuffer []byte
  54. }
  55. // sessionState contains the session keys.
  56. type sessionState struct {
  57. enc cipher.Stream
  58. dec cipher.Stream
  59. egressMAC hashMAC
  60. ingressMAC hashMAC
  61. rbuf readBuffer
  62. wbuf writeBuffer
  63. }
  64. // hashMAC holds the state of the RLPx v4 MAC contraption.
  65. type hashMAC struct {
  66. cipher cipher.Block
  67. hash hash.Hash
  68. aesBuffer [16]byte
  69. hashBuffer [32]byte
  70. seedBuffer [32]byte
  71. }
  72. func newHashMAC(cipher cipher.Block, h hash.Hash) hashMAC {
  73. m := hashMAC{cipher: cipher, hash: h}
  74. if cipher.BlockSize() != len(m.aesBuffer) {
  75. panic(fmt.Errorf("invalid MAC cipher block size %d", cipher.BlockSize()))
  76. }
  77. if h.Size() != len(m.hashBuffer) {
  78. panic(fmt.Errorf("invalid MAC digest size %d", h.Size()))
  79. }
  80. return m
  81. }
  82. // NewConn wraps the given network connection. If dialDest is non-nil, the connection
  83. // behaves as the initiator during the handshake.
  84. func NewConn(conn net.Conn, dialDest *ecdsa.PublicKey) *Conn {
  85. return &Conn{
  86. dialDest: dialDest,
  87. conn: conn,
  88. }
  89. }
  90. // SetSnappy enables or disables snappy compression of messages. This is usually called
  91. // after the devp2p Hello message exchange when the negotiated version indicates that
  92. // compression is available on both ends of the connection.
  93. func (c *Conn) SetSnappy(snappy bool) {
  94. if snappy {
  95. c.snappyReadBuffer = []byte{}
  96. c.snappyWriteBuffer = []byte{}
  97. } else {
  98. c.snappyReadBuffer = nil
  99. c.snappyWriteBuffer = nil
  100. }
  101. }
  102. // SetReadDeadline sets the deadline for all future read operations.
  103. func (c *Conn) SetReadDeadline(time time.Time) error {
  104. return c.conn.SetReadDeadline(time)
  105. }
  106. // SetWriteDeadline sets the deadline for all future write operations.
  107. func (c *Conn) SetWriteDeadline(time time.Time) error {
  108. return c.conn.SetWriteDeadline(time)
  109. }
  110. // SetDeadline sets the deadline for all future read and write operations.
  111. func (c *Conn) SetDeadline(time time.Time) error {
  112. return c.conn.SetDeadline(time)
  113. }
  114. // Read reads a message from the connection.
  115. // The returned data buffer is valid until the next call to Read.
  116. func (c *Conn) Read() (code uint64, data []byte, wireSize int, err error) {
  117. if c.session == nil {
  118. panic("can't ReadMsg before handshake")
  119. }
  120. frame, err := c.session.readFrame(c.conn)
  121. if err != nil {
  122. return 0, nil, 0, err
  123. }
  124. code, data, err = rlp.SplitUint64(frame)
  125. if err != nil {
  126. return 0, nil, 0, fmt.Errorf("invalid message code: %v", err)
  127. }
  128. wireSize = len(data)
  129. // If snappy is enabled, verify and decompress message.
  130. if c.snappyReadBuffer != nil {
  131. var actualSize int
  132. actualSize, err = snappy.DecodedLen(data)
  133. if err != nil {
  134. return code, nil, 0, err
  135. }
  136. if actualSize > maxUint24 {
  137. return code, nil, 0, errPlainMessageTooLarge
  138. }
  139. c.snappyReadBuffer = growslice(c.snappyReadBuffer, actualSize)
  140. data, err = snappy.Decode(c.snappyReadBuffer, data)
  141. }
  142. return code, data, wireSize, err
  143. }
  144. func (h *sessionState) readFrame(conn io.Reader) ([]byte, error) {
  145. h.rbuf.reset()
  146. // Read the frame header.
  147. header, err := h.rbuf.read(conn, 32)
  148. if err != nil {
  149. return nil, err
  150. }
  151. // Verify header MAC.
  152. wantHeaderMAC := h.ingressMAC.computeHeader(header[:16])
  153. if !hmac.Equal(wantHeaderMAC, header[16:]) {
  154. return nil, errors.New("bad header MAC")
  155. }
  156. // Decrypt the frame header to get the frame size.
  157. h.dec.XORKeyStream(header[:16], header[:16])
  158. fsize := readUint24(header[:16])
  159. // Frame size rounded up to 16 byte boundary for padding.
  160. rsize := fsize
  161. if padding := fsize % 16; padding > 0 {
  162. rsize += 16 - padding
  163. }
  164. // Read the frame content.
  165. frame, err := h.rbuf.read(conn, int(rsize))
  166. if err != nil {
  167. return nil, err
  168. }
  169. // Validate frame MAC.
  170. frameMAC, err := h.rbuf.read(conn, 16)
  171. if err != nil {
  172. return nil, err
  173. }
  174. wantFrameMAC := h.ingressMAC.computeFrame(frame)
  175. if !hmac.Equal(wantFrameMAC, frameMAC) {
  176. return nil, errors.New("bad frame MAC")
  177. }
  178. // Decrypt the frame data.
  179. h.dec.XORKeyStream(frame, frame)
  180. return frame[:fsize], nil
  181. }
  182. // Write writes a message to the connection.
  183. //
  184. // Write returns the written size of the message data. This may be less than or equal to
  185. // len(data) depending on whether snappy compression is enabled.
  186. func (c *Conn) Write(code uint64, data []byte) (uint32, error) {
  187. if c.session == nil {
  188. panic("can't WriteMsg before handshake")
  189. }
  190. if len(data) > maxUint24 {
  191. return 0, errPlainMessageTooLarge
  192. }
  193. if c.snappyWriteBuffer != nil {
  194. // Ensure the buffer has sufficient size.
  195. // Package snappy will allocate its own buffer if the provided
  196. // one is smaller than MaxEncodedLen.
  197. c.snappyWriteBuffer = growslice(c.snappyWriteBuffer, snappy.MaxEncodedLen(len(data)))
  198. data = snappy.Encode(c.snappyWriteBuffer, data)
  199. }
  200. wireSize := uint32(len(data))
  201. err := c.session.writeFrame(c.conn, code, data)
  202. return wireSize, err
  203. }
  204. func (h *sessionState) writeFrame(conn io.Writer, code uint64, data []byte) error {
  205. h.wbuf.reset()
  206. // Write header.
  207. fsize := rlp.IntSize(code) + len(data)
  208. if fsize > maxUint24 {
  209. return errPlainMessageTooLarge
  210. }
  211. header := h.wbuf.appendZero(16)
  212. putUint24(uint32(fsize), header)
  213. copy(header[3:], zeroHeader)
  214. h.enc.XORKeyStream(header, header)
  215. // Write header MAC.
  216. h.wbuf.Write(h.egressMAC.computeHeader(header))
  217. // Encode and encrypt the frame data.
  218. offset := len(h.wbuf.data)
  219. h.wbuf.data = rlp.AppendUint64(h.wbuf.data, code)
  220. h.wbuf.Write(data)
  221. if padding := fsize % 16; padding > 0 {
  222. h.wbuf.appendZero(16 - padding)
  223. }
  224. framedata := h.wbuf.data[offset:]
  225. h.enc.XORKeyStream(framedata, framedata)
  226. // Write frame MAC.
  227. h.wbuf.Write(h.egressMAC.computeFrame(framedata))
  228. _, err := conn.Write(h.wbuf.data)
  229. return err
  230. }
  231. // computeHeader computes the MAC of a frame header.
  232. func (m *hashMAC) computeHeader(header []byte) []byte {
  233. sum1 := m.hash.Sum(m.hashBuffer[:0])
  234. return m.compute(sum1, header)
  235. }
  236. // computeFrame computes the MAC of framedata.
  237. func (m *hashMAC) computeFrame(framedata []byte) []byte {
  238. m.hash.Write(framedata)
  239. seed := m.hash.Sum(m.seedBuffer[:0])
  240. return m.compute(seed, seed[:16])
  241. }
  242. // compute computes the MAC of a 16-byte 'seed'.
  243. //
  244. // To do this, it encrypts the current value of the hash state, then XORs the ciphertext
  245. // with seed. The obtained value is written back into the hash state and hash output is
  246. // taken again. The first 16 bytes of the resulting sum are the MAC value.
  247. //
  248. // This MAC construction is a horrible, legacy thing.
  249. func (m *hashMAC) compute(sum1, seed []byte) []byte {
  250. if len(seed) != len(m.aesBuffer) {
  251. panic("invalid MAC seed")
  252. }
  253. m.cipher.Encrypt(m.aesBuffer[:], sum1)
  254. for i := range m.aesBuffer {
  255. m.aesBuffer[i] ^= seed[i]
  256. }
  257. m.hash.Write(m.aesBuffer[:])
  258. sum2 := m.hash.Sum(m.hashBuffer[:0])
  259. return sum2[:16]
  260. }
  261. // Handshake performs the handshake. This must be called before any data is written
  262. // or read from the connection.
  263. func (c *Conn) Handshake(prv *ecdsa.PrivateKey) (*ecdsa.PublicKey, error) {
  264. var (
  265. sec Secrets
  266. err error
  267. h handshakeState
  268. )
  269. if c.dialDest != nil {
  270. sec, err = h.runInitiator(c.conn, prv, c.dialDest)
  271. } else {
  272. sec, err = h.runRecipient(c.conn, prv)
  273. }
  274. if err != nil {
  275. return nil, err
  276. }
  277. c.InitWithSecrets(sec)
  278. c.session.rbuf = h.rbuf
  279. c.session.wbuf = h.wbuf
  280. return sec.remote, err
  281. }
  282. // InitWithSecrets injects connection secrets as if a handshake had
  283. // been performed. This cannot be called after the handshake.
  284. func (c *Conn) InitWithSecrets(sec Secrets) {
  285. if c.session != nil {
  286. panic("can't handshake twice")
  287. }
  288. macc, err := aes.NewCipher(sec.MAC)
  289. if err != nil {
  290. panic("invalid MAC secret: " + err.Error())
  291. }
  292. encc, err := aes.NewCipher(sec.AES)
  293. if err != nil {
  294. panic("invalid AES secret: " + err.Error())
  295. }
  296. // we use an all-zeroes IV for AES because the key used
  297. // for encryption is ephemeral.
  298. iv := make([]byte, encc.BlockSize())
  299. c.session = &sessionState{
  300. enc: cipher.NewCTR(encc, iv),
  301. dec: cipher.NewCTR(encc, iv),
  302. egressMAC: newHashMAC(macc, sec.EgressMAC),
  303. ingressMAC: newHashMAC(macc, sec.IngressMAC),
  304. }
  305. }
  306. // Close closes the underlying network connection.
  307. func (c *Conn) Close() error {
  308. return c.conn.Close()
  309. }
  310. // Constants for the handshake.
  311. const (
  312. sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
  313. sigLen = crypto.SignatureLength // elliptic S256
  314. pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte
  315. shaLen = 32 // hash length (for nonce etc)
  316. eciesOverhead = 65 /* pubkey */ + 16 /* IV */ + 32 /* MAC */
  317. )
  318. var (
  319. // this is used in place of actual frame header data.
  320. // TODO: replace this when Msg contains the protocol type code.
  321. zeroHeader = []byte{0xC2, 0x80, 0x80}
  322. // errPlainMessageTooLarge is returned if a decompressed message length exceeds
  323. // the allowed 24 bits (i.e. length >= 16MB).
  324. errPlainMessageTooLarge = errors.New("message length >= 16MB")
  325. )
  326. // Secrets represents the connection secrets which are negotiated during the handshake.
  327. type Secrets struct {
  328. AES, MAC []byte
  329. EgressMAC, IngressMAC hash.Hash
  330. remote *ecdsa.PublicKey
  331. }
  332. // handshakeState contains the state of the encryption handshake.
  333. type handshakeState struct {
  334. initiator bool
  335. remote *ecies.PublicKey // remote-pubk
  336. initNonce, respNonce []byte // nonce
  337. randomPrivKey *ecies.PrivateKey // ecdhe-random
  338. remoteRandomPub *ecies.PublicKey // ecdhe-random-pubk
  339. rbuf readBuffer
  340. wbuf writeBuffer
  341. }
  342. // RLPx v4 handshake auth (defined in EIP-8).
  343. type authMsgV4 struct {
  344. Signature [sigLen]byte
  345. InitiatorPubkey [pubLen]byte
  346. Nonce [shaLen]byte
  347. Version uint
  348. // Ignore additional fields (forward-compatibility)
  349. Rest []rlp.RawValue `rlp:"tail"`
  350. }
  351. // RLPx v4 handshake response (defined in EIP-8).
  352. type authRespV4 struct {
  353. RandomPubkey [pubLen]byte
  354. Nonce [shaLen]byte
  355. Version uint
  356. // Ignore additional fields (forward-compatibility)
  357. Rest []rlp.RawValue `rlp:"tail"`
  358. }
  359. // runRecipient negotiates a session token on conn.
  360. // it should be called on the listening side of the connection.
  361. //
  362. // prv is the local client's private key.
  363. func (h *handshakeState) runRecipient(conn io.ReadWriter, prv *ecdsa.PrivateKey) (s Secrets, err error) {
  364. authMsg := new(authMsgV4)
  365. authPacket, err := h.readMsg(authMsg, prv, conn)
  366. if err != nil {
  367. return s, err
  368. }
  369. if err := h.handleAuthMsg(authMsg, prv); err != nil {
  370. return s, err
  371. }
  372. authRespMsg, err := h.makeAuthResp()
  373. if err != nil {
  374. return s, err
  375. }
  376. authRespPacket, err := h.sealEIP8(authRespMsg)
  377. if err != nil {
  378. return s, err
  379. }
  380. if _, err = conn.Write(authRespPacket); err != nil {
  381. return s, err
  382. }
  383. return h.secrets(authPacket, authRespPacket)
  384. }
  385. func (h *handshakeState) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) error {
  386. // Import the remote identity.
  387. rpub, err := importPublicKey(msg.InitiatorPubkey[:])
  388. if err != nil {
  389. return err
  390. }
  391. h.initNonce = msg.Nonce[:]
  392. h.remote = rpub
  393. // Generate random keypair for ECDH.
  394. // If a private key is already set, use it instead of generating one (for testing).
  395. if h.randomPrivKey == nil {
  396. h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
  397. if err != nil {
  398. return err
  399. }
  400. }
  401. // Check the signature.
  402. token, err := h.staticSharedSecret(prv)
  403. if err != nil {
  404. return err
  405. }
  406. signedMsg := xor(token, h.initNonce)
  407. remoteRandomPub, err := crypto.Ecrecover(signedMsg, msg.Signature[:])
  408. if err != nil {
  409. return err
  410. }
  411. h.remoteRandomPub, _ = importPublicKey(remoteRandomPub)
  412. return nil
  413. }
  414. // secrets is called after the handshake is completed.
  415. // It extracts the connection secrets from the handshake values.
  416. func (h *handshakeState) secrets(auth, authResp []byte) (Secrets, error) {
  417. ecdheSecret, err := h.randomPrivKey.GenerateShared(h.remoteRandomPub, sskLen, sskLen)
  418. if err != nil {
  419. return Secrets{}, err
  420. }
  421. // derive base secrets from ephemeral key agreement
  422. sharedSecret := crypto.Keccak256(ecdheSecret, crypto.Keccak256(h.respNonce, h.initNonce))
  423. aesSecret := crypto.Keccak256(ecdheSecret, sharedSecret)
  424. s := Secrets{
  425. remote: h.remote.ExportECDSA(),
  426. AES: aesSecret,
  427. MAC: crypto.Keccak256(ecdheSecret, aesSecret),
  428. }
  429. // setup sha3 instances for the MACs
  430. mac1 := sha3.NewLegacyKeccak256()
  431. mac1.Write(xor(s.MAC, h.respNonce))
  432. mac1.Write(auth)
  433. mac2 := sha3.NewLegacyKeccak256()
  434. mac2.Write(xor(s.MAC, h.initNonce))
  435. mac2.Write(authResp)
  436. if h.initiator {
  437. s.EgressMAC, s.IngressMAC = mac1, mac2
  438. } else {
  439. s.EgressMAC, s.IngressMAC = mac2, mac1
  440. }
  441. return s, nil
  442. }
  443. // staticSharedSecret returns the static shared secret, the result
  444. // of key agreement between the local and remote static node key.
  445. func (h *handshakeState) staticSharedSecret(prv *ecdsa.PrivateKey) ([]byte, error) {
  446. return ecies.ImportECDSA(prv).GenerateShared(h.remote, sskLen, sskLen)
  447. }
  448. // runInitiator negotiates a session token on conn.
  449. // it should be called on the dialing side of the connection.
  450. //
  451. // prv is the local client's private key.
  452. func (h *handshakeState) runInitiator(conn io.ReadWriter, prv *ecdsa.PrivateKey, remote *ecdsa.PublicKey) (s Secrets, err error) {
  453. h.initiator = true
  454. h.remote = ecies.ImportECDSAPublic(remote)
  455. authMsg, err := h.makeAuthMsg(prv)
  456. if err != nil {
  457. return s, err
  458. }
  459. authPacket, err := h.sealEIP8(authMsg)
  460. if err != nil {
  461. return s, err
  462. }
  463. if _, err = conn.Write(authPacket); err != nil {
  464. return s, err
  465. }
  466. authRespMsg := new(authRespV4)
  467. authRespPacket, err := h.readMsg(authRespMsg, prv, conn)
  468. if err != nil {
  469. return s, err
  470. }
  471. if err := h.handleAuthResp(authRespMsg); err != nil {
  472. return s, err
  473. }
  474. return h.secrets(authPacket, authRespPacket)
  475. }
  476. // makeAuthMsg creates the initiator handshake message.
  477. func (h *handshakeState) makeAuthMsg(prv *ecdsa.PrivateKey) (*authMsgV4, error) {
  478. // Generate random initiator nonce.
  479. h.initNonce = make([]byte, shaLen)
  480. _, err := rand.Read(h.initNonce)
  481. if err != nil {
  482. return nil, err
  483. }
  484. // Generate random keypair to for ECDH.
  485. h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
  486. if err != nil {
  487. return nil, err
  488. }
  489. // Sign known message: static-shared-secret ^ nonce
  490. token, err := h.staticSharedSecret(prv)
  491. if err != nil {
  492. return nil, err
  493. }
  494. signed := xor(token, h.initNonce)
  495. signature, err := crypto.Sign(signed, h.randomPrivKey.ExportECDSA())
  496. if err != nil {
  497. return nil, err
  498. }
  499. msg := new(authMsgV4)
  500. copy(msg.Signature[:], signature)
  501. copy(msg.InitiatorPubkey[:], crypto.FromECDSAPub(&prv.PublicKey)[1:])
  502. copy(msg.Nonce[:], h.initNonce)
  503. msg.Version = 4
  504. return msg, nil
  505. }
  506. func (h *handshakeState) handleAuthResp(msg *authRespV4) (err error) {
  507. h.respNonce = msg.Nonce[:]
  508. h.remoteRandomPub, err = importPublicKey(msg.RandomPubkey[:])
  509. return err
  510. }
  511. func (h *handshakeState) makeAuthResp() (msg *authRespV4, err error) {
  512. // Generate random nonce.
  513. h.respNonce = make([]byte, shaLen)
  514. if _, err = rand.Read(h.respNonce); err != nil {
  515. return nil, err
  516. }
  517. msg = new(authRespV4)
  518. copy(msg.Nonce[:], h.respNonce)
  519. copy(msg.RandomPubkey[:], exportPubkey(&h.randomPrivKey.PublicKey))
  520. msg.Version = 4
  521. return msg, nil
  522. }
  523. // readMsg reads an encrypted handshake message, decoding it into msg.
  524. func (h *handshakeState) readMsg(msg interface{}, prv *ecdsa.PrivateKey, r io.Reader) ([]byte, error) {
  525. h.rbuf.reset()
  526. h.rbuf.grow(512)
  527. // Read the size prefix.
  528. prefix, err := h.rbuf.read(r, 2)
  529. if err != nil {
  530. return nil, err
  531. }
  532. size := binary.BigEndian.Uint16(prefix)
  533. // Read the handshake packet.
  534. packet, err := h.rbuf.read(r, int(size))
  535. if err != nil {
  536. return nil, err
  537. }
  538. dec, err := ecies.ImportECDSA(prv).Decrypt(packet, nil, prefix)
  539. if err != nil {
  540. return nil, err
  541. }
  542. // Can't use rlp.DecodeBytes here because it rejects
  543. // trailing data (forward-compatibility).
  544. s := rlp.NewStream(bytes.NewReader(dec), 0)
  545. err = s.Decode(msg)
  546. return h.rbuf.data[:len(prefix)+len(packet)], err
  547. }
  548. // sealEIP8 encrypts a handshake message.
  549. func (h *handshakeState) sealEIP8(msg interface{}) ([]byte, error) {
  550. h.wbuf.reset()
  551. // Write the message plaintext.
  552. if err := rlp.Encode(&h.wbuf, msg); err != nil {
  553. return nil, err
  554. }
  555. // Pad with random amount of data. the amount needs to be at least 100 bytes to make
  556. // the message distinguishable from pre-EIP-8 handshakes.
  557. h.wbuf.appendZero(mrand.Intn(100) + 100)
  558. prefix := make([]byte, 2)
  559. binary.BigEndian.PutUint16(prefix, uint16(len(h.wbuf.data)+eciesOverhead))
  560. enc, err := ecies.Encrypt(rand.Reader, h.remote, h.wbuf.data, nil, prefix)
  561. return append(prefix, enc...), err
  562. }
  563. // importPublicKey unmarshals 512 bit public keys.
  564. func importPublicKey(pubKey []byte) (*ecies.PublicKey, error) {
  565. var pubKey65 []byte
  566. switch len(pubKey) {
  567. case 64:
  568. // add 'uncompressed key' flag
  569. pubKey65 = append([]byte{0x04}, pubKey...)
  570. case 65:
  571. pubKey65 = pubKey
  572. default:
  573. return nil, fmt.Errorf("invalid public key length %v (expect 64/65)", len(pubKey))
  574. }
  575. // TODO: fewer pointless conversions
  576. pub, err := crypto.UnmarshalPubkey(pubKey65)
  577. if err != nil {
  578. return nil, err
  579. }
  580. return ecies.ImportECDSAPublic(pub), nil
  581. }
  582. func exportPubkey(pub *ecies.PublicKey) []byte {
  583. if pub == nil {
  584. panic("nil pubkey")
  585. }
  586. return elliptic.Marshal(pub.Curve, pub.X, pub.Y)[1:]
  587. }
  588. func xor(one, other []byte) (xor []byte) {
  589. xor = make([]byte, len(one))
  590. for i := 0; i < len(one); i++ {
  591. xor[i] = one[i] ^ other[i]
  592. }
  593. return xor
  594. }