This commit is contained in:
N 2022-09-02 12:07:21 +02:00
parent 3966299a91
commit 6d183d2b59
21 changed files with 524 additions and 289 deletions

View File

@ -66,41 +66,41 @@ func Decrypt(privateKey string, data []byte) ([]byte, error) {
if err != nil { if err != nil {
log.Error().Msg("Message decryption b64 failed") log.Error().Msg("Message decryption b64 failed")
} }
decrypted, err := helper.DecryptBinaryMessageArmored(string(priv), []byte(""), string(data)) decrypted, err := helper.DecryptBinaryMessageArmored(string(priv), nil, string(data))
if err != nil { if err != nil {
log.Error().Msg("Message decryption failed") log.Error().Msg("Message decryption failed")
} }
return []byte(decrypted), err return []byte(decrypted), err
} }
func EncryptAndSign(publicKey string, privateKey string, data []byte) ([]byte, []byte, error) { func EncryptAndSign(publicEncKey string, privateSignKey string, data []byte) ([]byte, []byte, error) {
pub, err := base64.StdEncoding.DecodeString(publicKey) pub, err := base64.StdEncoding.DecodeString(publicEncKey)
if err != nil { if err != nil {
log.Error().Msg("Message encryption and sign b64 failed") log.Error().Msg("Message encryption and sign b64 failed")
} }
priv, err := base64.StdEncoding.DecodeString(privateKey) priv, err := base64.StdEncoding.DecodeString(privateSignKey)
if err != nil { if err != nil {
log.Error().Msg("Message encryption and sign b64 failed") log.Error().Msg("Message encryption and sign b64 failed")
} }
armor, signature, err := helper.EncryptSignBinaryDetached(string(pub), string(priv), []byte(""), data) encrypted, signature, err := helper.EncryptSignBinaryDetached(string(pub), string(priv), nil, data)
if err != nil { if err != nil {
log.Error().Msg("Message encryption and sign failed") log.Error().Msg("Message encryption and sign failed")
} }
return []byte(armor), []byte(signature), err return []byte(encrypted), []byte(signature), err
} }
func DecryptAndSign(publicKey string, privateKey string, data []byte, signature []byte) ([]byte, error) { func DecryptAndCheck(MyPrivateEncryptionKey string, peerContactPublicKey string, data []byte, signature []byte) (DecryptedMessage []byte, err error) {
pub, err := base64.StdEncoding.DecodeString(publicKey) pub, err := base64.StdEncoding.DecodeString(MyPrivateEncryptionKey)
if err != nil { if err != nil {
log.Error().Msg("Message decryption and sign b64 failed") log.Error().Msg("Message decryption and sign b64 failed")
} }
priv, err := base64.StdEncoding.DecodeString(privateKey) priv, err := base64.StdEncoding.DecodeString(peerContactPublicKey)
if err != nil { if err != nil {
log.Error().Msg("Message decryption and sign b64 failed") log.Error().Msg("Message decryption and sign b64 failed")
} }
decrypted, err := helper.DecryptVerifyBinaryDetached(string(pub), string(priv), []byte(""), data, string(signature)) DecryptedMessage, err = helper.DecryptVerifyBinaryDetached(string(pub), string(priv), nil, data, string(signature))
if err != nil { if err != nil {
log.Error().Msg("Message decryption and sign failed") log.Error().Msg("Message decryption and sign failed")
} }
return decrypted, err return DecryptedMessage, err
} }

