pull in an ed25519 implementation and replace use of RSA in the DHT with ECC. fix up makefiles

This commit is contained in:
Arvid Norberg
2013-08-18 16:01:20 +00:00
parent 76f32f0659
commit 6bd07fd65f
33 changed files with 5478 additions and 102 deletions

View File

@@ -81,7 +81,7 @@ the key is the public key of the key pair used to sign the data.</p>
<div class="section" id="terminology">
<h1>terminology</h1>
<p>In this document, a <em>storage node</em> refers to the node in the DHT to which
an item is being announced and stored on. A <em>subscribing node</em> refers to
an item is being announced and stored on. A <em>requesting node</em> refers to
a node which makes look-ups in the DHT to find the storage nodes, to
request items from them, and possibly re-announce those items to keep them
alive.</p>
@@ -90,15 +90,17 @@ alive.</p>
<h1>messages</h1>
<p>The proposed new messages <tt class="docutils literal">get</tt> and <tt class="docutils literal">put</tt> are similar to the existing <tt class="docutils literal">get_peers</tt>
and <tt class="docutils literal">announce_peer</tt>.</p>
<p>Responses to <tt class="docutils literal">get</tt> should always include <tt class="docutils literal">nodes</tt> and <tt class="docutils literal">nodes6</tt> has the same
semantics as in its <tt class="docutils literal">get_peers</tt> response. It should also include a write token,
<tt class="docutils literal">token</tt>, with the same semantics as <tt class="docutils literal">get_peers</tt>.</p>
<p>Responses to <tt class="docutils literal">get</tt> should always include <tt class="docutils literal">nodes</tt> and <tt class="docutils literal">nodes6</tt>. Those fields
have the same semantics as in its <tt class="docutils literal">get_peers</tt> response. It should also include a write token,
<tt class="docutils literal">token</tt>, with the same semantics as int <tt class="docutils literal">get_peers</tt>. The write token MAY be tied
specifically to the key which <tt class="docutils literal">get</tt> requested. i.e. the <tt class="docutils literal">token</tt> can only be used
to store values under that one key.</p>
<p>The <tt class="docutils literal">id</tt> field in these messages has the same semantics as the standard DHT messages,
i.e. the node ID of the node sending the message, to maintain the structure of the DHT
network.</p>
<p>The <tt class="docutils literal">token</tt> field also has the same semantics as the standard DHT message <tt class="docutils literal">get_peers</tt>
and <tt class="docutils literal">announce_peer</tt>, when requesting an item and to write an item respectively.</p>
<p>The <tt class="docutils literal">k</tt> field is the PKCS#1 encoded 2048 bit RSA public key, which the signature
<p>The <tt class="docutils literal">k</tt> field is the 32 byte ed25519 public key, which the signature
can be authenticated with. When looking up a mutable item, the <tt class="docutils literal">target</tt> field
MUST be the SHA-1 hash of this key.</p>
<p>The distinction between storing mutable and immutable items is the inclusion
@@ -113,7 +115,7 @@ its key), its flattened, bencoded, form is used. It is important to use the exac
bencoded representation as it appeared in the message. decoding and then re-encoding
bencoded structures is not necessarily an identity operation.</p>
<p>Storing nodes SHOULD reject <tt class="docutils literal">put</tt> requests where the bencoded form of <tt class="docutils literal">v</tt> is longer
than 767 bytes.</p>
than 1000 bytes.</p>
</div>
<div class="section" id="immutable-items">
<h1>immutable items</h1>
@@ -129,7 +131,7 @@ that its hash matches the target that was looked up.</p>
&quot;a&quot;:
{
&quot;id&quot;: <em>&lt;20 byte id of sending node (string)&gt;</em>,
&quot;v&quot;: <em>&lt;any bencoded type, whose encoded size &lt; 768&gt;</em>
&quot;v&quot;: <em>&lt;any bencoded type, whose encoded size &lt;= 1000&gt;</em>
},
&quot;t&quot;: <em>&lt;transaction-id (string)&gt;</em>,
&quot;y&quot;: &quot;q&quot;,
@@ -189,7 +191,7 @@ and a node hosting the list node MUST not downgrade a list head from a higher se
number to a lower one, only upgrade. The sequence number SHOULD not exceed <tt class="docutils literal">MAX_INT64</tt>,
(i.e. <tt class="docutils literal">0x7fffffffffffffff</tt>. A client MAY reject any message with a sequence number
exceeding this.</p>
<p>The signature is a 2048 bit RSA signature of the SHA-1 hash of the bencoded sequence
<p>The signature is a 64 byte ed25519 signature of the bencoded sequence
number and <tt class="docutils literal">v</tt> key. e.g. something like this:: <tt class="docutils literal">3:seqi4e1:v12:Hello world!</tt>.</p>
<div class="section" id="id1">
<h2>put message</h2>
@@ -199,19 +201,24 @@ number and <tt class="docutils literal">v</tt> key. e.g. something like this:: <
&quot;a&quot;:
{
&quot;id&quot;: <em>&lt;20 byte id of sending node (string)&gt;</em>,
&quot;k&quot;: <em>&lt;RSA-2048 public key (PKCS#1 encoded)&gt;</em>,
&quot;k&quot;: <em>&lt;ed25519 public key (32 bytes string)&gt;</em>,
&quot;seq&quot;: <em>&lt;monotonically increasing sequence number (integer)&gt;</em>,
&quot;sig&quot;: <em>&lt;RSA-2048 signature (256 bytes string)&gt;</em>,
&quot;sig&quot;: <em>&lt;ed25519 signature (64 bytes string)&gt;</em>,
&quot;token&quot;: <em>&lt;write-token (string)&gt;</em>,
&quot;v&quot;: <em>&lt;any bencoded type, whose encoded size &lt; 768&gt;</em>
&quot;v&quot;: <em>&lt;any bencoded type, whose encoded size &lt; 1000&gt;</em>
},
&quot;t&quot;: <em>&lt;transaction-id (string)&gt;</em>,
&quot;y&quot;: &quot;q&quot;,
&quot;q&quot;: &quot;put&quot;
}
</pre>
<p>Storing nodes receiving a <tt class="docutils literal">put</tt> request where <tt class="docutils literal">seq</tt> is lower than what's already
stored on the node, MUST reject the request.</p>
<p>Storing nodes receiving a <tt class="docutils literal">put</tt> request where <tt class="docutils literal">seq</tt> is lower than or equal
to what's already stored on the node, MUST reject the request. If the sequence
number is equal, and the value is also the same, the node SHOULD reset its timeout
counter.</p>
<p>Note that this request does not contain a target hash. The target hash under
which this blob is stored is implied by the <tt class="docutils literal">k</tt> argument. The key is
the SHA-1 hash of the key (<tt class="docutils literal">k</tt>).</p>
<p>Response:</p>
<pre class="literal-block">
{
@@ -242,13 +249,13 @@ stored on the node, MUST reject the request.</p>
&quot;r&quot;:
{
&quot;id&quot;: <em>&lt;20 byte id of sending node (string)&gt;</em>,
&quot;k&quot;: <em>&lt;RSA-2048 public key (268 bytes string)&gt;</em>,
&quot;k&quot;: <em>&lt;ed25519 public key (32 bytes string)&gt;</em>,
&quot;nodes&quot;: <em>&lt;IPv4 nodes close to 'target'&gt;</em>,
&quot;nodes6&quot;: <em>&lt;IPv6 nodes close to 'target'&gt;</em>,
&quot;seq&quot;: <em>&lt;monotonically increasing sequence number (integer)&gt;</em>,
&quot;sig&quot;: <em>&lt;RSA-2048 signature (256 bytes string)&gt;</em>,
&quot;sig&quot;: <em>&lt;ed25519 signature (64 bytes string)&gt;</em>,
&quot;token&quot;: <em>&lt;write-token (string)&gt;</em>,
&quot;v&quot;: <em>&lt;any bencoded type, whose encoded size &lt; 768&gt;</em>
&quot;v&quot;: <em>&lt;any bencoded type, whose encoded size &lt;= 1000&gt;</em>
},
&quot;t&quot;: <em>&lt;transaction-id (string)&gt;</em>,
&quot;y&quot;: &quot;r&quot;,
@@ -267,12 +274,11 @@ sequence number 1 of value &quot;Hello World!&quot; would be converted to: 3:seq
In this way it is not possible to convince a node that part of the length is actually part of the
sequence number even if the parser contains certain bugs. Furthermore it is not possible to have a
verification failure if a bencoding serializer alters the order of entries in the dictionary.</li>
<li>hash the concatenated string with SHA-1</li>
<li>sign or verify the hash digest.</li>
<li>sign or verify the concatenated string</li>
</ol>
<p>On the storage node, the signature MUST be verified before accepting the store command. The data
MUST be stored under the SHA-1 hash of the public key (as it appears in the bencoded dict).</p>
<p>On the subscribing nodes, the key they get back from a <tt class="docutils literal">get</tt> request MUST be verified to hash
<p>On the requesting nodes, the key they get back from a <tt class="docutils literal">get</tt> request MUST be verified to hash
to the target ID the lookup was made for, as well as verifying the signature. If any of these fail,
the response SHOULD be considered invalid.</p>
</div>

View File

@@ -22,7 +22,7 @@ terminology
-----------
In this document, a *storage node* refers to the node in the DHT to which
an item is being announced and stored on. A *subscribing node* refers to
an item is being announced and stored on. A *requesting node* refers to
a node which makes look-ups in the DHT to find the storage nodes, to
request items from them, and possibly re-announce those items to keep them
alive.
@@ -33,9 +33,11 @@ messages
The proposed new messages ``get`` and ``put`` are similar to the existing ``get_peers``
and ``announce_peer``.
Responses to ``get`` should always include ``nodes`` and ``nodes6`` has the same
semantics as in its ``get_peers`` response. It should also include a write token,
``token``, with the same semantics as ``get_peers``.
Responses to ``get`` should always include ``nodes`` and ``nodes6``. Those fields
have the same semantics as in its ``get_peers`` response. It should also include a write token,
``token``, with the same semantics as int ``get_peers``. The write token MAY be tied
specifically to the key which ``get`` requested. i.e. the ``token`` can only be used
to store values under that one key.
The ``id`` field in these messages has the same semantics as the standard DHT messages,
i.e. the node ID of the node sending the message, to maintain the structure of the DHT
@@ -44,7 +46,7 @@ network.
The ``token`` field also has the same semantics as the standard DHT message ``get_peers``
and ``announce_peer``, when requesting an item and to write an item respectively.
The ``k`` field is the PKCS#1 encoded 2048 bit RSA public key, which the signature
The ``k`` field is the 32 byte ed25519 public key, which the signature
can be authenticated with. When looking up a mutable item, the ``target`` field
MUST be the SHA-1 hash of this key.
@@ -63,7 +65,7 @@ bencoded representation as it appeared in the message. decoding and then re-enco
bencoded structures is not necessarily an identity operation.
Storing nodes SHOULD reject ``put`` requests where the bencoded form of ``v`` is longer
than 767 bytes.
than 1000 bytes.
immutable items
---------------
@@ -85,7 +87,7 @@ Request:
"a":
{
"id": *<20 byte id of sending node (string)>*,
"v": *<any bencoded type, whose encoded size < 768>*
"v": *<any bencoded type, whose encoded size <= 1000>*
},
"t": *<transaction-id (string)>*,
"y": "q",
@@ -153,8 +155,8 @@ number to a lower one, only upgrade. The sequence number SHOULD not exceed ``MAX
(i.e. ``0x7fffffffffffffff``. A client MAY reject any message with a sequence number
exceeding this.
The signature is a 2048 bit RSA signature of the SHA-1 hash of the bencoded sequence
number and ``v`` key. e.g. something like this:: ``3:seqi4e1:v12:Hello world!``.
The signature is a 64 byte ed25519 signature of the bencoded sequence
number concatenated with the ``v`` key. e.g. something like this:: ``3:seqi4e1:v12:Hello world!``.
put message
...........
@@ -167,19 +169,25 @@ Request:
"a":
{
"id": *<20 byte id of sending node (string)>*,
"k": *<RSA-2048 public key (PKCS#1 encoded)>*,
"k": *<ed25519 public key (32 bytes string)>*,
"seq": *<monotonically increasing sequence number (integer)>*,
"sig": *<RSA-2048 signature (256 bytes string)>*,
"sig": *<ed25519 signature (64 bytes string)>*,
"token": *<write-token (string)>*,
"v": *<any bencoded type, whose encoded size < 768>*
"v": *<any bencoded type, whose encoded size < 1000>*
},
"t": *<transaction-id (string)>*,
"y": "q",
"q": "put"
}
Storing nodes receiving a ``put`` request where ``seq`` is lower than what's already
stored on the node, MUST reject the request.
Storing nodes receiving a ``put`` request where ``seq`` is lower than or equal
to what's already stored on the node, MUST reject the request. If the sequence
number is equal, and the value is also the same, the node SHOULD reset its timeout
counter.
Note that this request does not contain a target hash. The target hash under
which this blob is stored is implied by the ``k`` argument. The key is
the SHA-1 hash of the key (``k``).
Response:
@@ -217,13 +225,13 @@ Response:
"r":
{
"id": *<20 byte id of sending node (string)>*,
"k": *<RSA-2048 public key (268 bytes string)>*,
"k": *<ed25519 public key (32 bytes string)>*,
"nodes": *<IPv4 nodes close to 'target'>*,
"nodes6": *<IPv6 nodes close to 'target'>*,
"seq": *<monotonically increasing sequence number (integer)>*,
"sig": *<RSA-2048 signature (256 bytes string)>*,
"sig": *<ed25519 signature (64 bytes string)>*,
"token": *<write-token (string)>*,
"v": *<any bencoded type, whose encoded size < 768>*
"v": *<any bencoded type, whose encoded size <= 1000>*
},
"t": *<transaction-id (string)>*,
"y": "r",
@@ -241,13 +249,12 @@ value and sequence number should be done as follows:
In this way it is not possible to convince a node that part of the length is actually part of the
sequence number even if the parser contains certain bugs. Furthermore it is not possible to have a
verification failure if a bencoding serializer alters the order of entries in the dictionary.
3. hash the concatenated string with SHA-1
4. sign or verify the hash digest.
3. sign or verify the concatenated string
On the storage node, the signature MUST be verified before accepting the store command. The data
MUST be stored under the SHA-1 hash of the public key (as it appears in the bencoded dict).
On the subscribing nodes, the key they get back from a ``get`` request MUST be verified to hash
On the requesting nodes, the key they get back from a ``get`` request MUST be verified to hash
to the target ID the lookup was made for, as well as verifying the signature. If any of these fail,
the response SHOULD be considered invalid.