This commit is contained in:
ycc 2022-09-06 09:30:45 +02:00
parent 86f222a7df
commit 37fadc5bb3
16 changed files with 944 additions and 619 deletions

View File

@ -1,42 +1,44 @@
package meowlib package client
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"forge.redroom.link/yves/meowlib"
"github.com/ProtonMail/gopenpgp/v2/helper" "github.com/ProtonMail/gopenpgp/v2/helper"
) )
const key = "3pw0c8#6ZG8{75b5;3?fe80$2" const key = "3pw0c8#6ZG8{75b5;3?fe80$2"
type Identity struct { type Identity struct {
Nickname string `json:"nickname,omitempty"` Nickname string `json:"nickname,omitempty"`
PublicKey string `json:"public_key,omitempty"` PublicKey string `json:"public_key,omitempty"`
PrivateKey string `json:"private_key,omitempty"` PrivateKey string `json:"private_key,omitempty"`
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
Peers PeerList `json:"peers,omitempty"` Peers PeerList `json:"peers,omitempty"`
KnownServers ServerList `json:"known_servers,omitempty"` KnownServers InternalServerList `json:"known_servers,omitempty"`
MessageServers ServerList `json:"message_servers,omitempty"` MessageServers InternalServerList `json:"message_servers,omitempty"`
} }
func CreateIdentity(nickname string) *Identity { func CreateIdentity(nickname string) *Identity {
var id Identity var id Identity
id.Nickname = nickname id.Nickname = nickname
kp := NewKeyPair() kp := meowlib.NewKeyPair()
id.PublicKey = kp.Public id.PublicKey = kp.Public
id.PrivateKey = kp.Private id.PrivateKey = kp.Private
return &id return &id
} }
func (id *Identity) InvitePeer(myName string, contactName string, messageServerIdxs []int) (*Peer, *ContactCard) { func (id *Identity) InvitePeer(myName string, contactName string, messageServerIdxs []int) (*Peer, *meowlib.ContactCard) {
var peer Peer var peer Peer
var myContactCard ContactCard var myContactCard meowlib.ContactCard
peer.Me = NewKeyPair() peer.Me = meowlib.NewKeyPair()
peer.EncryptionKp = NewKeyPair() peer.EncryptionKp = meowlib.NewKeyPair()
peer.LookupKp = NewKeyPair() peer.LookupKp = meowlib.NewKeyPair()
peer.Name = contactName peer.Name = contactName
for _, i := range messageServerIdxs { for _, i := range messageServerIdxs {
myContactCard.PullServers = append(myContactCard.PullServers, id.MessageServers.Servers[i].ServerData) srv := id.MessageServers.Servers[i].ServerData
myContactCard.PullServers = append(myContactCard.PullServers, &srv)
} }
myContactCard.Name = myName myContactCard.Name = myName
myContactCard.ContactPublicKey = peer.Me.Public myContactCard.ContactPublicKey = peer.Me.Public
@ -48,7 +50,7 @@ func (id *Identity) InvitePeer(myName string, contactName string, messageServerI
return &id.Peers[len(id.Peers)-1], &myContactCard return &id.Peers[len(id.Peers)-1], &myContactCard
} }
func (*Identity) FinalizeInvitation(peer *Peer, receivedContact *ContactCard) { func (*Identity) FinalizeInvitation(peer *Peer, receivedContact *meowlib.ContactCard) {
peer.Contact = *receivedContact peer.Contact = *receivedContact
} }

View File

@ -1,4 +1,4 @@
package meowlib package client
import ( import (
"log" "log"

83
client/peer.go Normal file
View File

@ -0,0 +1,83 @@
package client
import (
"fmt"
"time"
"forge.redroom.link/yves/meowlib"
)
/*
type ContactCard struct {
Name string `json:"name,omitempty"`
ContactPublicKey string `json:"contact_public_key,omitempty"`
EncryptionPublicKey string `json:"encryption_public_key,omitempty"`
LookupPublicKey string `json:"lookup_public_key,omitempty"`
PullServers []meowlib.Server `json:"pull_servers,omitempty"`
}
*/
type Peer struct {
Name string `json:"name,omitempty"`
// Conversation []InternalMessage `json:"conversation,omitempty"`
// My own keys for that peer
Me meowlib.KeyPair `json:"me,omitempty"`
EncryptionKp meowlib.KeyPair `json:"conversation_kp,omitempty"`
LookupKp meowlib.KeyPair `json:"lookup_kp,omitempty"`
// Peer keys and infos
Contact meowlib.ContactCard `json:"contact,omitempty"`
// Internal management attributes
Visible bool `json:"visible,omitempty"`
VisiblePassword string `json:"visible_password,omitempty"`
PasswordType string `json:"password_type,omitempty"`
Blocked bool `json:"blocked,omitempty"`
MessageNotification string `json:"message_notification,omitempty"`
OnionMode bool `json:"onion_mode,omitempty"`
LastMessage time.Time `json:"last_message,omitempty"`
}
type PeerList []Peer
type Group struct {
Name string `json:"name,omitempty"`
Members []Peer `json:"members,omitempty"`
}
func (pl *PeerList) GetFromPublicKey(publickey string) *Peer {
for _, peer := range *pl {
if peer.Contact.ContactPublicKey == publickey {
return &peer
}
}
return nil
}
func (pl *PeerList) GetFromName(name string) *Peer {
for _, peer := range *pl {
if peer.Contact.Name == name {
return &peer
}
}
return nil
}
func (p *Peer) AsymEncryptMessage(Message []byte) (lookupK string, EncryptedMsg []byte, Signature []byte, Servers []*meowlib.Server, err error) {
// prepares a message to send to a specific peer contact
EncryptedMsg, Signature, err = meowlib.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) AsymDecryptMessage(Message []byte, Signature []byte) (DecryptedMsg []byte, err error) {
// reads a message from a specific peer contact
DecryptedMsg, err = meowlib.DecryptAndCheck(p.Me.Private, p.Contact.ContactPublicKey, Message, Signature)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
return DecryptedMsg, err
}

View File

@ -1,4 +1,4 @@
package meowlib package client
import ( import (
"testing" "testing"

55
client/server.go Normal file
View File

@ -0,0 +1,55 @@
package client
import (
"fmt"
"time"
"forge.redroom.link/yves/meowlib"
)
type InternalServer struct {
ServerData meowlib.Server `json:"server_data,omitempty"`
Presence bool `json:"presence,omitempty"`
LastCheck time.Time `json:"last_check,omitempty"`
Uptime time.Duration `json:"uptime,omitempty"`
Login string `json:"login,omitempty"`
Password string `json:"password,omitempty"`
Me meowlib.KeyPair `json:"me,omitempty"`
}
type InternalServerList struct {
Name string
Servers []InternalServer
}
func InternalServerFromUrl(url string) *InternalServer {
var is InternalServer
is.ServerData.Url = url
return &is
}
func (sl *InternalServerList) AddUrls(urls []string) {
for _, url := range urls {
sl.Servers = append(sl.Servers, *InternalServerFromUrl(url))
}
}
func (ints *InternalServer) AsymEncryptMessage(Message []byte) (EncryptedMsg []byte, Signature []byte, err error) {
// prepares a message to send to a specific internal server
EncryptedMsg, Signature, err = meowlib.EncryptAndSign(ints.ServerData.PublicKey, ints.Me.Private, Message)
if err != nil {
fmt.Println(err.Error())
return nil, nil, err
}
return EncryptedMsg, Signature, err
}
func (ints *InternalServer) AsymDecryptMessage(Message []byte, Signature []byte) (DecryptedMsg []byte, err error) {
// reads a message from a specific internal server
DecryptedMsg, err = meowlib.DecryptAndCheck(ints.Me.Private, ints.ServerData.PublicKey, Message, Signature)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
return DecryptedMsg, err
}

99
contactcard.go Normal file
View File

@ -0,0 +1,99 @@
package meowlib
import (
"encoding/json"
"fmt"
"image"
"image/color"
"image/png"
"log"
"math"
"os"
"github.com/makiuchi-d/gozxing"
"github.com/makiuchi-d/gozxing/qrcode"
)
func ServerFromUrl(url string) *Server {
var s Server
s.Url = url
return &s
}
func (contact *ContactCard) AddUrls(urls []string) {
for _, url := range urls {
contact.PullServers = append(contact.PullServers, ServerFromUrl(url))
}
}
func (contact *ContactCard) 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 *ContactCard) 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) ContactCard {
var contact ContactCard
// 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
}

View File

@ -1,10 +1,13 @@
package meowlib package meowlib_test
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"testing" "testing"
"forge.redroom.link/yves/meowlib"
"forge.redroom.link/yves/meowlib/client"
) )
func TestEndToEnd(t *testing.T) { func TestEndToEnd(t *testing.T) {
@ -12,10 +15,10 @@ 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("id.enc") me, err := client.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 = client.CreateIdentity("myname")
// //
// define my preferences (servers) // define my preferences (servers)
@ -35,24 +38,19 @@ 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 meowlib.ContactCard
// Friend simulated invitation // Friend simulated invitation
firstFriendContactKp := NewKeyPair() firstFriendContactKp := meowlib.NewKeyPair()
firstFriendEncryptionKp := NewKeyPair() firstFriendEncryptionKp := meowlib.NewKeyPair()
firstFriendLookupKp := NewKeyPair() firstFriendLookupKp := meowlib.NewKeyPair()
receivedContact.Name = "I'm the friend" receivedContact.Name = "I'm the friend"
receivedContact.ContactPublicKey = firstFriendContactKp.Public receivedContact.ContactPublicKey = firstFriendContactKp.Public
receivedContact.EncryptionPublicKey = firstFriendEncryptionKp.Public receivedContact.EncryptionPublicKey = firstFriendEncryptionKp.Public
receivedContact.LookupPublicKey = firstFriendLookupKp.Public receivedContact.LookupPublicKey = firstFriendLookupKp.Public
var friendsMessageServers ServerList receivedContact.AddUrls([]string{"http://myfriend.org/meow/"})
friendsMessageServers.AddUrls([]string{"http://myfriend.org/meow/"})
// end Friend simulated invitation // end Friend simulated invitation
for _, srv := range friendsMessageServers.Servers {
receivedContact.PullServers = append(receivedContact.PullServers, srv.ServerData)
}
// End simulating contact invitation response // End simulating contact invitation response
// //
@ -83,7 +81,7 @@ func TestEndToEnd(t *testing.T) {
// simulates if peer can decrypt my message // simulates if peer can decrypt my message
//Message := "toto" //Message := "toto"
//Signature := "test" //Signature := "test"
decMess, err2 := DecryptAndCheck(myFirstFriend.EncryptionKp.Private, myFirstFriend.Contact.EncryptionPublicKey, []byte(EncMsg), MsgSignature) decMess, err2 := meowlib.DecryptAndCheck(myFirstFriend.EncryptionKp.Private, myFirstFriend.Contact.EncryptionPublicKey, []byte(EncMsg), MsgSignature)
if err2 != nil { if err2 != nil {
fmt.Println(err2.Error()) fmt.Println(err2.Error())
} }

3
go.mod
View File

@ -4,9 +4,6 @@ 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/golang/protobuf v1.5.2 // indirect
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

10
go.sum
View File

@ -9,16 +9,10 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4=
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/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 h1:xxqijhoedi+/lZlhINteGbywIrewVdVv2wl9r5O9S1I=
@ -56,7 +50,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -84,9 +77,6 @@ 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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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=

File diff suppressed because it is too large Load Diff

View File

@ -72,6 +72,15 @@ message Server {
int32 ConfidenceLevel = 5; int32 ConfidenceLevel = 5;
} }
message ContactCard {
string name=1;
string contactPublicKey =2;
string encryptionPublicKey= 3;
string lookupPublicKey =4;
repeated Server PullServers =5;
}
message MinimalContact { message MinimalContact {
string name=1; string name=1;
string publicKey=2; string publicKey=2;

160
peer.go
View File

@ -1,160 +0,0 @@
package meowlib
import (
"encoding/json"
"fmt"
"image"
"image/color"
"image/png"
"log"
"math"
"os"
"time"
"github.com/makiuchi-d/gozxing"
"github.com/makiuchi-d/gozxing/qrcode"
)
type ContactCard struct {
Name string `json:"name,omitempty"`
ContactPublicKey string `json:"contact_public_key,omitempty"`
EncryptionPublicKey string `json:"encryption_public_key,omitempty"`
LookupPublicKey string `json:"lookup_public_key,omitempty"`
PullServers []Server `json:"pull_servers,omitempty"`
}
type Peer struct {
Name string `json:"name,omitempty"`
// Conversation []InternalMessage `json:"conversation,omitempty"`
// My own keys for that peer
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"`
// Internal management attributes
Visible bool `json:"visible,omitempty"`
VisiblePassword string `json:"visible_password,omitempty"`
PasswordType string `json:"password_type,omitempty"`
Blocked bool `json:"blocked,omitempty"`
MessageNotification string `json:"message_notification,omitempty"`
OnionMode bool `json:"onion_mode,omitempty"`
LastMessage time.Time `json:"last_message,omitempty"`
}
type PeerList []Peer
type Group struct {
Name string `json:"name,omitempty"`
Members []Peer `json:"members,omitempty"`
}
func (pl *PeerList) GetFromPublicKey(publickey string) *Peer {
for _, peer := range *pl {
if peer.Contact.ContactPublicKey == publickey {
return &peer
}
}
return nil
}
func (pl *PeerList) GetFromName(name string) *Peer {
for _, peer := range *pl {
if peer.Contact.Name == name {
return &peer
}
}
return nil
}
func (contact *ContactCard) 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 *ContactCard) 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) ContactCard {
var contact ContactCard
// 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
}
func (p *Peer) AsymEncryptMessage(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) AsymDecryptMessage(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
}

View File

@ -1,19 +1,20 @@
package meowlib package meowlib_test
import ( import (
"io/ioutil" "io/ioutil"
"log" "log"
"testing" "testing"
"forge.redroom.link/yves/meowlib"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
func TestServerMessageSerialization(t *testing.T) { func TestServerMessageSerialization(t *testing.T) {
var msg PackedServerMessage var msg meowlib.PackedServerMessage
msg.From = "toto" msg.From = "toto"
msg.Payload = []byte("mon texte") msg.Payload = []byte("mon texte")
msg.Signature = "moi" msg.Signature = []byte("moi")
out, err := proto.Marshal(&msg) out, err := proto.Marshal(&msg)
if err != nil { if err != nil {
log.Fatalln("Failed to encode address book:", err) log.Fatalln("Failed to encode address book:", err)
@ -25,7 +26,7 @@ func TestServerMessageSerialization(t *testing.T) {
if err != nil { if err != nil {
log.Fatalln("Error reading file:", err) log.Fatalln("Error reading file:", err)
} }
rmsg := &PackedServerMessage{} rmsg := &meowlib.PackedServerMessage{}
if err := proto.Unmarshal(in, rmsg); err != nil { if err := proto.Unmarshal(in, rmsg); err != nil {
log.Fatalln("Failed to parse address book:", err) log.Fatalln("Failed to parse address book:", err)
} }

View File

@ -1,53 +0,0 @@
package meowlib
import (
"fmt"
"time"
)
type InternalServer struct {
ServerData Server `json:"server_data,omitempty"`
Presence bool `json:"presence,omitempty"`
LastCheck time.Time `json:"last_check,omitempty"`
Uptime time.Duration `json:"uptime,omitempty"`
Login string `json:"login,omitempty"`
Password string `json:"password,omitempty"`
Me KeyPair `json:"me,omitempty"`
}
type ServerList struct {
Name string
Servers []InternalServer
}
func ServerFromUrl(url string) *InternalServer {
var is InternalServer
is.ServerData.Url = url
return &is
}
func (sl *ServerList) AddUrls(urls []string) {
for _, url := range urls {
sl.Servers = append(sl.Servers, *ServerFromUrl(url))
}
}
func (ints *InternalServer) AsymEncryptMessage(Message []byte) (EncryptedMsg []byte, Signature []byte, err error) {
// prepares a message to send to a specific internal server
EncryptedMsg, Signature, err = EncryptAndSign(ints.ServerData.PublicKey, ints.Me.Private, Message)
if err != nil {
fmt.Println(err.Error())
return nil, nil, err
}
return EncryptedMsg, Signature, err
}
func (ints *InternalServer) AsymDecryptMessage(Message []byte, Signature []byte) (DecryptedMsg []byte, err error) {
// reads a message from a specific internal server
DecryptedMsg, err = DecryptAndCheck(ints.Me.Private, ints.ServerData.PublicKey, Message, Signature)
if err != nil {
fmt.Println(err.Error())
return nil, err
}
return DecryptedMsg, err
}

54
server/identity.go Normal file
View File

@ -0,0 +1,54 @@
package client
import (
"encoding/json"
"io/ioutil"
"forge.redroom.link/yves/meowlib"
"github.com/ProtonMail/gopenpgp/v2/helper"
)
const key = "3pw0c8#6ZG8{75b5;3?fe80$2"
type Identity struct {
ServerName string `json:"servername,omitempty"`
ServerDesc string `json:"servername,omitempty"`
PublicKey string `json:"public_key,omitempty"`
PrivateKey string `json:"private_key,omitempty"`
Status string `json:"status,omitempty"`
// KnownServers ServerList `json:"known_servers,omitempty"`
}
func CreateIdentity(servername string, serverdesc string) *Identity {
var id Identity
id.ServerName = servername
id.ServerDesc = serverdesc
kp := meowlib.NewKeyPair()
id.PublicKey = kp.Public
id.PrivateKey = kp.Private
return &id
}
func LoadIdentity(file string) (*Identity, error) {
var id Identity
indata, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}
pass, err := helper.DecryptMessageWithPassword([]byte(key), string(indata))
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(pass), &id)
return &id, err
}
func (id *Identity) Save(file string) error {
b, _ := json.Marshal(id)
armor, err := helper.EncryptMessageWithPassword([]byte(key), string(b))
if err != nil {
return err
}
err = ioutil.WriteFile(file, []byte(armor), 0644)
return err
}

View File

@ -1,54 +0,0 @@
package meowlib
import (
"encoding/json"
"github.com/rs/zerolog/log"
)
const MessagesType = 1
const PollRequestType = 1
const PollResponseType = 1
const MtrkType = 1
func (msg *ServerMessage) Pack() *PackedServerMessage {
var pck PackedServerMessage
jsonMsg, _ := json.Marshal(msg)
armor, err := Encrypt(msg.ServerPubKey, jsonMsg)
if err != nil {
log.Error().Msg("Message encryption failed")
}
pck.Payload = []byte(armor)
return &pck
}
func (pck *PackedServerMessage) Unpack(privateKey string) *ServerMessage {
var msg *ServerMessage
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
}
func CreateMtrkChainServerMessage([]Server, []PackedUserMessage) *PackedServerMessage {
var msg PackedServerMessage
return &msg
}
func (msg *ServerMessage) Parse() {
var pck PackedServerMessage
jsonMsg, _ := json.Marshal(msg)
armor, err := Encrypt(msg.ServerPubKey, jsonMsg)
if err != nil {
log.Error().Msg("Message encryption failed")
}
pck.Payload = []byte(armor)
}