View File

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"log" "log"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestNewKeyPair(t *testing.T) { func TestNewKeyPair(t *testing.T) {
@ -21,7 +23,36 @@ func TestGetKey(t *testing.T) {
// fmt.Println(key.Armor()) // fmt.Println(key.Armor())
Armpubkey, _ := key.GetArmoredPublicKey() Armpubkey, _ := key.GetArmoredPublicKey()
pubkey := base64.StdEncoding.EncodeToString([]byte(Armpubkey)) pubkey := base64.StdEncoding.EncodeToString([]byte(Armpubkey))
if kp.Public != pubkey { assert.Equal(t, kp.Public, pubkey, "The two public keys should be the same.")
log.Fatal("error in public key") //if kp.Public != pubkey {
// log.Fatal("error in public key")
//}
} }
func TestEncryptDecrypt(t *testing.T) {
kp := NewKeyPair()
foo := "totoaimelesfrites!"
encMess, err := Encrypt(kp.Public, []byte(foo))
if err != nil {
log.Println(err.Error())
}
decMess, err2 := Decrypt(kp.Private, encMess)
if err2 != nil {
log.Println(err2.Error())
}
assert.Equal(t, foo, decMess, "The two messages should be the same.")
}
func TestEncryptDecryptSigned(t *testing.T) {
kp := NewKeyPair()
foo := "totoaimelesfrites!"
encMess, sign, err := EncryptAndSign(kp.Public, kp.Private, []byte(foo))
if err != nil {
log.Println(err.Error())
}
decMess, err2 := DecryptAndCheck(kp.Private, kp.Public, encMess, sign)
if err2 != nil {
log.Println(err2.Error())
}
assert.Equal(t, foo, string(decMess), "The two messages should be the same.")
} }

View File

@ -35,12 +35,12 @@ No phone number or email check will be performed, unlike main instant messaging
\subsubsection{Trustable server based communication} \subsubsection{Trustable server based communication}
Like most widely available messaging softwares, (Whatsapp, Signal, Viber, Telegram...), \textffm{Meow} provides a simple server based messaging. Like most widely available messaging softwares, (Whatsapp, Signal, Viber, Telegram...), \textffm{Meow} provides a simple server based messaging.
The main difference is that allows to explicitly choose which server you want to use. The main difference is it allows 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 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. The server requires very few ressources and will run on any low cost single board computer.
\subsubsection{Anonymized message transfer} \subsubsection{Anonymized message transfer}
\textffm{Meow} also provides an anonymizing transfer services very similar to the Tor Onion protocol, we called it the Matriochka protocol. \textffm{Meow} also provides an anonymizing transfer services very similar to the Tor Onion protocol, we call it the Matriochka protocol.
Any server can be used for building the transfer chain. Any server can be used for building the transfer chain.
Some of them might be marked as trusted. Some of them might be marked as trusted.
It is strongly advised to use trusted servers as your first node and message server (the one that holds your incoming messages). It is strongly advised to use trusted servers as your first node and message server (the one that holds your incoming messages).
@ -54,13 +54,13 @@ If that flag is set, your encrypted IP will be published on the server, allowing
You might define specific communication privacy preferences for each of your contacts: You might define specific communication privacy preferences for each of your contacts:
\begin{itemize} \begin{itemize}
\item simple server based communication allowed for Joe, \item simple server based communication allowed for Joe,
\item direct communication prefered with Julian, fallback to my own server, \item preferred direct communication with Julian, fallback to my own server,
\item matriochka protocol required 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 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 ... \item ...
\end{itemize} \end{itemize}
\subsection{Multiple devices support} \subsection{Multiple devices support}
\textffm{Meow} allows you to be connected from multiple devices and offers chat synchronization capability. \textffm{Meow} allows you to be connected from multiple devices and offers chat synchronization capability.
A device might be revoqued anytime from an other any one. Proof of your identity (password or other) shall be provided in order to grant device revocation. 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} \subsection{Adding contacts}
If you want to add a new contact, keys and uuids will be generated, then a rendez-vous card will be created. If you want to add a new contact, keys and uuids will be generated, then a rendez-vous card will be created.
@ -68,8 +68,8 @@ That rendez-vous card might be sent by any trustable communication means, or pre
In return your contact will provide the exact same data, encrypted with your public key and delivered to the address specified in the initial rendez-vous card. In return your contact will provide the exact same data, encrypted with your public key and delivered to the address specified in the initial rendez-vous card.
\subsection{Contacts forwarding} \subsection{Contacts forwarding}
Using the \textffm{Meow} protocol a user won't be able to forward your contact information without your consent. 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 thna you would be discarded. 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} \subsection{Group conversation}
@ -81,18 +81,18 @@ A local (server based) emergency broadcast service will be provided. It will pro
\subsection{Public networks shortage resilience} \subsection{Public networks shortage resilience}
\textffm{Meow} may run without Internet connection, either on an isolated wifi access point, either on a meshed network of wifi routers or even via serial IOT transport layers (LoRa,...) \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} \subsection{User directory service}
This service allows to restore a lost functionality of Internet historic chat services (like ICQ). You could simply set a "Free for chat" status that allowed other people to contact you, either randomly or based on a short description that you might provide. This service allows to restore 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 ?\\ Why providing that service while the internet is suffocating due to the abundance of social networks ?\\
Well, that option offered a few advantages : Well, that option offers a few advantages :
\begin{itemize} \begin{itemize}
\item you're still an anonymous user chatting with other anonymous users. \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 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. \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 old times, when people had to be able to start a win98 computer, connect it to internet, then download and install ICQ... It's a bit like in the old times, 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 know what I mean. If you lost some time in social networks, and experienced ICQ in the 2000's, you know what I mean.
\end{itemize} \end{itemize}
@ -104,45 +104,43 @@ Each \textffm{Meow} user has a unique identity. That identity is strictly privat
Let's call that one the User Key Pair (Ukp) Let's call that one the User Key Pair (Ukp)
\subsection{Contact identity} \subsection{Contact identity}
Each of your contacts will know you as a different identity, we'll call that one the Contact Key Pair (Ckp) 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 the two peerr : An initial key will be exchanged as part of the peer invitation process. 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 myth have seen your key As other people might have seen your key, this means that :
This means that :
\begin{itemize} \begin{itemize}
\item none of your contacts will be able to forward your id to another person without your consent \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 the user associated to it, will be discarded. \item any message to that Ckp, not signed by its associated user, will be discarded.
\end{itemize} \end{itemize}
\subsection{Conversation encryption} \subsection{Conversation encryption}
Each conversation with one of your contacts will be encrypted using an encryption keypair (Ekp) 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. The Ekp might be changed anytime by its owner and the new public key will be sent along the last message.
The Ekp is used to cypher your conversation.
\subsection{Conversation lookup} \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. 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. 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 it's owner and the new public key will be sent along the last 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. The Lkp and the Ekp are only changed once the change has beeen acknowledged by your contact.
\subsection{Server identity} \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. 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} \subsection{Device identity}
Each device is identified by a key (Dkp), that device key allows you to perform secured exchanges between your devices for synchronization/revocation purposes. 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 are based on a synchronization protocol. 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} \section{Contact management}
\subsection{Adding a contact} \subsection{Adding a contact}
Rendez-vous card, containing : Rendez-vous card, containing :
\begin{itemize} \begin{itemize}
\item Your public key for that contact \item Your public key for that contact;
\item An initial conversation public key for getting encrypted messages from 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 An initial conversation uuid that you'll use to lookup for incoming messages on the servers;
\item A list of your prefered message servers \item A list of your preferred message servers;
\item A signature to prevent transmission of tampered data \item A signature to prevent transmission of tampered data.
\end{itemize} \end{itemize}
\subsection{Sharing a contact} \subsection{Sharing a contact}
If a user wants to forward one of his contacts to you, that will be handled as a double request : If a user wants to forward one of his contacts to you, it will be handled as a double request:
\begin{enumerate} \begin{enumerate}
\item I'm receiving a contact name, without any key \item I'm receiving a contact name, without any key
\item \item
@ -164,7 +162,7 @@ TODO
\section{Transport protocols} \section{Transport protocols}
\subsection{URLs} \subsection{URLs}
Server urls do define the protocol used for communicating with the server. 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.\\ 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: Examples of a valid url:
\begin{verbatim} \begin{verbatim}
http://myserver.com http://myserver.com

