Section 2.x: Query Keys

In order to facilitate secure, non-spoofable GUESS query exchanges, a
Query Key system MUST be supported by both client and server GUESS
servents.

At a high level, a Query Key system mandates that all queries must be
prefaced with a credential in order to be executed. This ensures that
malicious clients cannot generate queries on behalf of servents and cannot
easily use the Gnutella GUESS network as a slave in DoS attacks.

The security concerns that are addressed by a Query Key system should not
override GUESS's main goal of reducing bandwidth and communication costs
on the Gnutella network. For this reason, the Query Key system has been
kept as unobtrusive as possible without sacrificing security goals.

2.x.1: Query Keys and Queries

All queries sent to servents over the UDP channel must have a valid Query
Key included with the Query. The Query Key is a n-byte value (4 <= n <=
16) located in the payload of a GGEP Extension with header "QK".
Intelligent Query Key generation will guarantee that collisions between
Query Keys for different queriers generated by a given GUESS Ultrapeer are
highly unlikely (more in section 2.x.4).  Further, since GUESS Ultrapeers
that generate Query Keys will be using random parameters to the Query Key
Algorithm (section 2.x.4), the chances of two GUESS Ultrapeers generating
the same Query Key for a given query source is highly unlikely.

2.x.2: Obtaining Query Keys

If a GUESS servent wishing to query Host A has a Query Key for Host A in
its Query Key cache, it should include that Query Key in the query as the
payload of GGEP extenson with header "QK".

In order to obtain a Query Key for host A if there is not one in the
cache, a GUESS servent should send a ping with GGEP Extension header "QK"
and no GGEP Extension data AND a TTL of 1 to the host A over the UDP
channel. Only TTL 1 pings sent over the UDP channel will be inspected for
the Query Key request. In response it will receive via UDP a TTL 1 Pong
from host A with GGEP Extension header "QK" and a n-byte (4 <= n <= 16)
GGEP Extension value (the Query Key). It should cache the Query Key,
associating it with Host A.

If a servent receives a unrequested Query Key pong from another servent,
it should cache the Query Key, considering the new Query Key to be the
valid credential.

2.x.3 Distributing Query Keys

As stated in section 2.x.2, GUESS Ultrapeers should respond to Query Key
requests (TTL 1 UDP Pings with a "QK" GGEP Extension) by generating a
Query Key for the requester (see section 2.x.4) and packaging this Key as
the n-byte payload (4 <= n <= 16) of a "QK" GGEP Extension in a TTL 1 pong
sent to the requester via the UDP channel.

If a Query arrives from a source with a invalid Query Key (found in the
"QK" GGEP Extension), then a valid Query Key should be generated and
delivered via UDP to the source in a TTL 1 pong message*. A Query Key may
be invalid due to a change in the parameters of the Query Key Algorithm
(see section 2.x.4).

When a valid Query Key is attached to a query, the query should be
executed as normal (sent via QRP to leaves and evaluated on the local
client).

GUESS ULTRAPEERS SHOULD ONLY CONSIDER THE VALIDITY OF QUERY KEYS FOR
QUERIES RECEIVED OVER THE UDP CHANNEL.

2.x.4.1 Query Key Algorithm

In order to generate Query Keys, vendors must use a 'sufficiently secure'
one-to-one mapping between some function of host address and port and a
n-byte Query Key (4 <= n <= 16):

f(g(ip,port)) --> n-byte Query Key

Often, the algorithm cannot be secret, but a distinct secret key should be
generated by a distinct instance of a servent. The Query Key MUST be at
least 4 bytes in length to guarantee that Query Keys cannot be guessed
simply by brute force.

The following algorithm is an example and is not required by the Query Key
system - any vendor can generate Query Keys as needed as long as their
algorithm is 'sufficiently secure'. A GUESS Ultrapeer generates two secret
values upon startup: a 3-byte long secret pad and a 8-byte long DES
Key. To generate a Query Key, the Ultrapeer appends the IP address,
portnumber, and the secret pad (any repeatable permutation) and performs a
DES encryption using the DES key, producing a 8-byte Query Key.

2.x.4.2 'Sufficiently Secure' Algorithms

A Query Key Algorithm is sufficiently secure if it is not subject to easy
cryptanalysis. DES is a well known block cipher and is prone to
cryptanalysis, but the average lifetime of a DES key is at least 10 hours
(assuming a very dedicated opponent). Gnutella GUESS Ultrapeers should
generate a new secret pad and a new secret key as often as necessary - in
the case of DES on the order of 8-10 hours. Moreover, since a secret pad
is appended to the host and ip address during Query Key construction, any
snooper has no particular advantage when attempting to determine a GUESS
Ultrapeers DES key.

THE PRECISE NATURE OF THE ALGORITHM USED TO GENERATE QUERY KEYS IS
UNIMPORTANT- THE TWO MAIN REQUIREMENTS ARE:
* The algorithm should be resistant to attacks that are effective over a
  short period of time (8-12 hours).
* There should be some secret padding and key involved in Query Key
  generation.

Some 'sufficiently secure' algorithms:
* DES
* truncated SHA1

* As an added optimization, a GUESS Ultrapeer may keep a window of Query
Key generation parameters - this way 'not too old' Query Keys can still be
honored and a new Query Key can be sent in addition to processing the
query (with the 'not too old' Query Key). For example:

- Keep two private secrets, called N and N-1. Your current secret is N,
  and its lifetime is T. However, N-1 was the last previous valid secret.
- Every T, you discard N-1 and create N+1. Your two secrets are now N+1
  and N.
- For each query that comes, you validate against the two secrets, N
  first, then N-1. If N-1 matches, you can send back an usollicited pong
  with the new query key "N".
