Protocole JNTP Version 0.17


Protocole JNTP Version 0.17.
Cette version rend obsolète toutes les versions précédentes.

Statut du présent mémoire

Ce document définit un nouveau protocole pour la diffusion de données sur un réseau décentralisé sur Internet, et appelle à discussion et suggestions en vue de son amélioration. Il est distribué comme une RFC pour rendre ces informations facilement accessibles aux internautes. La distribution de ce document est illimitée.

Sommaire

1) Résumé
2) Le protocole JNTP
3) Définitions
4) Format d’un paquet
5) Accès aux ressources
6) Les commandes du protocole JNTP
? Exemple d’une communication entre un client et un serveur
? Exemple d’une communication entre deux serveurs
? L’algorithme de propagation

1) Résumé

Le protocole JNTP « JSON News Transfer Protocol » définit un format d’échange de données en vue de créer un réseau décentralisé et standardisé de contenus sur internet, il permet aux différents serveurs qui constituent les nœuds de ce réseau d’échanger des données et d’en assurer la gestion. À l’origine le protocole JNTP a été créé pour les besoins du projet Nemo qui propose une interface opérationnelle pour assurer l’interopérabilité des différents réseaux et logiciels de discussion, dans toute leur diversité : webforums, newsgroups, réseaux sociaux, groupes JNTP, etc… Le projet Nemo s’articule autour d’un ensemble de technologies et de protocoles dont le protocole JNTP.

2) Le protocole JNTP

Le protocole définit les règles de distribution de contenu sur un ensemble de serveurs, qui forment collectivement un réseau JNTP. Le protocole JNTP permet de transporter des messages au format texte, mais il peut également transporter tous types de médias : sons, fichiers, images, vidéos…

Le protocole JNTP s’appuie sur un mécanisme transactionnel par le biais de requêtes. Une requête JNTP ainsi que sa réponse sont toutes deux constituées d’une chaîne de caractères définie par le format de données JSON. Le protocole JNTP suppose un protocole de requêtes de la couche applicative pour encapsuler la requête JNTP et sa réponse, il s’agira généralement de HTTP. Lorsque JNTP est transporté par HTTP la requête JNTP doit être adressée en méthode POST à l’url http://serveur/jntp/ où serveur désigne le FQDN du serveur JNTP.

Toutes les commandes transmises par les clients et les serveurs JNTP sont des objets JSON. Le protocole JNTP est sensible à la casse.

3) Définitions

* Un nœud JNTP ou serveur JNTP désigne un logiciel servant des requêtes qui respectent le protocole JNTP. Le logiciel doit s’exécuter sur une machine physique qui dispose d’au moins une adresse IP, d’un nom de domaine reconnu de manière globale, et d’au moins une paire declés asymétriques. [norme X.509, protocole NTP ?]

* Un lecteur JNTP désigne un logiciel conçu pour se connecter sur un serveur JNTP et qui permet de diffuser et d’interpréter les données qui y sont transportées.

* Une Data désigne une information destinée à être transportée et diffusée sur un réseau JNTP.

* Un DataType désigne un format de données qui structure une Data.

* Un paquet JNTP désigne l’objet JSON qui encapsule une Data.

* Le Jid désigne l’identifiant unique d’un paquet sur un réseau JNTP.

* Une passerelle désigne un logiciel qui permet de dialoguer d’un côté avec un serveur JNTP, de l’autre avec un serveur de transport de données (distinct de JNTP).

4) Format d’un paquet JNTP

packet = 
{ 
	"Jid": String,
	"Route": Array,
	"ID": Number,
	"ServerSign": String,
	"Data": Object,
	"Meta": Object
}

L’ordre des clés d’un paquet JNTP n’a aucune importance.
Une clé d’un paquet JNTP est une chaîne de caractères qui contient les caractères  :
"!#-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
dans la limite de 20 caractères. Les caractères "!" et "#" ne peuvent figurer que dans le premier caractère de la clé et lorsque c’est le cas ce caractère définit la directive de la clé.

On définit le chemin d’une valeur contenue dans un objet JSON par une chaîne de caractères qui contient la hiérarchie de toutes les clés parentes séparées entre elles par le caractère "/". Lorsque la valeur est incluse dans un tableau, le chemin est suffixé du caractère ":" suivi d’un entier qui identifie la position de la valeur dans le tableau, le premier élément étant indicé à 1.

Exemple avec l’objet JSON:

{
	"Name" : "Julien Arlandis", 
	"Projet RFC_v0.12" : {
		"name" : "Nemo", 
		"contributeurs" : ["Joe", "Jim", "Jack"],
		"!content" : "Ce document définit un nouveau protocole pour la diffusion de données sur un réseau décentralisé sur internet"
	}
}

"Name" désigne "Julien Arlandis",
"Projet RFC_v0.12" désigne

{ 
	"name" : "Nemo", 
	"contributeurs" : ["Joe", "Jim", "Jack"] ,
	"!content" : "Ce document définit un nouveau protocole pour la diffusion de données sur un réseau décentralisé sur internet"
},