View File

@ -12,7 +12,7 @@ func TestEndToEnd(t *testing.T) {
// Create my own identity // Create my own identity
// //
fmt.Println("Trying to load identity from file.") fmt.Println("Trying to load identity from file.")
me, err := LoadIdentity("test.id") me, err := LoadIdentity("id.enc")
if err != nil { if err != nil {
fmt.Println("Failed : creating New identity...") fmt.Println("Failed : creating New identity...")
me = CreateIdentity("myname") me = CreateIdentity("myname")
@ -36,6 +36,8 @@ func TestEndToEnd(t *testing.T) {
// Simulate peer invitation response : generate the friend's keypair // Simulate peer invitation response : generate the friend's keypair
fmt.Println("Simulating first friend answer...") fmt.Println("Simulating first friend answer...")
var receivedContact ContactCard var receivedContact ContactCard
// Friend simulated invitation
firstFriendContactKp := NewKeyPair() firstFriendContactKp := NewKeyPair()
firstFriendEncryptionKp := NewKeyPair() firstFriendEncryptionKp := NewKeyPair()
firstFriendLookupKp := NewKeyPair() firstFriendLookupKp := NewKeyPair()
@ -45,9 +47,12 @@ func TestEndToEnd(t *testing.T) {
receivedContact.LookupPublicKey = firstFriendLookupKp.Public receivedContact.LookupPublicKey = firstFriendLookupKp.Public
var friendsMessageServers ServerList var friendsMessageServers ServerList
friendsMessageServers.AddUrls([]string{"http://myfriend.org/meow/"}) friendsMessageServers.AddUrls([]string{"http://myfriend.org/meow/"})
// end Friend simulated invitation
for _, srv := range friendsMessageServers.Servers { for _, srv := range friendsMessageServers.Servers {
receivedContact.PullServers = append(receivedContact.PullServers, srv.ServerData) receivedContact.PullServers = append(receivedContact.PullServers, srv.ServerData)
} }
// End simulating contact invitation response // End simulating contact invitation response
// //
@ -55,7 +60,7 @@ func TestEndToEnd(t *testing.T) {
// Finalize the contact with the invitation response // Finalize the contact with the invitation response
// //
me.FinalizeInvitation(myFirstFriend, &receivedContact) me.FinalizeInvitation(myFirstFriend, &receivedContact)
err = me.Save("test.id") err = me.Save("id.enc")
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
} }
@ -63,10 +68,27 @@ func TestEndToEnd(t *testing.T) {
a, _ = json.Marshal(me) a, _ = json.Marshal(me)
ioutil.WriteFile("id.json", a, 0644) ioutil.WriteFile("id.json", a, 0644)
fmt.Println(string(a)) fmt.Println(string(a))
}
// go me.CheckMessages()
//myFirstFriend.SetComMethod() // create message to simulated friend
//msg := myFirstFriend.SendText() sentmessage := "Hello friend!"
lookupK, EncMsg, MsgSignature, Servers, err := myFirstFriend.CreateMessage([]byte(sentmessage))
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(lookupK)
fmt.Println(len(Servers))
// simulated friend decoding the message
//ReadMessage
// simulates if peer can decrypt my message
//Message := "toto"
//Signature := "test"
decMess, err2 := DecryptAndCheck(myFirstFriend.EncryptionKp.Private, myFirstFriend.Contact.EncryptionPublicKey, []byte(EncMsg), MsgSignature)
if err2 != nil {
fmt.Println(err2.Error())
}
fmt.Println(decMess)
//
}
} }

3
go.mod
View File

@ -5,9 +5,10 @@ go 1.16
require ( require (
github.com/ProtonMail/gopenpgp/v2 v2.2.4 github.com/ProtonMail/gopenpgp/v2 v2.2.4
github.com/go-resty/resty/v2 v2.6.0 github.com/go-resty/resty/v2 v2.6.0
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/makiuchi-d/gozxing v0.1.1 github.com/makiuchi-d/gozxing v0.1.1
github.com/rs/zerolog v1.25.0 github.com/rs/zerolog v1.25.0
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.4.0
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.28.1
) )

5
go.sum
View File

@ -13,6 +13,8 @@ github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKY
github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q= github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
@ -82,8 +84,11 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=

View File

@ -1,33 +0,0 @@
package meowlib
import (
"crypto/tls"
"github.com/go-resty/resty/v2"
"github.com/rs/zerolog/log"
)
type Https struct {
url string
}
func (https *Https) Send(msg []byte) ([]byte, error) {
client := resty.New().SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(msg).
Post(https.url + "/message/add/")
if err != nil {
log.Error().Msg(err.Error())
}
return resp.Body(), err
}
func (https *Https) Start(callback *func() []InternalMessage) {
}
func (https *Https) Stop() {
}

243
id.enc Normal file
View File

@ -0,0 +1,243 @@
-----BEGIN PGP MESSAGE-----
Comment: https://gopenpgp.org
Version: GopenPGP 2.2.4
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
=zCs9
-----END PGP MESSAGE-----

1
id.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -53,14 +53,6 @@ func (*Identity) FinalizeInvitation(peer *Peer, receivedContact *ContactCard) {
} }
func (*Identity) AddPeer(name string, peerPublicKey string) string {
var peer Peer
peer.Me = NewKeyPair()
peer.Contact.Name = name
peer.Contact.ContactPublicKey = peerPublicKey
return peer.Me.Public
}
func LoadIdentity(file string) (*Identity, error) { func LoadIdentity(file string) (*Identity, error) {
var id Identity var id Identity
indata, err := ioutil.ReadFile(file) indata, err := ioutil.ReadFile(file)
@ -68,10 +60,10 @@ func LoadIdentity(file string) (*Identity, error) {
return nil, err return nil, err
} }
pass, err := helper.DecryptMessageWithPassword([]byte(key), string(indata)) pass, err := helper.DecryptMessageWithPassword([]byte(key), string(indata))
if err == nil { if err != nil {
err = json.Unmarshal([]byte(pass), &id)
return nil, err return nil, err
} }
err = json.Unmarshal([]byte(pass), &id)
return &id, err return &id, err
} }

