31 void RLPXHandshake::writeAuth()
33 clog(
NetP2PConnect) <<
"p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
44 sha3(m_ecdhe.pubkey().ref(), hepubk);
45 m_host->m_alias.pub().ref().copyTo(pubk);
46 m_nonce.ref().copyTo(nonce);
47 m_auth[m_auth.size() - 1] = 0x0;
50 auto self(shared_from_this());
51 ba::async_write(m_socket->ref(), ba::buffer(m_authCipher), [
this,
self](boost::system::error_code ec, std::size_t)
57 void RLPXHandshake::writeAck()
59 clog(
NetP2PConnect) <<
"p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
63 m_ecdhe.pubkey().ref().copyTo(epubk);
64 m_nonce.ref().copyTo(nonce);
65 m_ack[m_ack.size() - 1] = 0x0;
68 auto self(shared_from_this());
69 ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [
this,
self](boost::system::error_code ec, std::size_t)
75 void RLPXHandshake::writeAckEIP8()
77 clog(
NetP2PConnect) <<
"p2p.connect.ingress sending EIP-8 ack to " << m_socket->remoteEndpoint();
85 int padAmount(rand()%100 + 100);
86 m_ack.resize(m_ack.size() + padAmount, 0);
89 toBigEndian<uint16_t>(m_ack.size() + c_eciesOverhead,
prefix);
91 m_ackCipher.insert(m_ackCipher.begin(), prefix.begin(), prefix.end());
93 auto self(shared_from_this());
94 ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [
this,
self](boost::system::error_code ec, std::size_t)
100 void RLPXHandshake::setAuthValues(
Signature const& _sig,
Public const& _remotePubk,
h256 const& _remoteNonce, uint64_t _remoteVersion)
102 _remotePubk.
ref().
copyTo(m_remote.ref());
103 _remoteNonce.
ref().
copyTo(m_remoteNonce.ref());
104 m_remoteVersion = _remoteVersion;
110 void RLPXHandshake::readAuth()
112 clog(
NetP2PConnect) <<
"p2p.connect.ingress receiving auth from " << m_socket->remoteEndpoint();
113 m_authCipher.resize(307);
114 auto self(shared_from_this());
115 ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [
this,
self](boost::system::error_code ec, std::size_t)
125 setAuthValues(sig, pubk, nonce, 4);
133 void RLPXHandshake::readAuthEIP8()
135 assert(m_authCipher.size() == 307);
136 uint16_t
size(m_authCipher[0]<<8 | m_authCipher[1]);
137 clog(
NetP2PConnect) <<
"p2p.connect.ingress receiving " << size <<
"bytes EIP-8 auth from " << m_socket->remoteEndpoint();
138 m_authCipher.resize((
size_t)size + 2);
139 auto rest = ba::buffer(ba::buffer(m_authCipher) + 307);
140 auto self(shared_from_this());
141 ba::async_read(m_socket->ref(), rest, [
this,
self](boost::system::error_code ec, std::size_t)
148 RLP rlp(m_auth, RLP::ThrowOnFail | RLP::FailIfTooSmall);
150 rlp[0].toHash<Signature>(),
151 rlp[1].toHash<Public>(),
152 rlp[2].toHash<h256>(),
153 rlp[3].toInt<uint64_t>()
155 m_nextState = AckAuthEIP8;
160 clog(
NetP2PConnect) <<
"p2p.connect.ingress auth decrypt failed for" << m_socket->remoteEndpoint();
167 void RLPXHandshake::readAck()
169 clog(
NetP2PConnect) <<
"p2p.connect.egress receiving ack from " << m_socket->remoteEndpoint();
170 m_ackCipher.resize(210);
171 auto self(shared_from_this());
172 ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [
this,
self](boost::system::error_code ec, std::size_t)
188 void RLPXHandshake::readAckEIP8()
190 assert(m_ackCipher.size() == 210);
191 uint16_t
size(m_ackCipher[0]<<8 | m_ackCipher[1]);
192 clog(
NetP2PConnect) <<
"p2p.connect.egress receiving " << size <<
"bytes EIP-8 ack from " << m_socket->remoteEndpoint();
193 m_ackCipher.resize((
size_t)size + 2);
194 auto rest = ba::buffer(ba::buffer(m_ackCipher) + 210);
195 auto self(shared_from_this());
196 ba::async_read(m_socket->ref(), rest, [
this,
self](boost::system::error_code ec, std::size_t)
203 RLP rlp(m_ack, RLP::ThrowOnFail | RLP::FailIfTooSmall);
206 m_remoteVersion = rlp[2].
toInt<uint64_t>();
211 clog(
NetP2PConnect) <<
"p2p.connect.egress ack decrypt failed for " << m_socket->remoteEndpoint();
218 void RLPXHandshake::cancel()
221 m_idleTimer.cancel();
228 auto connected = m_socket->isConnected();
229 if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
230 clog(
NetP2PConnect) <<
"Disconnecting " << m_socket->remoteEndpoint() <<
" (Handshake Failed)";
237 void RLPXHandshake::transition(boost::system::error_code _ech)
240 m_idleTimer.cancel();
242 if (_ech || m_nextState ==
Error || m_cancel)
248 auto self(shared_from_this());
249 assert(m_nextState != StartSession);
250 m_idleTimer.expires_from_now(c_timeout);
251 m_idleTimer.async_wait([
this,
self](boost::system::error_code
const& _ec)
255 if (!m_socket->remoteEndpoint().address().is_unspecified())
256 clog(
NetP2PConnect) <<
"Disconnecting " << m_socket->remoteEndpoint() <<
" (Handshake Timeout)";
261 if (m_nextState == New)
263 m_nextState = AckAuth;
269 else if (m_nextState == AckAuth)
271 m_nextState = WriteHello;
277 else if (m_nextState == AckAuthEIP8)
279 m_nextState = WriteHello;
285 else if (m_nextState == WriteHello)
287 m_nextState = ReadHello;
288 clog(
NetP2PConnect) << (m_originated ?
"p2p.connect.egress" :
"p2p.connect.ingress") <<
"sending capabilities handshake";
297 << m_host->m_clientVersion
299 << m_host->listenPort()
304 m_io->writeSingleFramePacket(&packet, m_handshakeOutBuffer);
305 ba::async_write(m_socket->ref(), ba::buffer(m_handshakeOutBuffer), [
this,
self](boost::system::error_code ec, std::size_t)
310 else if (m_nextState == ReadHello)
314 m_nextState = StartSession;
317 unsigned const handshakeSize = 32;
318 m_handshakeInBuffer.resize(handshakeSize);
319 ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, handshakeSize), [
this,
self](boost::system::error_code ec, std::size_t)
327 clog(
NetP2PWarn) <<
"Internal error in handshake: RLPXFrameCoder disappeared.";
334 if (!m_io->authAndDecryptHeader(
bytesRef(m_handshakeInBuffer.data(), m_handshakeInBuffer.size())))
341 clog(
NetP2PNote) << (m_originated ?
"p2p.connect.egress" :
"p2p.connect.ingress") <<
"recvd hello header";
344 bytes& header = m_handshakeInBuffer;
345 uint32_t frameSize = (uint32_t)(header[2]) | (uint32_t)(header[1])<<8 | (uint32_t)(header[0])<<16;
346 if (frameSize > 1024)
349 clog(
NetP2PWarn) << (m_originated ?
"p2p.connect.egress" :
"p2p.connect.ingress") <<
"hello frame is too large" << frameSize;
360 m_handshakeInBuffer.resize(frameSize + ((16 - (frameSize % 16)) % 16) +
h128::size);
361 ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, m_handshakeInBuffer.size()), [
this,
self, headerRLP](boost::system::error_code ec, std::size_t)
363 m_idleTimer.cancel();
371 clog(
NetP2PWarn) <<
"Internal error in handshake: RLPXFrameCoder disappeared.";
377 bytesRef frame(&m_handshakeInBuffer);
378 if (!m_io->authAndDecryptFrame(frame))
380 clog(
NetTriviaSummary) << (m_originated ?
"p2p.connect.egress" :
"p2p.connect.ingress") <<
"hello frame: decrypt failed";
389 clog(
NetTriviaSummary) << (m_originated ?
"p2p.connect.egress" :
"p2p.connect.ingress") <<
"hello frame: invalid packet type";
395 clog(
NetTriviaSummary) << (m_originated ?
"p2p.connect.egress" :
"p2p.connect.ingress") <<
"hello frame: success. starting session.";
398 RLP rlp(frame.
cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
399 m_host->startPeerSession(m_remote,
rlp, move(m_io), m_socket);
401 catch (std::exception
const& _e)
403 clog(
NetWarn) <<
"Handshake causing an exception:" << _e.what();
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
bool error(const char *fmt, const Args &...args)
A modifiable reference to an existing object or vector in memory.
vector_ref< _T const > ref(_T const &_t)
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
RLPStream & append(unsigned _s)
Append given datum to the byte stream.
bytes const & out() const
Read the byte stream.
bool decryptECIES(Secret const &_k, bytesConstRef _cipher, bytes &o_plaintext)
Decrypt payload using ECIES standard with AES128-CTR.
std::hash for asio::adress
assert(len-trim+(2 *lenIndices)<=WIDTH)
void encryptECIES(Public const &_k, bytesConstRef _plain, bytes &o_cipher)
Encrypt payload using ECIES standard with AES128-CTR.
const unsigned c_protocolVersion
Peer network protocol version.
vector_ref< _T > cropped(size_t _begin, size_t _count) const
_N toHash(int _flags=Strict) const
FixedHash< T > const & makeInsecure() const
Public recover(Signature const &_sig, h256 const &_hash)
Recovers Public key from signed message hash.
std::vector< byte > bytes
vector_ref< byte const > bytesConstRef
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
RLPStream & appendList(size_t _items)
Appends a list.
Signature sign(Secret const &_k, h256 const &_hash)
Returns siganture of message hash.
uint8_t const size_t const size
void copyTo(vector_ref< typename std::remove_const< _T >::type > _t) const
Copies the contents of this vector_ref to the contents of _t, up to the max size of _t...
void agree(Secret const &_s, Public const &_r, Secret &o_s)
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
void swapOut(bytes &_dest)
Swap the contents of the output stream out for some other byte array.
_T toInt(int _flags=Strict) const
Converts to int of type given; if isString(), decodes as big-endian bytestream.
Class for writing to an RLP bytestream.
Encoder/decoder transport for RLPx connection established by RLPXHandshake.
Class for interpreting Recursive Linear-Prefix Data.