Doc update
This commit is contained in:
parent
cd41a59518
commit
08ff9d58b8
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,9 +1,10 @@
|
|||||||
doc/protocol.aux
|
doc/*.aux
|
||||||
doc/protocol.fdb_latexmk
|
doc/*.fdb_latexmk
|
||||||
doc/protocol.fls
|
doc/*.fls
|
||||||
doc/protocol.log
|
doc/*.log
|
||||||
doc/protocol.pdf
|
doc/*.pdf
|
||||||
doc/protocol.synctex.gz
|
doc/*.synctex.gz
|
||||||
|
doc/generated
|
||||||
out/doc/general_deployment/general_deployment.png
|
out/doc/general_deployment/general_deployment.png
|
||||||
out/doc/server_deployment/server_deployment.png
|
out/doc/server_deployment/server_deployment.png
|
||||||
*.json
|
*.json
|
||||||
|
25
README.md
25
README.md
@ -1,14 +1,21 @@
|
|||||||
# MEOW lib
|
# MEOW lib
|
||||||
|
|
||||||
## Go Mobile setup
|
# Documentation generation
|
||||||
go install golang.org/x/mobile/cmd/gobind@latest
|
## required tools
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
* protoc
|
||||||
go get golang.org/x/mobile/bind
|
* protoc-gen-doc
|
||||||
Replace "Get" by "get" in messages.pb.go
|
* protoc-gen-uml
|
||||||
|
* go-plantuml
|
||||||
|
* plantuml (plantuml command is as shell script : `java -jar /<path-to-plantuml>/plantuml-mit-<version>.jar "$@"`)
|
||||||
|
## generation
|
||||||
|
run the shell scripts
|
||||||
|
|
||||||
gomobile bind -target android -androidapi=19
|
cd pb
|
||||||
|
./protogen.sh
|
||||||
|
|
||||||
|
cd doc
|
||||||
|
./docgen.sh
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
|
||||||
Look at the exported API and cry...
|
|
||||||
|
|
||||||
## Other option
|
|
||||||
GOOS=android GOARCH=arm64 go build -buildmode=c-archive -o libmeow.a
|
|
||||||
|
@ -35,6 +35,7 @@ type Config struct {
|
|||||||
Theme string `json:"theme,omitempty"`
|
Theme string `json:"theme,omitempty"`
|
||||||
FingerprintEnable bool `json:"fingerprint_enable,omitempty"`
|
FingerprintEnable bool `json:"fingerprint_enable,omitempty"`
|
||||||
ShowFavoriteContacts bool `json:"show_favorite_contacts,omitempty"`
|
ShowFavoriteContacts bool `json:"show_favorite_contacts,omitempty"`
|
||||||
|
NightModeEnable bool `json:"night_mode_enable,omitempty"`
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
DbSuffix string `json:"db_suffix,omitempty"`
|
DbSuffix string `json:"db_suffix,omitempty"`
|
||||||
|
@ -71,10 +71,10 @@ func (pl *PeerList) GetFromName(name string) *Peer {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pl *PeerList) GetConversationRequests() []*meowlib.ToServerMessage_ConversationRequest {
|
func (pl *PeerList) GetConversationRequests() []*meowlib.ConversationRequest {
|
||||||
var list []*meowlib.ToServerMessage_ConversationRequest
|
var list []*meowlib.ConversationRequest
|
||||||
for _, peer := range *pl {
|
for _, peer := range *pl {
|
||||||
var cr meowlib.ToServerMessage_ConversationRequest
|
var cr meowlib.ConversationRequest
|
||||||
cr.LookupKey = peer.MyLookupKp.Public
|
cr.LookupKey = peer.MyLookupKp.Public
|
||||||
// TODO Add key signature
|
// TODO Add key signature
|
||||||
list = append(list, &cr)
|
list = append(list, &cr)
|
||||||
@ -88,7 +88,7 @@ func (p *Peer) BuildSimpleUserMessage(message []byte) (*meowlib.UserMessage, err
|
|||||||
msg.From = p.MyIdentity.Public
|
msg.From = p.MyIdentity.Public
|
||||||
msg.Data = message
|
msg.Data = message
|
||||||
msg.Type = "1"
|
msg.Type = "1"
|
||||||
msg.Status = &meowlib.UserMessage_ConversationStatus{}
|
msg.Status = &meowlib.ConversationStatus{}
|
||||||
msg.Status.LocalUuid = uuid.New().String()
|
msg.Status.LocalUuid = uuid.New().String()
|
||||||
return &msg, nil
|
return &msg, nil
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ func (p *Peer) BuildSingleFileMessage(filename string, message []byte) ([]meowli
|
|||||||
msg.Files = append(msg.Files, &file)
|
msg.Files = append(msg.Files, &file)
|
||||||
msg.Type = "2"
|
msg.Type = "2"
|
||||||
if chunk == 0 {
|
if chunk == 0 {
|
||||||
msg.Status = &meowlib.UserMessage_ConversationStatus{}
|
msg.Status = &meowlib.ConversationStatus{}
|
||||||
msg.Status.LocalUuid = uuid.New().String()
|
msg.Status.LocalUuid = uuid.New().String()
|
||||||
}
|
}
|
||||||
msgs = append(msgs, msg)
|
msgs = append(msgs, msg)
|
||||||
@ -196,8 +196,8 @@ func (p *Peer) UnPackUserMessage(protoPackedMessage []byte) (payload []byte, sig
|
|||||||
return msg.Payload, msg.Signature, nil
|
return msg.Payload, msg.Signature, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Peer) GetConversationRequest() *meowlib.ToServerMessage_ConversationRequest {
|
func (p *Peer) GetConversationRequest() *meowlib.ConversationRequest {
|
||||||
var cr meowlib.ToServerMessage_ConversationRequest
|
var cr meowlib.ConversationRequest
|
||||||
return &cr
|
return &cr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func (ints *InternalServer) AsymDecryptMessage(Message []byte, Signature []byte)
|
|||||||
return DecryptedMessage, err
|
return DecryptedMessage, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array
|
// BuildToServerMessageFromUserMessage creates a basic message to server from a single packed user message and returns a meowlib.ToServerMessage
|
||||||
func (ints *InternalServer) BuildToServerMessageFromUserMessage(usermsg *meowlib.PackedUserMessage) *meowlib.ToServerMessage {
|
func (ints *InternalServer) BuildToServerMessageFromUserMessage(usermsg *meowlib.PackedUserMessage) *meowlib.ToServerMessage {
|
||||||
var msg meowlib.ToServerMessage
|
var msg meowlib.ToServerMessage
|
||||||
msg.Uuid = uuid.New().String()
|
msg.Uuid = uuid.New().String()
|
||||||
@ -76,7 +76,7 @@ func (ints *InternalServer) BuildToServerMessageFromUserMessage(usermsg *meowlib
|
|||||||
return &msg
|
return &msg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array
|
// BuildMessageSendingMessage creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array
|
||||||
func (ints *InternalServer) BuildMessageSendingMessage(usermsg *meowlib.PackedUserMessage) ([]byte, error) {
|
func (ints *InternalServer) BuildMessageSendingMessage(usermsg *meowlib.PackedUserMessage) ([]byte, error) {
|
||||||
msg := ints.BuildToServerMessageFromUserMessage(usermsg)
|
msg := ints.BuildToServerMessageFromUserMessage(usermsg)
|
||||||
out, err := proto.Marshal(msg)
|
out, err := proto.Marshal(msg)
|
||||||
@ -86,7 +86,7 @@ func (ints *InternalServer) BuildMessageSendingMessage(usermsg *meowlib.PackedUs
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array
|
// BuildMessageRequestMessage creates a message lookup message to server and returns it as protobuf serialized byte array
|
||||||
func (ints *InternalServer) BuildMessageRequestMessage(lookupKeys []string) ([]byte, error) {
|
func (ints *InternalServer) BuildMessageRequestMessage(lookupKeys []string) ([]byte, error) {
|
||||||
var msg meowlib.ToServerMessage
|
var msg meowlib.ToServerMessage
|
||||||
msg.Uuid = uuid.New().String()
|
msg.Uuid = uuid.New().String()
|
||||||
@ -100,7 +100,7 @@ func (ints *InternalServer) BuildMessageRequestMessage(lookupKeys []string) ([]b
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a basic message to server from a single packed user message and returns it as protobuf serialized byte array
|
// BuildToServerMessageInvitation creates an invintatio message to server from a single packed user message and returns it as a meowlib.ToServerMessage
|
||||||
func (ints *InternalServer) BuildToServerMessageInvitation(invitation *meowlib.ContactCard, password string, timeout int, urllen int) (*meowlib.ToServerMessage, error) {
|
func (ints *InternalServer) BuildToServerMessageInvitation(invitation *meowlib.ContactCard, password string, timeout int, urllen int) (*meowlib.ToServerMessage, error) {
|
||||||
var msg meowlib.ToServerMessage
|
var msg meowlib.ToServerMessage
|
||||||
var inv meowlib.Invitation
|
var inv meowlib.Invitation
|
||||||
|
11
doc/docgen.sh
Executable file
11
doc/docgen.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
go-plantuml generate -o generated/meowlib.puml -d ..
|
||||||
|
sed -i 's/\.\./meowlib\ /g' generated/meowlib.puml
|
||||||
|
go-plantuml generate -o generated/client.puml -d ../client
|
||||||
|
sed -i 's/\.\.\/client/client/g' generated/client.puml
|
||||||
|
go-plantuml generate -o generated/server.puml -d ../server
|
||||||
|
sed -i 's/\.\.\/server/server/g' generated/server.puml
|
||||||
|
cd generated
|
||||||
|
plantuml .
|
||||||
|
|
||||||
|
|
223
doc/meow.tex
Normal file
223
doc/meow.tex
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
\documentclass{article}
|
||||||
|
\usepackage{fetamont}
|
||||||
|
\begin{document}
|
||||||
|
\title{
|
||||||
|
\textffm{Meow} messaging protocol}
|
||||||
|
\author{Author
|
||||||
|
\texttt{meow@redroom.link}}
|
||||||
|
\date{\today}
|
||||||
|
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\begin{abstract}
|
||||||
|
|
||||||
|
|
||||||
|
The \textffm{Meow} protocol is a privacy driven instant messaging protocol.
|
||||||
|
That protocol might be used for creating secure and distributed chat services or allowing machine to machine communication.
|
||||||
|
This document describes the services provided by the protocol, the messaging structures and the transport protocols that might be used.
|
||||||
|
\begin{quote}
|
||||||
|
|
||||||
|
\centering
|
||||||
|
\emph{"Nous ne vivrons pas d'utopie collective, nous arrivons trop tard, le grand marché est déjà là.
|
||||||
|
Nous devons élaborer des stratégies de survie et de contamination, par la prolifération d'utopies privées, cryptées, qui se substitueront à l'ancien ordre social.
|
||||||
|
Tout ce que je sais, c'est que nous vivons dans un monde dont on ne s'évade pas"}\\
|
||||||
|
\footnotesize{Maurice G. Dantec for NOII (1997)}
|
||||||
|
\end{quote}
|
||||||
|
\end{abstract}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Services}
|
||||||
|
\subsection{Unregulated identities}
|
||||||
|
The only requirement to get a valid \textffm{Meow} identity is to generate a user key pair.
|
||||||
|
No phone number or email check will be performed, unlike main instant messaging protocols, there is no central administration.
|
||||||
|
|
||||||
|
\subsection{Fine grained privacy control}
|
||||||
|
|
||||||
|
\subsubsection{Trustable server based communication}
|
||||||
|
Like most widely available messaging softwares, (Whatsapp, Signal, Viber, Telegram...), \textffm{Meow} provides a simple server based messaging.
|
||||||
|
The main difference is that \textffm{Meow} allows you to explicitly choose which server you want to use.
|
||||||
|
The server code being open source, we strongly encourage you to run your own server at home or in your company.
|
||||||
|
The server requires very few ressources and will run on any low cost single board computer.
|
||||||
|
|
||||||
|
\subsubsection{Anonymized message transfer}
|
||||||
|
\textffm{Meow} also provides an anonymizing transfer service very similar to the Tor Onion protocol, we call it the Matriochka protocol.
|
||||||
|
Any server can be used for building the transfer chain.
|
||||||
|
Some of them might be marked as trusted.
|
||||||
|
Random delays might be set for each forwarding step, making the overall message tracking much more difficult, even with a global network survey.
|
||||||
|
It is strongly advised to use trusted servers as your first node and message server (the one that holds your incoming messages).
|
||||||
|
|
||||||
|
\subsubsection{Presence protocol for direct messaging}
|
||||||
|
A presence service associating your conversation keys to your IP address for direct peer to peer connection is also provided.
|
||||||
|
The presence protocol is simply activated by setting a flag in the message poll requests.
|
||||||
|
If that flag is set, your encrypted IP will be published on the server, allowing your only your peer(s) to decrypt it and directly communicate with your terminal.
|
||||||
|
|
||||||
|
\subsubsection{Peer based privacy settings}
|
||||||
|
You might define specific communication privacy preferences for each of your contacts:
|
||||||
|
\begin{itemize}
|
||||||
|
\item simple server based communication allowed for Joe,
|
||||||
|
\item preferred direct communication with Julian, fallback to my own server,
|
||||||
|
\item required matriochka protocol for Edward, first node is one of my trusted servers, my message node is my own server, randomly switch from trusted server lists for others.
|
||||||
|
\item ...
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsubsection{Resistance to device requisition / forensic}
|
||||||
|
All your contact information and discussion are encrypted on the device and password protected.
|
||||||
|
Password shall be asked on application startup and allows your identity file and contact decrytion.
|
||||||
|
That password is not recoverable, so you can't forget it, or you'll loose your whole configuration and identity.
|
||||||
|
Real security implies some constraints.
|
||||||
|
You might configure the app to save your password, but that is a security flaw.
|
||||||
|
In many authoritarian countries, you are required by law to provide your device passwords to authorities.
|
||||||
|
In a \textffm{Meow} device, you might set a specific password for some contacts.
|
||||||
|
Those contacts won't be visible when entering your main identity password.
|
||||||
|
You'll have to type their specific password in order to make them visible.
|
||||||
|
The \textffm{Meow} application will by default create a random set of fake hidden contacts and conversations.
|
||||||
|
Even in case of device storage analysis, authorities won't be able to differentiate a real hidden contact from an normal fake generated one.
|
||||||
|
It could be argued that this feature puts every user at risk, because authorities might think you're hiding something, even if you're not.
|
||||||
|
As every \textffm{Meow} user has the same constraint, users are not responsible for that. Moreover solidarity is also a requirement for real security.
|
||||||
|
|
||||||
|
\subsection{Multiple devices support}
|
||||||
|
\textffm{Meow} allows you to be connected from multiple devices and offers chat synchronization capability.
|
||||||
|
A device might be revoqued anytime from any other one. Proof of your identity (password or other) shall be provided in order to grant device revocation.
|
||||||
|
|
||||||
|
\subsection{Adding contacts}
|
||||||
|
If you want to add a new contact, keys will be generated, then a contact card will be created.
|
||||||
|
That contact card might be sent by any trustable communication means, or preferably from hand to hand, as a file on a flash disk or a QR code.\\
|
||||||
|
In return your contact will provide a similar contact card as an answer to your invitation.
|
||||||
|
|
||||||
|
\subsection{Contacts forwarding}
|
||||||
|
By using the \textffm{Meow} protocol a user won't be able to forward your contact information without your consent.
|
||||||
|
Each user knows you as a different identity, thus forwarding a known identity to another user is meaningless. Any message to that identity signed by another user than you would be discarded.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Group conversation}
|
||||||
|
A very basic group messaging service is available. It allows to exchange group information between users. After that, a message to a group will send a copy of the message to each member.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Emergency broadcast}
|
||||||
|
A local (server based) emergency broadcast service will be provided. It will provide the ability to send/receive broadcast messages to all users connected to the current server.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Public networks shortage resilience}
|
||||||
|
\textffm{Meow} may run without Internet connection, either on an isolated wifi access point, or on a meshed network of wifi routers or even via serial IOT transport layers (LoRa,...)
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{User directory service}
|
||||||
|
This service allows restoring a lost functionality of Internet historic chat services (like ICQ). You could simply set a "Free for chat" status that would allow other people to contact you, either randomly or based on a short description that you might provide.
|
||||||
|
Why providing that service while the internet is suffocating due to the abundance of social networks ?\\
|
||||||
|
Well, that option offers a few advantages :
|
||||||
|
\begin{itemize}
|
||||||
|
\item you are still an anonymous user chatting with other anonymous users;
|
||||||
|
\item no social network algorithm will select people that think/behave/vote/eat... just like you. Diversity makes a better world;
|
||||||
|
\item a smaller community of users, skilled enough to operate a \textffm{Meow} chat app... that might provide a first filter;
|
||||||
|
It's a bit like in the early ages, when people had to be able to start a win98 computer, connect it to internet, then download and install ICQ...
|
||||||
|
If you lost some time in social networks, and experienced ICQ in the 2000's, you'll understand.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\section{Identities and keys}
|
||||||
|
|
||||||
|
\subsection{User identity}
|
||||||
|
Each \textffm{Meow} user has a unique identity. That identity is strictly private, only used to manage your own data (local encryption, devices, ...)
|
||||||
|
Let's call that one the User Key Pair (Ukp)
|
||||||
|
|
||||||
|
\subsection{Contact identity}
|
||||||
|
Each of your contacts will know you under a different identity, we'll call that one the Contact Key Pair (Ckp)
|
||||||
|
That contact Key Pair will not change once it's agreed between both peers: an initial key will be exchanged as part of the peer invitation process.
|
||||||
|
As other people might have seen your key, this means that :
|
||||||
|
\begin{itemize}
|
||||||
|
\item none of your contacts will be able to forward your id to another person without your consent;
|
||||||
|
\item any message to that Ckp, not signed by its associated user, will be discarded.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{Conversation encryption}
|
||||||
|
Each conversation with one of your contacts will be encrypted using an encryption keypair (Ekp) allowing cyphering your conversation.
|
||||||
|
The Ekp might be changed anytime by its owner and the new public key will be sent along the last message.
|
||||||
|
|
||||||
|
\subsection{Conversation lookup}
|
||||||
|
A contact conversation Lookup Key Pair(Lkp) is also associated with your conversation. The Lkp public key is used to identify your conversation on a server.
|
||||||
|
The private key allows you to sign your request and prove the server that you are the legitimate recipient for a message.
|
||||||
|
This Lkp can be changed anytime by its owner and the new public key will be sent along the last message.
|
||||||
|
The Lkp and the Ekp are only changed once the change has beeen acknowledged by your contact.
|
||||||
|
|
||||||
|
\subsection{Server identity}
|
||||||
|
Each server has a Server key (Skp). That key allows you to cypher the messages that you're sending to the server.
|
||||||
|
|
||||||
|
\subsection{Device identity}
|
||||||
|
Each device is identified by a device key (Dkp) that allows you to perform secured exchanges between your devices for synchronization/revocation purposes.
|
||||||
|
Communication between devices is achieved using the same principle as the user to user communication. A device might be considered as any another user. The messages content is based on a synchronization protocol.
|
||||||
|
|
||||||
|
\section{Contact management}
|
||||||
|
\subsection{Adding a contact}
|
||||||
|
Rendez-vous card, containing :
|
||||||
|
\begin{itemize}
|
||||||
|
\item Your public key for that contact;
|
||||||
|
\item An initial conversation public key for getting encrypted messages from that contact;
|
||||||
|
\item An initial conversation uuid that you'll use to lookup for incoming messages on the servers;
|
||||||
|
\item A list of your preferred message servers;
|
||||||
|
\item A signature to prevent transmission of tampered data.
|
||||||
|
\end{itemize}
|
||||||
|
\subsection{Sharing a contact}
|
||||||
|
If a user wants to forward one of his contacts to you, it will be handled as a double request:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item I'm receiving a contact name, without any key
|
||||||
|
\item
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\section{Messaging}
|
||||||
|
\subsection{User messages}
|
||||||
|
TODO
|
||||||
|
|
||||||
|
\subsection{Server stored message}
|
||||||
|
TODO
|
||||||
|
|
||||||
|
\subsection{Matriochka message packing}
|
||||||
|
TODO
|
||||||
|
|
||||||
|
\subsection{Synchronization messages}
|
||||||
|
TODO
|
||||||
|
|
||||||
|
\section{Transport protocols}
|
||||||
|
\subsection{URLs}
|
||||||
|
Server urls do define the protocol used for communicating with the server.
|
||||||
|
Some of the protocols will be described hereafter, but that list is not exhaustive and might be extended in the future.\\
|
||||||
|
Examples of a valid url:
|
||||||
|
\begin{verbatim}
|
||||||
|
http://myserver.com
|
||||||
|
https://user:pass@myauthenticatedserver.net:8443
|
||||||
|
mqtt://mymqttserver:6203
|
||||||
|
udp://myudpserver.org:41325
|
||||||
|
serial://dev/ttyS0
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
\subsection{HTTP/S}
|
||||||
|
TODO
|
||||||
|
|
||||||
|
\subsection{UDP}
|
||||||
|
TODO
|
||||||
|
|
||||||
|
\subsection{Internetless alternative routing}
|
||||||
|
TODO
|
||||||
|
|
||||||
|
\section{Server Features}
|
||||||
|
\subsection{Server catalog}
|
||||||
|
Each server will cache a list of all the servers that it is aware of.
|
||||||
|
|
||||||
|
\subsection{Antispam}
|
||||||
|
|
||||||
|
\subsection{Self defense}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\section{Backup}
|
||||||
|
\section{Recovery}
|
||||||
|
|
||||||
|
\section{Very secure devices}
|
||||||
|
You don't trust your phone ?
|
||||||
|
|
||||||
|
\section{Roadmap}
|
||||||
|
\subsection{Nations}
|
||||||
|
Beyond the scope of user directories, we plan to implement the concept of virtual Nations.
|
||||||
|
Today still, most people don't really choose the nation they live in.
|
||||||
|
|
||||||
|
|
||||||
|
\end{document}
|
155
doc/protocol.tex
155
doc/protocol.tex
@ -1,8 +1,11 @@
|
|||||||
\documentclass{article}
|
\documentclass{article}
|
||||||
\usepackage{fetamont}
|
\usepackage{fetamont}
|
||||||
|
\usepackage{listings}
|
||||||
|
\usepackage{protobuf/lang} % include language definition for protobuf
|
||||||
|
\usepackage{protobuf/style} % include custom style for proto declarations.
|
||||||
\begin{document}
|
\begin{document}
|
||||||
\title{
|
\title{
|
||||||
\textffm{Meow} messaging protocol}
|
\textffm{Meow} messaging protocol description}
|
||||||
\author{Author
|
\author{Author
|
||||||
\texttt{meow@redroom.link}}
|
\texttt{meow@redroom.link}}
|
||||||
\date{\today}
|
\date{\today}
|
||||||
@ -25,155 +28,13 @@ Tout ce que je sais, c'est que nous vivons dans un monde dont on ne s'évade pas
|
|||||||
\end{quote}
|
\end{quote}
|
||||||
\end{abstract}
|
\end{abstract}
|
||||||
|
|
||||||
|
\section{Identity creation}
|
||||||
|
|
||||||
\section{Services}
|
\section{Messages structure}
|
||||||
\subsection{Unregulated identities}
|
\lstinputlisting[language=protobuf2,style=protobuf]{../pb/messages.proto}
|
||||||
The only requirement to get a valid \textffm{Meow} identity is to generate a user key pair.
|
|
||||||
No phone number or email check will be performed, unlike main instant messaging protocols, there is no central administration.
|
|
||||||
|
|
||||||
\subsection{Fine grained privacy control}
|
\section{Invitation process}
|
||||||
|
|
||||||
\subsubsection{Trustable server based communication}
|
|
||||||
Like most widely available messaging softwares, (Whatsapp, Signal, Viber, Telegram...), \textffm{Meow} provides a simple server based messaging.
|
|
||||||
The main difference is that \textffm{Meow} allows you to explicitly choose which server you want to use.
|
|
||||||
The server code being open source, we strongly encourage you to run your own server at home or in your company.
|
|
||||||
The server requires very few ressources and will run on any low cost single board computer.
|
|
||||||
|
|
||||||
\subsubsection{Anonymized message transfer}
|
|
||||||
\textffm{Meow} also provides an anonymizing transfer service very similar to the Tor Onion protocol, we call it the Matriochka protocol.
|
|
||||||
Any server can be used for building the transfer chain.
|
|
||||||
Some of them might be marked as trusted.
|
|
||||||
Random delays might be set for each forwarding step, making the overall message tracking much more difficult, even with a global network survey.
|
|
||||||
It is strongly advised to use trusted servers as your first node and message server (the one that holds your incoming messages).
|
|
||||||
|
|
||||||
\subsubsection{Presence protocol for direct messaging}
|
|
||||||
A presence service associating your conversation keys to your IP address for direct peer to peer connection is also provided.
|
|
||||||
The presence protocol is simply activated by setting a flag in the message poll requests.
|
|
||||||
If that flag is set, your encrypted IP will be published on the server, allowing your only your peer(s) to decrypt it and directly communicate with your terminal.
|
|
||||||
|
|
||||||
\subsubsection{Peer based privacy settings}
|
|
||||||
You might define specific communication privacy preferences for each of your contacts:
|
|
||||||
\begin{itemize}
|
|
||||||
\item simple server based communication allowed for Joe,
|
|
||||||
\item preferred direct communication with Julian, fallback to my own server,
|
|
||||||
\item required matriochka protocol for Edward, first node is one of my trusted servers, my message node is my own server, randomly switch from trusted server lists for others.
|
|
||||||
\item ...
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
\subsubsection{Resistance to device requisition / forensic}
|
|
||||||
All your contact information and discussion are encrypted on the device and password protected.
|
|
||||||
Password shall be asked on application startup and allows your identity file and contact decrytion.
|
|
||||||
That password is not recoverable, so you can't forget it, or you'll loose your whole configuration and identity.
|
|
||||||
Real security implies some constraints.
|
|
||||||
You might configure the app to save your password, but that is a security flaw.
|
|
||||||
In many authoritarian countries, you are required by law to provide your device passwords to authorities.
|
|
||||||
In a \textffm{Meow} device, you might set a specific password for some contacts.
|
|
||||||
Those contacts won't be visible when entering your main identity password.
|
|
||||||
You'll have to type their specific password in order to make them visible.
|
|
||||||
The \textffm{Meow} application will by default create a random set of fake hidden contacts and conversations.
|
|
||||||
Even in case of device storage analysis, authorities won't be able to differentiate a real hidden contact from an normal fake generated one.
|
|
||||||
It could be argued that this feature puts every user at risk, because authorities might think you're hiding something, even if you're not.
|
|
||||||
As every \textffm{Meow} user has the same constraint, users are not responsible for that. Moreover solidarity is also a requirement for real security.
|
|
||||||
|
|
||||||
\subsection{Multiple devices support}
|
|
||||||
\textffm{Meow} allows you to be connected from multiple devices and offers chat synchronization capability.
|
|
||||||
A device might be revoqued anytime from any other one. Proof of your identity (password or other) shall be provided in order to grant device revocation.
|
|
||||||
|
|
||||||
\subsection{Adding contacts}
|
|
||||||
If you want to add a new contact, keys will be generated, then a contact card will be created.
|
|
||||||
That contact card might be sent by any trustable communication means, or preferably from hand to hand, as a file on a flash disk or a QR code.\\
|
|
||||||
In return your contact will provide a similar contact card as an answer to your invitation.
|
|
||||||
|
|
||||||
\subsection{Contacts forwarding}
|
|
||||||
By using the \textffm{Meow} protocol a user won't be able to forward your contact information without your consent.
|
|
||||||
Each user knows you as a different identity, thus forwarding a known identity to another user is meaningless. Any message to that identity signed by another user than you would be discarded.
|
|
||||||
|
|
||||||
|
|
||||||
\subsection{Group conversation}
|
|
||||||
A very basic group messaging service is available. It allows to exchange group information between users. After that, a message to a group will send a copy of the message to each member.
|
|
||||||
|
|
||||||
|
|
||||||
\subsection{Emergency broadcast}
|
|
||||||
A local (server based) emergency broadcast service will be provided. It will provide the ability to send/receive broadcast messages to all users connected to the current server.
|
|
||||||
|
|
||||||
|
|
||||||
\subsection{Public networks shortage resilience}
|
|
||||||
\textffm{Meow} may run without Internet connection, either on an isolated wifi access point, or on a meshed network of wifi routers or even via serial IOT transport layers (LoRa,...)
|
|
||||||
|
|
||||||
|
|
||||||
\subsection{User directory service}
|
|
||||||
This service allows restoring a lost functionality of Internet historic chat services (like ICQ). You could simply set a "Free for chat" status that would allow other people to contact you, either randomly or based on a short description that you might provide.
|
|
||||||
Why providing that service while the internet is suffocating due to the abundance of social networks ?\\
|
|
||||||
Well, that option offers a few advantages :
|
|
||||||
\begin{itemize}
|
|
||||||
\item you are still an anonymous user chatting with other anonymous users;
|
|
||||||
\item no social network algorithm will select people that think/behave/vote/eat... just like you. Diversity makes a better world;
|
|
||||||
\item a smaller community of users, skilled enough to operate a \textffm{Meow} chat app... that might provide a first filter;
|
|
||||||
It's a bit like in the early ages, when people had to be able to start a win98 computer, connect it to internet, then download and install ICQ...
|
|
||||||
If you lost some time in social networks, and experienced ICQ in the 2000's, you'll understand.
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
\section{Identities and keys}
|
|
||||||
|
|
||||||
\subsection{User identity}
|
|
||||||
Each \textffm{Meow} user has a unique identity. That identity is strictly private, only used to manage your own data (local encryption, devices, ...)
|
|
||||||
Let's call that one the User Key Pair (Ukp)
|
|
||||||
|
|
||||||
\subsection{Contact identity}
|
|
||||||
Each of your contacts will know you under a different identity, we'll call that one the Contact Key Pair (Ckp)
|
|
||||||
That contact Key Pair will not change once it's agreed between both peers: an initial key will be exchanged as part of the peer invitation process.
|
|
||||||
As other people might have seen your key, this means that :
|
|
||||||
\begin{itemize}
|
|
||||||
\item none of your contacts will be able to forward your id to another person without your consent;
|
|
||||||
\item any message to that Ckp, not signed by its associated user, will be discarded.
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
\subsection{Conversation encryption}
|
|
||||||
Each conversation with one of your contacts will be encrypted using an encryption keypair (Ekp) allowing cyphering your conversation.
|
|
||||||
The Ekp might be changed anytime by its owner and the new public key will be sent along the last message.
|
|
||||||
|
|
||||||
\subsection{Conversation lookup}
|
|
||||||
A contact conversation Lookup Key Pair(Lkp) is also associated with your conversation. The Lkp public key is used to identify your conversation on a server.
|
|
||||||
The private key allows you to sign your request and prove the server that you are the legitimate recipient for a message.
|
|
||||||
This Lkp can be changed anytime by its owner and the new public key will be sent along the last message.
|
|
||||||
The Lkp and the Ekp are only changed once the change has beeen acknowledged by your contact.
|
|
||||||
|
|
||||||
\subsection{Server identity}
|
|
||||||
Each server has a Server key (Skp). That key allows you to cypher the messages that you're sending to the server.
|
|
||||||
|
|
||||||
\subsection{Device identity}
|
|
||||||
Each device is identified by a device key (Dkp) that allows you to perform secured exchanges between your devices for synchronization/revocation purposes.
|
|
||||||
Communication between devices is achieved using the same principle as the user to user communication. A device might be considered as any another user. The messages content is based on a synchronization protocol.
|
|
||||||
|
|
||||||
\section{Contact management}
|
|
||||||
\subsection{Adding a contact}
|
|
||||||
Rendez-vous card, containing :
|
|
||||||
\begin{itemize}
|
|
||||||
\item Your public key for that contact;
|
|
||||||
\item An initial conversation public key for getting encrypted messages from that contact;
|
|
||||||
\item An initial conversation uuid that you'll use to lookup for incoming messages on the servers;
|
|
||||||
\item A list of your preferred message servers;
|
|
||||||
\item A signature to prevent transmission of tampered data.
|
|
||||||
\end{itemize}
|
|
||||||
\subsection{Sharing a contact}
|
|
||||||
If a user wants to forward one of his contacts to you, it will be handled as a double request:
|
|
||||||
\begin{enumerate}
|
|
||||||
\item I'm receiving a contact name, without any key
|
|
||||||
\item
|
|
||||||
\end{enumerate}
|
|
||||||
|
|
||||||
\section{Messaging}
|
|
||||||
\subsection{User messages}
|
|
||||||
TODO
|
|
||||||
|
|
||||||
\subsection{Server stored message}
|
|
||||||
TODO
|
|
||||||
|
|
||||||
\subsection{Matriochka message packing}
|
|
||||||
TODO
|
|
||||||
|
|
||||||
\subsection{Synchronization messages}
|
|
||||||
TODO
|
|
||||||
|
|
||||||
\section{Transport protocols}
|
\section{Transport protocols}
|
||||||
\subsection{URLs}
|
\subsection{URLs}
|
||||||
|
@ -35,7 +35,7 @@ func (msg *UserMessage) AddFile(filename string, maxMessageSize int64) error {
|
|||||||
file.Data = data
|
file.Data = data
|
||||||
msg.Files = append(msg.Files, &file)
|
msg.Files = append(msg.Files, &file)
|
||||||
|
|
||||||
msg.Status = &UserMessage_ConversationStatus{}
|
msg.Status = &ConversationStatus{}
|
||||||
msg.Status.LocalUuid = uuid.New().String()
|
msg.Status.LocalUuid = uuid.New().String()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
992
messages.pb.go
992
messages.pb.go
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,12 @@
|
|||||||
// Lower field number values take less space in the wire format.
|
// Lower field number values take less space in the wire format.
|
||||||
// For example, field numbers in the range 1 through 15 take one byte to encode.
|
// For example, field numbers in the range 1 through 15 take one byte to encode.
|
||||||
// Field numbers in the range 16 through 2047 take two bytes.
|
// Field numbers in the range 16 through 2047 take two bytes.
|
||||||
|
/**
|
||||||
|
* Meow messages
|
||||||
|
*
|
||||||
|
* This is the Meow protocol protobuf messages description.
|
||||||
|
*
|
||||||
|
*/
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
package meowlib;
|
package meowlib;
|
||||||
option go_package = "forge.redroom.link/yves/meowlib";
|
option go_package = "forge.redroom.link/yves/meowlib";
|
||||||
@ -17,29 +22,31 @@ message PackedServerMessage {
|
|||||||
|
|
||||||
// structure to hold an invitation through a server
|
// structure to hold an invitation through a server
|
||||||
message Invitation {
|
message Invitation {
|
||||||
bytes payload = 1;
|
bytes payload = 1; // invitation payload, encrypted after step 2
|
||||||
int32 timeout = 2;
|
int32 timeout = 2; // how long do I want the invitation to remain available on the server
|
||||||
int32 idlen = 3;
|
int32 idlen = 3; // len of the id you wish for short url transmission
|
||||||
string password = 4;
|
string password = 4; // password tou set for accessin invitation (optional)
|
||||||
string id = 5;
|
string id = 5; // id that the friend shall request to get teh invitation
|
||||||
int64 expiry = 6;
|
int64 expiry = 6; // the server allowed expiry date, it may be samller than the requested timeout according to server policy
|
||||||
int32 step = 7;
|
int32 step = 7; // progress in the inviattion process : 1=invite friend, 2=friend requests invitation, 3=friend's answer, 4=request answer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// structure for requesting incoming messages
|
||||||
|
message ConversationRequest {
|
||||||
|
string lookupKey = 1; // lookup key for a conversation
|
||||||
|
string lastServerUuidOK = 2; // Last Server message UUID received (send me all after that one)
|
||||||
|
bool publishOnline = 3; // ?? Publish my online status for that contact ?
|
||||||
|
string lookupSignature = 4; // prove that I own the private key by signing that block
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// structure defining a message for a server, that will be encrypted, then sent in a "packedmessage" payload
|
// structure defining a message for a server, that will be encrypted, then sent in a "packedmessage" payload
|
||||||
message ToServerMessage {
|
message ToServerMessage {
|
||||||
string type = 1; // Type 1 : final destination / 2 : forward
|
string type = 1; // Type 1 : final destination / 2 : forward
|
||||||
string from = 2 ; // My pub key for the server to send me an encrypter answer
|
string from = 2 ; // My pub key for the server to send me an encrypter answer
|
||||||
bytes payload = 3 ; // optional payload for server
|
bytes payload = 3 ; // optional payload for server
|
||||||
|
|
||||||
// structure for requesting incoming messages
|
|
||||||
message ConversationRequest {
|
|
||||||
string lookupKey = 1; // lookup key for a conversation
|
|
||||||
string lastServerUuidOK = 2; // Last Server message UUID received (send me all after that one)
|
|
||||||
bool publishOnline = 3; // ?? Publish my online status for that contact ?
|
|
||||||
string lookupSignature = 4; // prove that I own the private key by signing that block
|
|
||||||
}
|
|
||||||
|
|
||||||
repeated ConversationRequest pullRequest = 4;
|
repeated ConversationRequest pullRequest = 4;
|
||||||
|
|
||||||
repeated PackedUserMessage messages = 5;
|
repeated PackedUserMessage messages = 5;
|
||||||
@ -54,6 +61,10 @@ message ToServerMessage {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ConversationResponse {
|
||||||
|
repeated string messageUuids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// structure defining a from server receiver message decrypted from a "packedmessage" payload
|
// structure defining a from server receiver message decrypted from a "packedmessage" payload
|
||||||
message FromServerMessage {
|
message FromServerMessage {
|
||||||
string type = 1; // Type
|
string type = 1; // Type
|
||||||
@ -62,10 +73,6 @@ message FromServerMessage {
|
|||||||
string uuidAck = 4 ; // Ack for the last received ToServerMessage Uuid
|
string uuidAck = 4 ; // Ack for the last received ToServerMessage Uuid
|
||||||
string serverUuid = 5 ; // Provides the server uuid that replaced the client uuid
|
string serverUuid = 5 ; // Provides the server uuid that replaced the client uuid
|
||||||
|
|
||||||
message ConversationResponse {
|
|
||||||
repeated string messageUuids = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
repeated PackedUserMessage chat = 6;
|
repeated PackedUserMessage chat = 6;
|
||||||
|
|
||||||
repeated Server knownServers = 7;
|
repeated Server knownServers = 7;
|
||||||
@ -90,10 +97,10 @@ message Matriochka {
|
|||||||
|
|
||||||
// structure describing required server attributes
|
// structure describing required server attributes
|
||||||
message Server {
|
message Server {
|
||||||
string name = 1;
|
string name = 1; // friendly server name
|
||||||
string description=2;
|
string description=2; // description : owner type (company/private/university...),
|
||||||
string publicKey = 3;
|
string publicKey = 3; // public key you must use to send encrypted messages to that server
|
||||||
string url = 4;
|
string url = 4; // meow server url
|
||||||
bool publish = 5; // publish this server when asked for a list by server
|
bool publish = 5; // publish this server when asked for a list by server
|
||||||
bytes signature = 6; // signature of all previous fields by the server itself
|
bytes signature = 6; // signature of all previous fields by the server itself
|
||||||
int32 confidenceLevel = 7; // additional info from the user
|
int32 confidenceLevel = 7; // additional info from the user
|
||||||
@ -101,11 +108,11 @@ message Server {
|
|||||||
|
|
||||||
// structure describing a user contact card ie the minimum set of attributes for exchanging identities
|
// structure describing a user contact card ie the minimum set of attributes for exchanging identities
|
||||||
message ContactCard {
|
message ContactCard {
|
||||||
string name=1;
|
string name=1; // contact nickname
|
||||||
string contactPublicKey =2;
|
string contactPublicKey =2; // contact public key, will be used to authenticate her/his messages
|
||||||
string encryptionPublicKey= 3;
|
string encryptionPublicKey= 3; // public key you must use to to write encrypted messages to that contact
|
||||||
string lookupPublicKey =4;
|
string lookupPublicKey =4; // public key you will use as "destination identifier" for her/him to lookup for your messages on the servers
|
||||||
repeated Server pullServers =5;
|
repeated Server pullServers =5; // list the servers where the contact will look for messages from you
|
||||||
uint32 version = 6;
|
uint32 version = 6;
|
||||||
string invitationId=7;
|
string invitationId=7;
|
||||||
}
|
}
|
||||||
@ -118,14 +125,7 @@ message PackedUserMessage {
|
|||||||
repeated int64 serverTimestamp=4; // server time stamp, might be several in matriochka mode
|
repeated int64 serverTimestamp=4; // server time stamp, might be several in matriochka mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ConversationStatus {
|
||||||
// structure defining information that might be exchanged between two peers.
|
|
||||||
message UserMessage {
|
|
||||||
string destination = 1; // Lookupkey
|
|
||||||
string from = 2; // My public key for that contact
|
|
||||||
string type = 3;
|
|
||||||
bytes data = 4;
|
|
||||||
message ConversationStatus {
|
|
||||||
string localUuid = 1;
|
string localUuid = 1;
|
||||||
uint64 localSequence = 2 ;
|
uint64 localSequence = 2 ;
|
||||||
uint64 sent = 3 ;
|
uint64 sent = 3 ;
|
||||||
@ -134,16 +134,25 @@ message UserMessage {
|
|||||||
ContactCard myNextIdentity = 6;
|
ContactCard myNextIdentity = 6;
|
||||||
int32 peerNextIdentityAck = 7; // version of the new peer accepted id
|
int32 peerNextIdentityAck = 7; // version of the new peer accepted id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Group{
|
||||||
|
string name=1;
|
||||||
|
repeated ContactCard members = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// structure defining information that might be exchanged between two peers.
|
||||||
|
message UserMessage {
|
||||||
|
string destination = 1; // Lookupkey
|
||||||
|
string from = 2; // My public key for that contact
|
||||||
|
string type = 3;
|
||||||
|
bytes data = 4;
|
||||||
|
|
||||||
ConversationStatus Status = 5;
|
ConversationStatus Status = 5;
|
||||||
|
|
||||||
ContactCard contact = 6;
|
ContactCard contact = 6;
|
||||||
|
|
||||||
Server knownServers = 7;
|
Server knownServers = 7;
|
||||||
|
|
||||||
message Group{
|
|
||||||
string name=1;
|
|
||||||
repeated ContactCard members = 2;
|
|
||||||
}
|
|
||||||
Group group = 8;
|
Group group = 8;
|
||||||
|
|
||||||
repeated File files = 9;
|
repeated File files = 9;
|
||||||
|
@ -3,4 +3,10 @@ protoc -I=. --go_out=.. messages.proto
|
|||||||
mv ../forge.redroom.link/yves/meowlib/messages.pb.go ../
|
mv ../forge.redroom.link/yves/meowlib/messages.pb.go ../
|
||||||
rm -rf ../forge.redroom.link
|
rm -rf ../forge.redroom.link
|
||||||
|
|
||||||
#protoc -I=. --dart_out=../../../flutter/meowlib/lib/ messages.proto
|
protoc --plugin=protoc-gen-doc=/usr/bin/protoc-gen-doc \
|
||||||
|
--doc_out=../doc/generated \
|
||||||
|
--doc_opt=html,index.html \
|
||||||
|
*.proto
|
||||||
|
|
||||||
|
protoc --plugin=protoc-gen-uml=/usr/bin/protoc-gen-uml \
|
||||||
|
--uml_out=../doc/generated -I=. *.proto
|
||||||
|
Loading…
Reference in New Issue
Block a user