View File

@ -3,6 +3,8 @@ package meowlib
import ( import (
"log" "log"
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestCreate(t *testing.T) { func TestCreate(t *testing.T) {
@ -10,21 +12,10 @@ func TestCreate(t *testing.T) {
id.Save("test.id") id.Save("test.id")
} }
func TestSave(t *testing.T) {
id := Identity{Nickname: "myname",
PublicKey: "pubk",
PrivateKey: "privk",
Status: "online",
}
id.Save("test.id")
}
func TestLoad(t *testing.T) { func TestLoad(t *testing.T) {
id, err := LoadIdentity("test.id") id, err := LoadIdentity("test.id")
if err != nil { if err != nil {
log.Fatal((err.Error())) log.Println(err.Error())
}
if id.Nickname != "myname" {
log.Fatal("failed")
} }
assert.Equal(t, id.Nickname, "myname", "The two words should be the same.")
} }

BIN
invitation.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.26.0 // protoc-gen-go v1.28.1
// protoc v3.6.1 // protoc v3.21.5
// source: messages.proto // source: messages.proto
package meowlib package meowlib
@ -693,10 +693,12 @@ type UserMessage_ConversationStatus struct {
Sent uint64 `protobuf:"varint,3,opt,name=Sent,proto3" json:"Sent,omitempty"` Sent uint64 `protobuf:"varint,3,opt,name=Sent,proto3" json:"Sent,omitempty"`
Received uint64 `protobuf:"varint,4,opt,name=Received,proto3" json:"Received,omitempty"` Received uint64 `protobuf:"varint,4,opt,name=Received,proto3" json:"Received,omitempty"`
Processed uint64 `protobuf:"varint,5,opt,name=Processed,proto3" json:"Processed,omitempty"` Processed uint64 `protobuf:"varint,5,opt,name=Processed,proto3" json:"Processed,omitempty"`
NextCcid string `protobuf:"bytes,6,opt,name=NextCcid,proto3" json:"NextCcid,omitempty"` NextCkey string `protobuf:"bytes,6,opt,name=NextCkey,proto3" json:"NextCkey,omitempty"` // conversation key
NextCcidAck bool `protobuf:"varint,7,opt,name=NextCcidAck,proto3" json:"NextCcidAck,omitempty"` // false when proposing a new id, true for accepting it NextCkeyAck bool `protobuf:"varint,7,opt,name=NextCkeyAck,proto3" json:"NextCkeyAck,omitempty"` // false when proposing a new id, true for accepting it
NextCcpkey string `protobuf:"bytes,8,opt,name=NextCcpkey,proto3" json:"NextCcpkey,omitempty"` NextEkey string `protobuf:"bytes,8,opt,name=NextEkey,proto3" json:"NextEkey,omitempty"` // encrypted key
NextKeyCcpkeyAck bool `protobuf:"varint,9,opt,name=NextKeyCcpkeyAck,proto3" json:"NextKeyCcpkeyAck,omitempty"` // false when proposing a new key, true for accpeting it NextKeyEkeyAck bool `protobuf:"varint,9,opt,name=NextKeyEkeyAck,proto3" json:"NextKeyEkeyAck,omitempty"` // false when proposing a new key, true for accpeting it
NextLkey string `protobuf:"bytes,10,opt,name=NextLkey,proto3" json:"NextLkey,omitempty"` // lookup key
NextLkeyAck bool `protobuf:"varint,11,opt,name=NextLkeyAck,proto3" json:"NextLkeyAck,omitempty"` // false when proposing a new id, true for accepting it
} }
func (x *UserMessage_ConversationStatus) Reset() { func (x *UserMessage_ConversationStatus) Reset() {
@ -766,30 +768,44 @@ func (x *UserMessage_ConversationStatus) GetProcessed() uint64 {
return 0 return 0
} }
func (x *UserMessage_ConversationStatus) GetNextCcid() string { func (x *UserMessage_ConversationStatus) GetNextCkey() string {
if x != nil { if x != nil {
return x.NextCcid return x.NextCkey
} }
return "" return ""
} }
func (x *UserMessage_ConversationStatus) GetNextCcidAck() bool { func (x *UserMessage_ConversationStatus) GetNextCkeyAck() bool {
if x != nil { if x != nil {
return x.NextCcidAck return x.NextCkeyAck
} }
return false return false
} }
func (x *UserMessage_ConversationStatus) GetNextCcpkey() string { func (x *UserMessage_ConversationStatus) GetNextEkey() string {
if x != nil { if x != nil {
return x.NextCcpkey return x.NextEkey
} }
return "" return ""
} }
func (x *UserMessage_ConversationStatus) GetNextKeyCcpkeyAck() bool { func (x *UserMessage_ConversationStatus) GetNextKeyEkeyAck() bool {
if x != nil { if x != nil {
return x.NextKeyCcpkeyAck return x.NextKeyEkeyAck
}
return false
}
func (x *UserMessage_ConversationStatus) GetNextLkey() string {
if x != nil {
return x.NextLkey
}
return ""
}
func (x *UserMessage_ConversationStatus) GetNextLkeyAck() bool {
if x != nil {
return x.NextLkeyAck
} }
return false return false
} }
@ -939,7 +955,7 @@ var file_messages_proto_rawDesc = []byte{
0x4b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x0e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x53, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x0e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x53, 0x65,
0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d, 0x65,
0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0e, 0x54, 0x72, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0e, 0x54, 0x72,
0x75, 0x73, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, 0x94, 0x05, 0x0a, 0x75, 0x73, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x22, 0xca, 0x05, 0x0a,
0x0b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x20, 0x0a, 0x0b,
0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12,
@ -957,7 +973,7 @@ var file_messages_proto_rawDesc = []byte{
0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x61, 0x67, 0x65, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70,
0x1a, 0xb0, 0x02, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0xe6, 0x02, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
0x55, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x55, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61,
0x6c, 0x55, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x55, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65,
@ -968,22 +984,26 @@ var file_messages_proto_rawDesc = []byte{
0x04, 0x52, 0x08, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x04, 0x52, 0x08, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x50,
0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09,
0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x65, 0x78,
0x74, 0x43, 0x63, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4e, 0x65, 0x78, 0x74, 0x43, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4e, 0x65, 0x78,
0x74, 0x43, 0x63, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x4e, 0x65, 0x78, 0x74, 0x43, 0x63, 0x69, 0x74, 0x43, 0x6b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x4e, 0x65, 0x78, 0x74, 0x43, 0x6b, 0x65,
0x64, 0x41, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4e, 0x65, 0x78, 0x74, 0x79, 0x41, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4e, 0x65, 0x78, 0x74,
0x43, 0x63, 0x69, 0x64, 0x41, 0x63, 0x6b, 0x12, 0x1e, 0x0a, 0x0a, 0x4e, 0x65, 0x78, 0x74, 0x43, 0x43, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x65, 0x78, 0x74, 0x45,
0x63, 0x70, 0x6b, 0x65, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4e, 0x65, 0x78, 0x6b, 0x65, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4e, 0x65, 0x78, 0x74, 0x45,
0x74, 0x43, 0x63, 0x70, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x10, 0x4e, 0x65, 0x78, 0x74, 0x4b, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x4e, 0x65, 0x78, 0x74, 0x4b, 0x65, 0x79, 0x45, 0x6b,
0x65, 0x79, 0x43, 0x63, 0x70, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x65, 0x79, 0x41, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x4e, 0x65, 0x78,
0x08, 0x52, 0x10, 0x4e, 0x65, 0x78, 0x74, 0x4b, 0x65, 0x79, 0x43, 0x63, 0x70, 0x6b, 0x65, 0x79, 0x74, 0x4b, 0x65, 0x79, 0x45, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x4e,
0x41, 0x63, 0x6b, 0x1a, 0x4e, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x74, 0x4c, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4e,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x65, 0x78, 0x74, 0x4c, 0x6b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x4e, 0x65, 0x78, 0x74, 0x4c,
0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4e, 0x65,
0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x2e, 0x4d, 0x69, 0x6e, 0x69, 0x78, 0x74, 0x4c, 0x6b, 0x65, 0x79, 0x41, 0x63, 0x6b, 0x1a, 0x4e, 0x0a, 0x05, 0x47, 0x72, 0x6f,
0x6d, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x65, 0x72, 0x73, 0x42, 0x21, 0x5a, 0x1f, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x2e, 0x72, 0x65, 0x64, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72,
0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x79, 0x76, 0x65, 0x73, 0x2f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69,
0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x62, 0x2e, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74,
0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x42, 0x21, 0x5a, 0x1f, 0x66, 0x6f, 0x72,
0x67, 0x65, 0x2e, 0x72, 0x65, 0x64, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f,
0x79, 0x76, 0x65, 0x73, 0x2f, 0x6d, 0x65, 0x6f, 0x77, 0x6c, 0x69, 0x62, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -1,7 +0,0 @@
package meowlib
type Network interface {
Send(request []byte) ([]byte, error)
Start(callback *func() []InternalMessage)
Stop()
}

View File

@ -2,12 +2,14 @@ syntax = "proto3";
package meowlib; package meowlib;
option go_package = "forge.redroom.link/yves/meowlib"; option go_package = "forge.redroom.link/yves/meowlib";
// structure for sending a message intended for server use in protobuf format
message PackedServerMessage { message PackedServerMessage {
string From = 1; string From = 1;
bytes Payload = 2; bytes Payload = 2;
string Signature = 3; bytes Signature = 3;
} }
// structure for sending a message to be forwarded to another user in protobuf format
message PackedUserMessage { message PackedUserMessage {
string From = 1; string From = 1;
string Destination=2; string Destination=2;
@ -15,6 +17,7 @@ message PackedUserMessage {
bytes Signature=4; bytes Signature=4;
} }
// structure defining a message to be forwarded encrypted, then sent in a "packedmessage"
message ServerMessage { message ServerMessage {
string Type = 1; string Type = 1;
string ServerPubKey = 2 ; string ServerPubKey = 2 ;
@ -72,10 +75,12 @@ message UserMessage {
uint64 Sent = 3 ; uint64 Sent = 3 ;
uint64 Received = 4; uint64 Received = 4;
uint64 Processed = 5; uint64 Processed = 5;
string NextCcid = 6; string NextCkey = 6; // contact key
bool NextCcidAck = 7; // false when proposing a new id, true for accepting it bool NextCkeyAck = 7; // false when proposing a new id, true for accepting it
string NextCcpkey = 8; string NextEkey = 8; // encryption key
bool NextKeyCcpkeyAck = 9; // false when proposing a new key, true for accpeting it bool NextKeyEkeyAck = 9; // false when proposing a new key, true for accpeting it
string NextLkey = 10; // lookup key
bool NextLkeyAck = 11; // false when proposing a new id, true for accepting it
} }
ConversationStatus Status = 5; ConversationStatus Status = 5;

4
pb/protogen.bat Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
protoc -I=. --go_out=.. messages.proto
move ..\forge.redroom.link\yves\meowlib\messages.pb.go ..\
rmdir ..\forge.redroom.link /S /Q

48
peer.go
View File

@ -9,7 +9,6 @@ import (
"log" "log"
"math" "math"
"os" "os"
"strings"
"time" "time"
"github.com/makiuchi-d/gozxing" "github.com/makiuchi-d/gozxing"
@ -26,27 +25,28 @@ type ContactCard struct {
type Peer struct { type Peer struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
// Conversation []InternalMessage `json:"conversation,omitempty"`
// My own keys for that peer
Me KeyPair `json:"me,omitempty"` Me KeyPair `json:"me,omitempty"`
EncryptionKp KeyPair `json:"conversation_kp,omitempty"`
LookupKp KeyPair `json:"lookup_kp,omitempty"`
// Peer keys and infos
Contact ContactCard `json:"contact,omitempty"` Contact ContactCard `json:"contact,omitempty"`
// Internal management attributes
Visible bool `json:"visible,omitempty"` Visible bool `json:"visible,omitempty"`
VisiblePassword string `json:"visible_password,omitempty"` VisiblePassword string `json:"visible_password,omitempty"`
PasswordType string `json:"password_type,omitempty"` PasswordType string `json:"password_type,omitempty"`
Blocked bool `json:"blocked,omitempty"` Blocked bool `json:"blocked,omitempty"`
MessageNotification string `json:"message_notification,omitempty"` MessageNotification string `json:"message_notification,omitempty"`
OnionMode bool `json:"onion_mode,omitempty"` OnionMode bool `json:"onion_mode,omitempty"`
Conversation []InternalMessage `json:"convdersation,omitempty"`
LastMessage time.Time `json:"last_message,omitempty"` LastMessage time.Time `json:"last_message,omitempty"`
EncryptionKp KeyPair `json:"conversation_kp,omitempty"`
LookupKp KeyPair `json:"lookup_kp,omitempty"`
CommUrl string `json:"comm_url,omitempty"`
net Network
} }
type PeerList []Peer type PeerList []Peer
type Group struct { type Group struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Members []ContactCard `json:"members,omitempty"` Members []Peer `json:"members,omitempty"`
} }
func (pl *PeerList) GetFromPublicKey(publickey string) *Peer { func (pl *PeerList) GetFromPublicKey(publickey string) *Peer {
@ -67,20 +67,6 @@ func (pl *PeerList) GetFromName(name string) *Peer {
return nil return nil
} }
func (peer *Peer) SetCommInterface(url string) {
if strings.HasPrefix(url, "http://") {
var https *Https
https.url = url
peer.net = Network(https)
}
peer.net = nil
}
func (peer *Peer) SendText(text string) {
im := CreateText(*peer, text)
fmt.Println(im.MessageData.Destination)
}
func (contact *ContactCard) WritePng(filename string) { func (contact *ContactCard) WritePng(filename string) {
jsonContact, _ := json.Marshal(contact) jsonContact, _ := json.Marshal(contact)
//imgdata := base64.StdEncoding.EncodeToString(jsonContact) //imgdata := base64.StdEncoding.EncodeToString(jsonContact)
@ -152,3 +138,23 @@ func ReadQr(fielname string) ContactCard {
fmt.Println(result) fmt.Println(result)
return contact return contact
} }
func (p *Peer) CreateMessage(Message []byte) (lookupK string, EncryptedMsg []byte, Signature []byte, Servers []Server, err error) {
// prepares a message to send to a specific peer contact
EncryptedMsg, Signature, err = EncryptAndSign(p.Contact.EncryptionPublicKey, p.Me.Private, Message)
if err != nil {
fmt.Println(err.Error())
return "", nil, nil, nil, err
}
return p.LookupKp.Public, EncryptedMsg, Signature, p.Contact.PullServers, err
}
func (p *Peer) ReadMessage(Message []byte, Signature []byte) (DecryptedMsg []byte, err error) {
// reads a message from a specific peer contact
DecryptedMsg, err = DecryptAndCheck(p.Me.Private, p.Contact.ContactPublicKey, Message, Signature)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
return DecryptedMsg, err
}

2
test Normal file
View File

@ -0,0 +1,2 @@
toto mon textemoi

51
test.id Normal file
View File

@ -0,0 +1,51 @@
-----BEGIN PGP MESSAGE-----
Version: GopenPGP 2.2.4
Comment: https://gopenpgp.org
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
=dF9e
-----END PGP MESSAGE-----

View File

@ -1,60 +0,0 @@
package meowlib
import (
"encoding/json"
"strings"
"time"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
type InternalMessage struct {
With Peer `json:"with,omitempty"`
SentByMe bool `json:"sent_by_me,omitempty"`
MessageData UserMessage `json:"message_data,omitempty"`
ServerUuid string `json:"server_uuid,omitempty"`
Received time.Time `json:"received,omitempty"`
Processed time.Time `json:"processed,omitempty"`
TransferPath []Server `json:"transfer_path,omitempty"`
}
func CreateText(Destination Peer, text string) *InternalMessage {
var msg InternalMessage
msg.With = Destination
msg.SentByMe = true
msg.MessageData.From = Destination.Me.Public
msg.MessageData.Destination = Destination.Contact.ContactPublicKey
msg.MessageData.Status.Sent = uint64(time.Now().Unix())
msg.MessageData.Status.LocalUuid = strings.Replace(uuid.New().String(), "-", "", -1)
msg.MessageData.Type = "t"
msg.MessageData.Data = []byte(text)
return &msg
}
func (msg *UserMessage) Pack() *PackedUserMessage {
var pck PackedUserMessage
jsonMsg, _ := json.Marshal(msg)
armor, err := Encrypt(msg.Destination, jsonMsg)
if err != nil {
log.Error().Msg("Message encryption failed")
}
pck.Destination = msg.Destination
pck.Payload = []byte(armor)
return &pck
}
func (pck *PackedUserMessage) Unpack(privateKey string) *UserMessage {
var msg *UserMessage
decrypted, err := Decrypt(privateKey, pck.Payload)
if err != nil {
log.Error().Msg("Message decryption failed")
}
err = json.Unmarshal(decrypted, &msg)
if err != nil {
log.Error().Msg("Message encryption failed")
}
return msg
}

View File

@ -1,37 +0,0 @@
package meowlib
import (
"fmt"
"log"
"testing"
)
func TestCreateText(t *testing.T) {
kp := NewKeyPair()
fmt.Println(kp.Public)
fmt.Println(kp.Private)
}
func TestPack(t *testing.T) {
kp := NewKeyPair()
// fmt.Println(kp.Public)
// fmt.Println(kp.Private)
key := kp.GetCryptoKeyObject()
// fmt.Println(key.Armor())
pubkey, _ := key.GetArmoredPublicKey()
if kp.Public != pubkey {
log.Fatal("error in public key")
}
}
func TestUnPack(t *testing.T) {
kp := NewKeyPair()
// fmt.Println(kp.Public)
// fmt.Println(kp.Private)
key := kp.GetCryptoKeyObject()
// fmt.Println(key.Armor())
pubkey, _ := key.GetArmoredPublicKey()
if kp.Public != pubkey {
log.Fatal("error in public key")
}
}