A library for a decentralised peer-to-peer chat over IPv6 only.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
root 9fe66a4196 update doxy 5 jaren geleden
bin config read/write fully working. 5 jaren geleden
doc update doxy 5 jaren geleden
inc update doxy 5 jaren geleden
lib reorganised files 5 jaren geleden
src update doxy 5 jaren geleden
Doxyfile update doxy 5 jaren geleden
Makefile reorganised files 5 jaren geleden
README.md typo again ;) 5 jaren geleden

README.md

libchat6

About

libchat6 is a complete library that handles an IPv6 only, peer-to-peer, end-to-end encrypted, decentralised, chat client.

Ideas

  • Transport is IPv6, but some fallback mechanism to help IPv4 client may be implemented.
  • all clients are identical and no server is needed (some clients might run to act as bootstrap servers but all clients do that as well.)
  • clients have a built-in bootstrap list of IPv6 addresses. This list gets updated when the client connects to the network. This allows the client to always have a recent list of bootstraping IPs.
  • There’s no central registration site, therefor users just choose a nickname and have a private/public key pair (generated by the client). Clients are identified by their public key.
  • Friends can be searched by their nickname or public key. If a client changes the nickname without changing the key pair, the friend can still be found using the public key. This process is completely handled by the library and is transparent to the user. Is a friend changes the key pair, a new friend request will have to be sent.
  • The interconnection of clients is handled over other clients. The network builds up and paths between clients are calculated similar as a routing protocol for routes. The network is anarchic and no rules, except the protocol, leads it.
  • A client may connect to multiple clients, the network of clients will adjust the routing paths according to a metric and select the best path. The metric is the delay in miliseconds on each connection. A regular keepalive is used to measure the delay and the routing information is adjusted accordingly.
  • To avoid dead paths, a relatively short keepalive timeout is used.
  • The network does not allow store-and-forward of messages. If the friend is offline, messages cannot be send and the client has to store the message until the friend is available. For mobile clients, notifications might be integrated to wakup the client (no clue how? anyone?)
  • The network allows users to find other users by nickname. Nickname collisions are possible.
  • Chat groups require to send the message to all the clients.
  • Each client will randomly add a certain amount of time to its own metric to avoid disclosing its identifiy to any incoming connection.
  • … ?

Bootstrapping

To bootstrap a node, a node will have a list of hardcoded nodes and a list of the last known nodes. The hardcoded list is a list of nodes that are put in place by the initiators of this library. Anyone willing to run a permanent node is welcome to contact us to add a node to the hardcoded list.

Protocol

Principles

A client is the user. A person or a bot using the network to exchange messages. A node is the entity transporting messages for clients. Both are within the same library but use different identities (keypairs). Nodes sending messages to its peer node(s) will use a temporary keypair generated on startup. This keypair changes at every startup and is not stored. A client, on the other side, will generate a keypair once and will use it to generate a temporary keypair for each chat partner to ensure forward secrecy. The temporary keypair is never stored.

Messages format

<MSGSIGNATURE> <MSGHASH> <TIMESTAMP> <MSGTYPE> [<name>=<value>] ...
  • MSGSIGNATURE: An authenticated MSGHASH to prove the origin of the msg. This is signed by the client for client-to-client messages and by the node key for node-to-node messages. The first HELLO message has the signature set to all zeroes.
  • MSGHASH: A hash of the complete message starting at the timestamp. If the name=value pairs contain a ‘metric’ option, the hash must be calculated with the metric set to 0.
  • TIMESTAMP: The timestamp at the creation of the message, formatted “YYYY-mm-dd HH:MM:SS.sss”. The timestamp is always in UTC.
  • MSGTYPE: The msgtime is the type of message that is sent. See below.
  • name=value: name=value pairs transport all the message informations and vary depending on the msgtype. See description of msgtypes below.

name=value pairs

NOTE: All ‘value’ transporting binary or UTF-8 data is represented as base64.

  • chatid: a uuid defining the chat group.
  • clientkey: the public key of the sending client.
  • icon: base64 encoded png.
  • message: a base64 encoded message, encrypted with the target’s session key.
  • metric: a 32 bits unsigned integer representing the sum of all latencies between the client and the announcing client. An originating client will set a random value between 1000 and 2000 to avoid localisation.
  • msgid: a uuid defining a message unique to a chatid.
  • mtype: A closed supported list of media types {text, png, jpeg, gif, webm, vcard, ??} (text is always UTF-8)
  • neighbour: ipv6,port[,ipv4] (IPv4 can be optionally disclosed)
  • nickname: the nickname chosen by the client (UTF-8 string).
  • nodekey: the public key of the sending node.
  • nonce: random bytes, also known as initialisation vector. Must be new for every message.
  • sessionkey: a session temporary public key.
  • target_hash: a hash of the target public key. Mainly used for routing.
  • version: currenlty has the value of 1.

begin and end of session (node-to-node)

This is the very first message both nodes will send after connecting. The connecting node will send it’s HELLO first. If the connected node agrees it will reply with its own HELLO. If it doesn’t it will reply with a BYE msg and close the connection. Both nodes may send a BYE message at any time to terminate the connection.

HELLO {version,nodekey}
BYE

path anouncement and withdrawal

Clients can announce, withdraw or update their presence. A node will keep all client information and inform any new node of the state of all known clients. The metric must be updated when a ONLINE or UPDATE msg is received.

CLIENT_ONLINE {clientkey, nickname, icon, metric}
CLIENT_UPDATE {nonce, nickname, icon, metric}
CLIENT_OFFLINE

KEEPALIVE

Keepalive and node-to-node only and are originated by both nodes on a connection. The interval is 15s and if a node doesn’t receive a timeout for 30s, it must shutdown the connection. The interval betweeen the request and the response is used to calculate the metric. The metric is caculcated as an average value of the last 10 messages.

KEEPALIVE_REQUEST
KEEPALIVE_RESPONSE

FRIENDS & MESSAGES

The friend request message has two purposes. First, for a new friend, is will ask the friend to confirm to actually be friends. Secondly, it will exchange temporary session keys. This means that everytime a client comes online and wants to initiate a chat with an existing friend, it will have to send a friend request and get a friend confirm message back in order to exchange new temporary keys. If a friend request from an existing friend comes in, the confim message will automatically be sent back without user confirmation. If the friend is unknown, a user confirmation is required.

FRIEND_REQUEST {target_hash, sessionkey}
FRIEND_CONFIRM {target_hash, sessionkey}

client-to-client messages are exchanged using those three message types. Message received and read are only confirmations. A UI may implement a visual aid to show those. Message send, sends a message using the name=value pair ‘message’. The message is encrypted using the temporary session key of the friend. Messages must be confirmed received, if they don’t, the client will retry sending it after a timeout of 30s until a recv is received or a CLIENT_OFFLINE message is received. Messages can only be sent to online friends. If a friend is offline, the client will have to store the message until the friend is online.

MESSAGE_SEND {target_hash, chatid, msgid, mtype, message}
MESSAGE_RECV {target_hash, chatid, msgid}
MESSAGE_READ {target_hash, chatid, msgid}

NEIGHBOURS

In order to discover other nodes, a node may request the directly connected nodes of a neighbor node. The list will be sent back to the requesting node with one or multiple name=value pairs of ‘neighbor’. The value is composed of the IP of the node and the TCP port separated by a comma. A neighbor will only be disclosed to another neighbor if it is relaying messages for others (showed more than one CLIENT_ONLINE msg).

NEIGHBORS_REQUEST # request the neighbours of your neighbour
NEIGHBORS_RESPONSE {neighbour,..} # neighbours list, multiple time the same key