"Projet RFC_v0.12/name" désigne "Nemo",
"Projet RFC_v0.12/contributeurs" désigne ["Joe", "Jim", "Jack"],
"Projet RFC_v0.12/contributeurs:1" désigne "Joe",
"Projet RFC_v0.12/contributeurs:2" désigne "Jim",
"Projet RFC_v0.12/contributeurs:3" désigne "Jack".
"Projet RFC_v0.12/#content" désigne "Ce document définit un nouveau protocole pour la diffusion de données sur un réseau décentralisé sur internet".

– La directive "!" indique que la valeur de la clé correspondante est susceptible de contenir des données volumineuses et autorise le serveur à remplacer la valeur de la clé par son empreinte SHA-1 lors de la transmission du paquet.
– La directive "#!" indique que la valeur de la clé correspondante est une empreinte SHA-1.

4.1. Jid (String, obligatoire)

– Jid est la chaîne de caractères qui identifie un paquet sur le réseau.
– Jid = SHA-1(minifyPacket(Data)) "@" ServerOrigin
– SHA-1 = fonction qui retourne l’empreinte numérique d’une chaîne de caractères passée en paramètres.
[Note de l’auteur : expliquer le passage des caractères aux octets (voire aux bits) utilisés par le mécanisme SHA-1.]
– ServerOrigin désigne le FQDN du nœud émetteur du paquet, sa valeur doit être identique à Data/ServerOrigin.

* Algorithme de la fonction minifyPacket

La fonction minifyPacket offre une représentation compacte et unique d’un objet JSON, voici l’algorithme de cette fonction :
– on « minifie » le tout, c’est-à-dire que l’on supprime les blancs et sauts de ligne inutiles et que l’on simplifie l’écriture (par exemple "\n" au lieu de "\u000a" et "é" au lieu de "\u00e9").
– si une clé contient la directive "!" celle-ci est remplacée par "#" et la valeur de la clé est remplacée par une empreinte SHA-1 empreinte SHA-1 du minifyPacket de sa valeur.
Cette transformation offre la possibilité aux serveurs de distribuer aux clients des paquets allégés, en substituant les valeurs volumineuses par de simples hashs SHA-1 (séquence de 40 caractères). JNTP offre ainsi la possibilité aux clients de récupérer de manière asynchrone les valeurs du paquet.
– si la clé « Data/DataID » est présente et si sa valeur est identique à la valeur du Jid alors sa valeur doit être remplacée par la chaîne vide "".
– dans les objets, on trie les éléments par ordre lexicographique des clés.

Exemple :

Data = { 
	"Name" : "Julien Arlandis", 
	"Projet RFC_v0.12" : { 
		"name" : "Nemo", 
		"contributeurs" : ["Joe", "Jim", "Jack"],
		"!content" : "Ce document définit un nouveau protocole pour la diffusion de données sur un réseau décentralisé sur internet"
	} 
}

minifyPacket(Data) = ‘{"Name":"Julien Arlandis","Projet RFC_v0.12":{"#!content":"ec360492b691b586739f535d5bde051bbbc08b66","contributeurs":["Joe","Jim","Jack"],"name":"Nemo"}}’

Le Jid est calculé par le serveur.

4.2. Route (Array, obligatoire)

La route liste dans un tableau les différents nœuds empruntés par un paquet, dans l’ordre (le plus ancien en premier, le plus récent en dernier). La Route est calculée par le serveur.

"Route": ["nemo.pasdenom.info", "news.nemoweb.net"] signifie que le paquet est passé successivement par le serveur nemo.pasdenom.info puis news.nemoweb.net.

4.3. ID (Number, obligatoire)

L’ID est un nombre entier positif qui identifie localement un paquet sur un serveur donné, l’ID est incrémenté chaque fois que le serveur insère un nouveau paquet dans sa base de données, l’ID ne doit pas dépasser la valeur 2^53-1. Il est principalement utilisé comme un moyen de pointer les paquets.

4.4. ServerSign (String, obligatoire)

Ce champ constitue la signature numérique qui garantit que le paquet a bien été émis par le serveur mentionné dans la partie droite du Jid réservé au nom de domaine du serveur.
ServerSign = chiffrementAsymétrique(Jid, PrivateKey) où PrivateKey désigne la clé privée du serveur.
On peut donc vérifier que Jid = chiffrementAsymétrique(ServerSign, PublicKey).
Ce champ est calculé par le serveur.

4.5. Data (Object, obligatoire)

La Data est l’objet qui contient toutes les informations relatives au contenu publié.

Data = {
	"DataType" : String,
	"DataID" : String,
	"InjectionDate" : String,
	"OriginServer" : String,
	"ServerPublicKey" : Object
(...)
}

4.5.1. Data/DataType (String, obligatoire)

Identifie le format de données de la Data.
La structure de la Data à l’exception des clés Data/DataID, Data/InjectionDate, Data/OriginServer et Data/ServerPublicKey est entièrement définie par le format de données désigné par Data/DataType qui fera l’objet d’une spécification séparée.Le DataType « ProtoData » définit une Data qui ne fait l’objet d’aucune spécification, et dont le format de données n’obéit qu’aux seules règles définies dans le présent document.

