Curve25519

This commit is contained in:
ycc 2022-03-01 10:37:11 +01:00
parent c07cdff3de
commit dee68043d1
10 changed files with 140 additions and 45 deletions

View File

@ -19,7 +19,7 @@ type KeysArray []KeyPair
func NewKeyPair() KeyPair { func NewKeyPair() KeyPair {
var kp KeyPair var kp KeyPair
keys, err := crypto.GenerateKey("name", "mail", "rsa", 4096) keys, err := crypto.GenerateKey("name", "mail", "x25519", 0)
if err != nil { if err != nil {
log.Error().Msg("Key generation failed") log.Error().Msg("Key generation failed")
} }

View File

@ -4,16 +4,25 @@
\title{ \title{
\textffm{Meow} messaging protocol} \textffm{Meow} messaging protocol}
\author{Author \author{Author
\texttt{author@address.net}} \texttt{meow@redroom.link}}
\date{\today} \date{\today}
\maketitle \maketitle
\begin{abstract} \begin{abstract}
The \textffm{Meow} protocol is a privacy driven instant messaging protocol.
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. 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. 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} \end{abstract}
@ -60,23 +69,21 @@ In return your contact will provide the exact same data, encrypted with your pub
\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. 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 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 thna you would be discarded.
\subsection{Group conversation} \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. 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} \subsection{Emergency broadcast}
The 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} \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, either 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 allowed other people to contact you, either randomly or based on a short description that you might provide.
@ -98,6 +105,8 @@ 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 as 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.
As other people myth 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
@ -176,7 +185,10 @@ TODO
\section{Server Features} \section{Server Features}
\subsection{Server catalog} \subsection{Server catalog}
Each server will cache a list of all the servers that it is aware of.
\subsection{Antispam} \subsection{Antispam}
\subsection{Self defense} \subsection{Self defense}
@ -188,6 +200,10 @@ TODO
\section{Very secure devices} \section{Very secure devices}
You don't trust your phone ? 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} \end{document}

View File

@ -31,7 +31,7 @@ func TestEndToEnd(t *testing.T) {
a, _ := json.Marshal(invitation) a, _ := json.Marshal(invitation)
fmt.Println(string(a)) fmt.Println(string(a))
// TODO : Convert invitation to QR Code // TODO : Convert invitation to QR Code
invitation.WritePng("invitation.png")
// //
// 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...")
@ -64,6 +64,8 @@ func TestEndToEnd(t *testing.T) {
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() //myFirstFriend.SetComMethod()
//msg := myFirstFriend.SendText() //msg := myFirstFriend.SendText()

2
go.mod
View File

@ -6,8 +6,8 @@ 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/google/uuid v1.3.0 github.com/google/uuid v1.3.0
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
github.com/tidwall/gjson v1.10.2
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.27.1
) )

11
go.sum
View File

@ -19,6 +19,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/makiuchi-d/gozxing v0.1.1 h1:xxqijhoedi+/lZlhINteGbywIrewVdVv2wl9r5O9S1I=
github.com/makiuchi-d/gozxing v0.1.1/go.mod h1:eRIHbOjX7QWxLIDJoQuMLhuXg9LAuw6znsUtRkNw9DU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -33,12 +35,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -72,8 +68,9 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=

View File

