Curve25519
This commit is contained in:
parent
c07cdff3de
commit
dee68043d1
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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,16 +69,15 @@ 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}
|
||||||
@ -77,7 +85,6 @@ The
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\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.
|
||||||
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 ?\\
|
||||||
@ -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}
|
@ -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
2
go.mod
@ -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
11
go.sum
@ -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=
|
||||||
|
37
https.go
37
https.go
@ -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
1
invitation.json
Normal file
File diff suppressed because one or more lines are too long
BIN
invitation.png
Normal file
BIN
invitation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 530 B |
@ -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
94
peer.go
@ -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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user