4.5.2. Data/DataID (String, facultative)

Cette clé permet de désigner des objets identiques qui ne peuvent pas être identifiés par un même Jid faute d’une représentation unique de la Data. Par exemple il peut arriver que des données générées en dehors de JNTP soient appelées à être injectées sur JNTP sous des formes différentes et par des passerelles différentes sans qu’il ne soit possible d’assurer l’unicité du Jid pour ces objets. La clé Data/DataID permet à la fois de les identifier et d’empêcher leur redondance au sein d’un réseau JNTP.
La valeur de Data/ID doit être unique sur l’ensemble du réseau pour un DataType bien déterminé. La clé Data/DataID peut par construction du Jid (voir la fonction minifyPacket) contenir la même valeur que le Jid du paquet.

4.5.3. Data/InjectionDate (String, obligatoire)

Contient la date au format UTC à laquelle le paquet a été émis sur le réseau JNTP.
Data/InjectionDate = AAAA"-" MM "-" JJ "T" HH ":" MM ":" SS "Z"
Ce champ est renseigné par le serveur.

4.5.4. Data/OriginServer (String, obligatoire)

ServerOrigin désigne le FQDN du nœud émetteur du paquet. Ce FQDN doit disposer d’un enregistrement DNS A, AAAA ou CNAME sur le réseau internet.

4.5.5. Data/ServerPublicKey (Object, obligatoire)

Contient la clé publique du serveur correspondant à la clé privée qui a servi à signer le paquet. Contient également des informations spécifiques comme les dates de validité.
[Note de l’auteur : partie à détailler]

4.6. Meta (Object, facultatif)

et objet contient les informations annexes à un paquet, il s’agit de valeurs précalculées qui ont pour objectif de fournir des informations utiles aux clients ou aux autres serveurs.
Cet objet est susceptible de contenir des clés dont la description est fournie par le DataType du paquet.

5) Accès aux ressources

Toute valeur d’un paquet JNTP est identifiée par une ressource au format URI.
URI = "jntp:" Jid "/" chemin
Jid = Jid d’un paquet
chemin = chemin de la valeur tel que défini dans la présente RFC.

Exemple :
"jntp:925f119a4ff6b363f486d6ecb81c11060db0bf0a@news2.nemoweb.net@Data/Subject" pointe vers la chaîne de caractères "Protocole JNTP Version 0.17".

Pour accéder physiquement à la ressource sur un serveur JNTP donné on utilise l’URL
URL = "http://" host "/jntp/" Jid "/" chemin.

où host est le nom de domaine d’un serveur JNTP.

Exemple :
http://news.nemoweb.net/jntp/925f119a4ff6b363f486d6ecb81c11060db0bf0a@news2.nemoweb.net/Data/Subject

6) Les commandes du protocole JNTP

Syntaxe générale d’une commande JNTP :

commande = [name, query]
name = chaîne de caractère qui désigne le nom de la commande.
query = objet JSON.

6.1. get : Récupère un ou plusieurs paquets.

6.2. diffuse : Permet de diffuser ou de demander la diffusion d’un paquet ou une Data sur le réseau.Il faut distinguer deux modes de diffusion, la diffusion d’une Data et la diffusion d’un paquet.

6.2.1. Diffusion d’une Data.

Il s’agit du mode de diffusion utilisé par les clients JNTP, n’étant pas en mesure de forger eux même un paquet complet, ils transmettent à leur serveur les champs obligatoires de la Data requis par le DataType mentionné :

["diffuse", {"Data": ObjectJson}]

ObjectJson = {
	"DataType": datatype,
	(...)
}

6.2.2. Diffusion d’un paquet.

Il s’agit du mode de diffusion utilisé par les serveurs JNTP pour s’échanger les paquets :

["diffuse", {"Packet": paquet, "From": from}]

où paquet désigne un paquet JNTP,
from le FQDN du serveur qui exécute la requête.

6.2.3. Demande de diffusion d’un paquet.

Permet à un serveur d’informer un autre serveur de la nature du paquet qu’il s’apprête à lui transmettre :

["diffuse", {"Propose": partialPacket, "From": from}]

où partialPacket est un objet JSON qui contient au minimum :

– Le Jid de l’article + d’autres champs facultatifs susceptibles d’apporter une information tangible pour aider le serveur à refuser ou à accepter l’article.
Exemple :

partialPacket = {
	"Jid": Jid,
	"Meta": {
		"Size":[16000000]
	}
}

indique un paquet qui contient 16MO de données.

-La clé Data/DataID et le DataType du paquet + d’autres champs facultatifs.
Exemple :

partialPacket = {
	"Data": {
		"DataID": "m4lcm7$1ehd$1@cabale.usenet-fr.net",
		"DataType": "Article"
	}
}

6.3. auth : Permet de s’authentifier sur un serveur JNTP.

6.4. whoami : Renvoie les informations relatives à la connexion (login, session…).

6.5. quit : Permet de fermer la connexion avec le serveur JNTP.