@ -2,48 +2,35 @@ package meowlib
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"github.com/tidwall/gjson"
"github.com/go-resty/resty/v2" "github.com/go-resty/resty/v2"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
var Address string type Https struct {
url string
func Configure(url string) {
Address = url
} }
func Send(msg []byte) (string, error) { func (https *Https) Send(msg []byte) ([]byte, error) {
client := resty.New().SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) client := resty.New().SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
resp, err := client.R(). resp, err := client.R().
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetBody(msg). SetBody(msg).
Post(Address + "/message/add/") Post(https.url + "/message/add/")
if err != nil { if err != nil {
log.Error().Msg(err.Error()) log.Error().Msg(err.Error())
} }
serverUuid := gjson.Get(resp.String(), "serveruuid").String() return resp.Body(), err
return serverUuid, err
} }
func Receive(key string) []byte { func (https *Https) Start(callback *func() []InternalMessage) {
client := resty.New().SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) for {
resp, err := client.R(). }
SetHeader("Content-Type", "application/json"). }
Get(Address + "/message/" + key)
fmt.Println(" StatusCode :", resp.StatusCode()) func (https *Https) Stop() {
fmt.Println(" Cookies :", resp.Cookies())
fmt.Println(" Error :", err)
msg := resp.Body()
return msg
}
func Start(callback *func() []InternalMessage) {
for { for {
} }

1
invitation.json Normal file

File diff suppressed because one or more lines are too long

BIN
invitation.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

View File

@ -1,9 +1,7 @@
package meowlib package meowlib
type Network interface { type Network interface {
Configure(url string) Send(request []byte) ([]byte, error)
Send(msg []byte) Start(callback *func() []InternalMessage)
Receive(request []byte) []byte
Start()
Stop() Stop()
} }

94
peer.go
View File

@ -1,8 +1,19 @@
package meowlib package meowlib
import ( import (
"encoding/json"
"fmt" "fmt"
"image"
"image/color"
"image/png"
"log"
"math"
"os"
"strings"
"time" "time"
"github.com/makiuchi-d/gozxing"
"github.com/makiuchi-d/gozxing/qrcode"
) )
type Contact struct { type Contact struct {
@ -27,6 +38,8 @@ type Peer struct {
LastMessage time.Time `json:"last_message,omitempty"` LastMessage time.Time `json:"last_message,omitempty"`
EncryptionKp KeyPair `json:"conversation_kp,omitempty"` EncryptionKp KeyPair `json:"conversation_kp,omitempty"`
LookupKp KeyPair `json:"lookup_kp,omitempty"` LookupKp KeyPair `json:"lookup_kp,omitempty"`
CommUrl string `json:"comm_url,omitempty"`
net Network
} }
type PeerList []Peer type PeerList []Peer
@ -54,7 +67,88 @@ 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) { func (peer *Peer) SendText(text string) {
im := CreateText(*peer, text) im := CreateText(*peer, text)
fmt.Println(im.MessageData.Destination) fmt.Println(im.MessageData.Destination)
} }
func (contact *Contact) WritePng(filename string) {
jsonContact, _ := json.Marshal(contact)
//imgdata := base64.StdEncoding.EncodeToString(jsonContact)
size := int(math.Sqrt(float64(len(jsonContact))/3)) + 1
println(size)
// Create a colored i mage of the given width and height.
img := image.NewNRGBA(image.Rect(0, 0, size, size))
for y := 0; y < size; y++ {
for x := 0; x < size*3; x = x + 3 {
p1 := uint8(jsonContact[x+y])
p2 := uint8(jsonContact[x+y+1])
p3 := uint8(jsonContact[x+y+2])
img.Set(x/3, y, color.NRGBA{
R: p1,
G: p2,
B: p3,
A: 255,
})
}
}
f, err := os.Create(filename)
if err != nil {
log.Fatal(err)
}
if err := png.Encode(f, img); err != nil {
f.Close()
log.Fatal(err)
}
if err := f.Close(); err != nil {
log.Fatal(err)
}
}
func (contact *Contact) WriteQr(filename string) {
jsonContact, _ := json.Marshal(contact)
qwriter := qrcode.NewQRCodeWriter()
code, err := qwriter.Encode(string(jsonContact), gozxing.BarcodeFormat_QR_CODE, 512, 512, nil)
if err != nil {
println(err.Error())
}
file, _ := os.Create("barcode.png")
defer file.Close()
// *BitMatrix implements the image.Image interface,
// so it is able to be passed to png.Encode directly.
_ = png.Encode(file, code)
}
func ReadQr(fielname string) Contact {
var contact Contact
// open and decode image file
file, _ := os.Open("qrcode.jpg")
img, _, _ := image.Decode(file)
// prepare BinaryBitmap
bmp, _ := gozxing.NewBinaryBitmapFromImage(img)
// decode image
qrReader := qrcode.NewQRCodeReader()
result, _ := qrReader.Decode(bmp, nil)
fmt.Println(result)
return contact
}