       | (1) -----------------> |
       | <----------------- (2) |
Client | (3) -----------------> | Server
       |                    (4) |
       | <----------------- (5) |

(1) Client sends an update query to the server. (ex. put account 1000 to 
    IP 1.2.3.4)
(2) Server sends an (now encrypted) alive query to account 1000 at IP 1.2.3.4
(3) Account 1000 which is really at IP 1.2.3.4 receives the query, interprets 
    it and replies to it to show he is really account 1000 and that he 
    received the query.
(4) Server receives the (also encrypted) reply as a confimation that 1000 
    is really at 1.2.3.4 and thus marks it online.
(5) Server sends an update reply telling the client the update has succeeded 
    (or failed).

================================================================================
This is an alternative
----------------------

Data Tables
-----------
 tblAccounts
   accountId
   verifier
   salt
   sessionkey
 
 tblRecords
   recordId
   accountId

Protocol
--------
* Overview
                    Client                   Server
                        | -----AuthQuery----> |
                        | <----AuthReply----- | Authentication (and)
                        | ----VerifyQuery---> | Verification
                        | <---VerifyReply---- |

                        | ----UpdateQuery---> | Update (IP Address)
                        | <---UpdateReply---- |

                        | <---AliveQuery----- | (Keep) Alive
                        | ----AliveReply----> |

* Auth Query/Reply + Verify Query/Reply

                    Client                   Server
                        | AuthQuery (nocrypto)    |
             send(i)    | (1)-------(i)---------> |
                        |                         | (v,s) = lookup(i)
                        |                         | (b,B) = genkeypair(v,g)
                        | AuthReply (nocrypto)    |
                        | <-------(B,u,s)-----(2) | send(B,u,s)
    x = hash(s,P)       |                         |
(a,A) = genkeypair(g)   |                         |
    S = (B-g^x)^(a+u*x) |                         |
    K = hash(S)         |                         |
   M1 = hash(A,B,K)     |                         |
                        | VerifyQuery (nocrypto)  |
             send(A,M1) | (3)------(A,M1)-------> | 
                        |                         | S = (A*v^u)^b
                        |                         | K = hash(S)
                        |                         | if(M1=hash(A,B,K))
                        |                         |   store(K)
                        |                         |   M2 = hash(A,M1,K)
                        | VerifyReply (nocrypto)  |
                        | <--------(M2)-------(4) | send(M2)
 if(M2=hash(A,M1,K)     |                         |
   store(K)


AuthQuery
(1) Client sends the accountId (i) to Server.

    Server looks up the accountId (i) in tblAccount and retrieves the
    verifier (v) and the accountSalt (s). Note that the verifier (v) is
    generated uniquely from the password (P). Only the client needs to
    remember the password (P). The lookup is denoted (v,s) = lookup(i).

    Server generates short-term private-public key pair. The short-term
    private key (b) is generated randomly from the range 1 < b < n. The
    short-term private key (B) is computed from B=v+g^b. Generating
    this key pair is denoted (b,B) = genkeypair(v,g).

AuthReply
(2) Server sends the short-term public key (B), a random scrambling
    value (u), and accountSalt (s) to Client.

    Client generates a long-term private key (x) using the salt (s) and
    the password (P) as in x = hash(s,P).

    Client also generates a short-term private/public key pair. The
    short-term private key (a) is generated randomly from the range
    1 < a < n. The short-term public key (A) is computed from A = g^a.
    Generating this key pair is denoted (a,A) = genkeypair(g).

    Client computes the common exponential value (S) = (B-g^x)^(a+u*x),
    the session key (K) = hash(S), and the client session verification
    value (M1) = hash(A,B,K).

VerifyQuery
(3) Client sends the short-term public key (A) and the client session
    verification value (M1) to Server.

    Server computes the common exponential value (S) = (A*v^u)^b and the
    session key (K) = hash(S).

    Server verifies that M1 does in fact equal hash(A,B,K). If it does,
    the CLIENT IS AUTHENTICATED.

    Server computes server session verification value (M2) = hash(A,M2,K).

VerifyReply
(4) Server sends the server session verification value (M2) to Client.

    Client verifies that M2 does in fact equal hash(A,M1,K). If it does,
    the SERVER IS AUTHENTICATED.

* Update Query/Reply
                        | UpdateQuery (crypto)|
  send(i,encrypt(I,K))  | (1)----(i,I)------> |
                        |                     | K = lookup(i)
                        |                     | r = updateIP(i,decrypt(I,K))
                        | UpdateReply (crypto)|
                        | <-------(r)-----(2) |

UpdateQuery
(1) Client encrypts IP address (I) using the session key (K) and sends it
    to Server. UpdateQuery contains the accountId (i).

    Server looks up the session key (K) corresponding to the accountId (i).
    Server decrypts the IP address (I) and updates the record in tblRecords.

(2) Server replies to Client with reply value (r) indicating success or
    failure.

* Alive Query/Reply
                        |                     | K   = lookup (i)
                        |                     | buf = "you alive?"
                        | AliveQuery (crypto) |
                        | <------(buf)------- | send(encrypt(buf,K))
 if(decrypt(buf,K)=OK)  |                     |
    buf = "yes mama"    |                     |
                        | AliveReply (crypto) |
send(i,encrypt(buf, K)) | -------(buf)------> |
                        |                     | K = lookup(i)
                        |                     | if(decrypt(buf,K)=OK)
                        |                     |   updateTimeOut(i)
