use crc32 for node ID restriction scheme
This commit is contained in:
parent
27adb1fc44
commit
b431ef7836
|
@ -63,20 +63,26 @@ In order to avoid the number node IDs controlled to grow linearly by the number
|
||||||
of IPs, as well as allowing more than one node ID per external IP, the node
|
of IPs, as well as allowing more than one node ID per external IP, the node
|
||||||
ID can be restricted at each class level of the IP.
|
ID can be restricted at each class level of the IP.
|
||||||
|
|
||||||
|
Another important property of the restriction put on node IDs is that the
|
||||||
|
distribution of the IDs remoain uniform. This is why CRC32 was chosen
|
||||||
|
as the hash function. See `comparisons of hash functions`__.
|
||||||
|
|
||||||
|
__ http://blog.libtorrent.org/2012/12/dht-security/
|
||||||
|
|
||||||
The expression to calculate a valid ID prefix (from an IPv4 address) is::
|
The expression to calculate a valid ID prefix (from an IPv4 address) is::
|
||||||
|
|
||||||
sha1((ip & 0x01071f7f) .. r)
|
crc32((ip & 0x01071f7f) .. r)
|
||||||
|
|
||||||
And for an IPv6 address (``ip`` is the high 64 bits of the address)::
|
And for an IPv6 address (``ip`` is the high 64 bits of the address)::
|
||||||
|
|
||||||
sha1((ip & 0x000103070f1f3f7f) .. r)
|
crc32((ip & 0x000103070f1f3f7f) .. r)
|
||||||
|
|
||||||
``r`` is a random number in the range [0, 7]. The resulting integer,
|
``r`` is a random number in the range [0, 7]. The resulting integer,
|
||||||
representing the masked IP address is supposed to be big-endian before
|
representing the masked IP address is supposed to be big-endian before
|
||||||
hashed. The ".." means concatenation.
|
hashed. The ".." means concatenation.
|
||||||
|
|
||||||
The details of implementing this is to evaluate the expression, store the
|
The details of implementing this is to evaluate the expression, store the
|
||||||
result in a big endian 64 bit integer and hash those 8 bytes with SHA-1.
|
result in a big endian 64 bit integer and hash those 8 bytes with CRC32.
|
||||||
|
|
||||||
The first 4 bytes of the node ID used in the DHT MUST match the first 4
|
The first 4 bytes of the node ID used in the DHT MUST match the first 4
|
||||||
bytes in the resulting hash. The last byte of the hash MUST match the
|
bytes in the resulting hash. The last byte of the hash MUST match the
|
||||||
|
@ -98,13 +104,17 @@ Example code code for calculating a valid node ID::
|
||||||
for (int i = 0; i < num_octets; ++i)
|
for (int i = 0; i < num_octets; ++i)
|
||||||
ip[i] &= mask[i];
|
ip[i] &= mask[i];
|
||||||
|
|
||||||
SHA_CTX ctx;
|
|
||||||
SHA1_Init(&ctx);
|
|
||||||
SHA1_Update(&ctx, (unsigned char*)ip, num_octets);
|
|
||||||
uint32_t rand = rand() & 0xff;
|
uint32_t rand = rand() & 0xff;
|
||||||
uint8_t r = rand & 0x7;
|
uint8_t r = rand & 0x7;
|
||||||
SHA1_Update(&ctx, (unsigned char*)&r, 1);
|
|
||||||
SHA1_Final(&ctx, node_id);
|
uint32_t crc = crc32(0, NULL, 0);
|
||||||
|
crc = crc32(crc, ip, num_octets);
|
||||||
|
crc = crc32(crc, &r, 1);
|
||||||
|
|
||||||
|
node_id[0] = (crc >> 24) & 0xff;
|
||||||
|
node_id[1] = (crc >> 16) & 0xff;
|
||||||
|
node_id[2] = (crc >> 8) & 0xff;
|
||||||
|
node_id[3] = crc & 0xff;
|
||||||
for (int i = 4; i < 19; ++i) node_id[i] = std::rand();
|
for (int i = 4; i < 19; ++i) node_id[i] = std::rand();
|
||||||
node_id[19] = rand;
|
node_id[19] = rand;
|
||||||
|
|
||||||
|
@ -114,11 +124,11 @@ test vectors:
|
||||||
|
|
||||||
IP rand example node ID
|
IP rand example node ID
|
||||||
============ ===== ==========================================
|
============ ===== ==========================================
|
||||||
124.31.75.21 1 **f766f9f5** 0c5d6a4ec8a88e4c6ab4c28b95eee4 **01**
|
124.31.75.21 1 **1712f6c7** 0c5d6a4ec8a88e4c6ab4c28b95eee4 **01**
|
||||||
21.75.31.124 86 **7ee04779** 4e7a08645677bbd1cfe7d8f956d532 **56**
|
21.75.31.124 86 **946406c1** 4e7a08645677bbd1cfe7d8f956d532 **56**
|
||||||
65.23.51.170 22 **76a626ff** bc8f112a3d426c84764f8c2a1150e6 **16**
|
65.23.51.170 22 **fefd9220** bc8f112a3d426c84764f8c2a1150e6 **16**
|
||||||
84.124.73.14 65 **beb4e619** 1bb1fe518101ceef99462b947a01ff **41**
|
84.124.73.14 65 **af1546dd** 1bb1fe518101ceef99462b947a01ff **41**
|
||||||
43.213.53.83 90 **ace5613a** 5b7c4be0237986d5243b87aa6d5130 **5a**
|
43.213.53.83 90 **a9e920bf** 5b7c4be0237986d5243b87aa6d5130 **5a**
|
||||||
|
|
||||||
The bold parts of the node ID are the important parts. The rest are
|
The bold parts of the node ID are the important parts. The rest are
|
||||||
random numbers.
|
random numbers.
|
||||||
|
|
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <boost/crc.hpp>
|
||||||
|
|
||||||
#include "libtorrent/kademlia/node_id.hpp"
|
#include "libtorrent/kademlia/node_id.hpp"
|
||||||
#include "libtorrent/hasher.hpp"
|
#include "libtorrent/hasher.hpp"
|
||||||
|
@ -129,11 +130,19 @@ node_id generate_id_impl(address const& ip_, boost::uint32_t r)
|
||||||
for (int i = 0; i < num_octets; ++i)
|
for (int i = 0; i < num_octets; ++i)
|
||||||
ip[i] &= mask[i];
|
ip[i] &= mask[i];
|
||||||
|
|
||||||
hasher h;
|
|
||||||
h.update((char*)ip, num_octets);
|
|
||||||
boost::uint8_t rand = r & 0x7;
|
boost::uint8_t rand = r & 0x7;
|
||||||
h.update((char*)&rand, 1);
|
|
||||||
node_id id = h.final();
|
boost::crc_32_type crc;
|
||||||
|
crc.process_block(ip, ip + num_octets);
|
||||||
|
crc.process_byte(rand);
|
||||||
|
boost::uint32_t c = crc.checksum();
|
||||||
|
node_id id;
|
||||||
|
|
||||||
|
id[0] = (c >> 24) & 0xff;
|
||||||
|
id[1] = (c >> 16) & 0xff;
|
||||||
|
id[2] = (c >> 8) & 0xff;
|
||||||
|
id[3] = c & 0xff;
|
||||||
|
|
||||||
for (int i = 4; i < 19; ++i) id[i] = random();
|
for (int i = 4; i < 19; ++i) id[i] = random();
|
||||||
id[19] = r;
|
id[19] = r;
|
||||||
|
|
||||||
|
|
|
@ -71,14 +71,6 @@ using namespace boost::tuples;
|
||||||
|
|
||||||
namespace libtorrent {
|
namespace libtorrent {
|
||||||
TORRENT_EXPORT std::string sanitize_path(std::string const& p);
|
TORRENT_EXPORT std::string sanitize_path(std::string const& p);
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
|
||||||
// namespace dht
|
|
||||||
// {
|
|
||||||
// TORRENT_EXPORT libtorrent::dht::node_id generate_id_impl(
|
|
||||||
// address const& ip_, boost::uint32_t r);
|
|
||||||
// }
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1_hash to_hash(char const* s)
|
sha1_hash to_hash(char const* s)
|
||||||
|
@ -1965,11 +1957,11 @@ int test_main()
|
||||||
|
|
||||||
boost::uint8_t prefixes[][4] =
|
boost::uint8_t prefixes[][4] =
|
||||||
{
|
{
|
||||||
{0xf7, 0x66, 0xf9, 0xf5},
|
{ 0x17, 0x12, 0xf6, 0xc7 },
|
||||||
{0x7e, 0xe0, 0x47, 0x79 },
|
{ 0x94, 0x64, 0x06, 0xc1 },
|
||||||
{0x76, 0xa6, 0x26, 0xff },
|
{ 0xfe, 0xfd, 0x92, 0x20 },
|
||||||
{0xbe, 0xb4, 0xe6, 0x19 },
|
{ 0xaf, 0x15, 0x46, 0xdd },
|
||||||
{0xac, 0xe5, 0x61, 0x3a },
|
{ 0xa9, 0xe9, 0x20, 0xbf }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
|
|
Loading…
Reference in New Issue