Commit of work so far

This commit is contained in:
Samuel Hawksby-Robinson 2021-07-09 15:47:26 +01:00
commit 8a5717b73c
No known key found for this signature in database
GPG Key ID: AD6D836B165CCDA7
8 changed files with 556 additions and 0 deletions

80
app/keys.go Normal file
View File

@ -0,0 +1,80 @@
package app
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"io"
"math/big"
"os"
"time"
)
const (
OrganisationName = "Status IM"
)
func getCertTemplate() *x509.Certificate {
return &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
Organization: []string{OrganisationName},
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(time.Hour),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}
}
func generateCert(certWriter io.Writer, key *ecdsa.PrivateKey) error {
certTemplate := getCertTemplate()
certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, &key.PublicKey, key)
if err != nil {
return err
}
return pem.Encode(certWriter, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
}
func generateKey(keyWriter io.Writer, key *ecdsa.PrivateKey) error {
b, err := x509.MarshalECPrivateKey(key)
if err != nil {
return err
}
return pem.Encode(keyWriter, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
}
func GenerateKeyAndCert(certWriter io.Writer, keyWriter io.Writer) error {
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return err
}
err = generateCert(certWriter, privKey)
if err != nil {
return err
}
err = generateKey(keyWriter, privKey)
if err != nil {
return err
}
return nil
}
func DeleteKeyAndCert() error {
err := os.Remove(TLSKeyName)
if err != nil {
return err
}
return os.Remove(TLSCertName)
}

95
app/keys_test.go Normal file
View File

@ -0,0 +1,95 @@
package app
import (
"bytes"
"crypto/x509"
"encoding/pem"
"testing"
)
func TestGenerateKeyAndCert(t *testing.T) {
crtWriter := bytes.NewBuffer([]byte{})
keyWriter := bytes.NewBuffer([]byte{})
err := GenerateKeyAndCert(crtWriter, keyWriter)
if err != nil {
t.Error(err)
}
expected := []*struct {
Name string
Bytes []byte
Len int
BeginWith string
EndWith string
PemBlock *pem.Block
}{
{
"certificate",
crtWriter.Bytes(),
509,
"-----BEGIN CERTIFICATE-----",
"-----END CERTIFICATE-----",
nil,
},
{
"private key",
keyWriter.Bytes(),
227,
"-----BEGIN EC PRIVATE KEY-----",
"-----END EC PRIVATE KEY-----",
nil,
},
}
for _, e := range expected {
if len(e.Bytes) != e.Len {
t.Errorf("%s pem bytes should be %d in length, received %d",
e.Name,
e.Len,
len(e.Bytes),
)
}
bwl := len(e.BeginWith)
if string(e.Bytes[:bwl]) != e.BeginWith {
t.Errorf("%s pem should begin with '%s', recieved '%s'",
e.Name,
e.BeginWith,
string(e.Bytes[:bwl]),
)
}
ewl := len(e.EndWith)
if string(e.Bytes[len(e.Bytes)-ewl-1:len(e.Bytes)-1]) != e.EndWith{
t.Errorf("%s pem should end with '%s', recieved '%s'",
e.Name,
e.EndWith,
e.Bytes[len(e.Bytes)-ewl-1:len(e.Bytes)-1],
)
}
pb, r := pem.Decode(e.Bytes)
if len(r) != 0 {
t.Errorf("%s pem decode should be empty, remaining bytes %v", e.Name, r)
}
e.PemBlock = pb
}
_, err = x509.ParseCertificate(expected[0].PemBlock.Bytes)
if err != nil {
t.Error(err)
}
_, err = x509.ParseECPrivateKey(expected[1].PemBlock.Bytes)
if err != nil {
t.Error(err)
}
}
func TestDeleteKeyAndCert(t *testing.T) {
err := DeleteKeyAndCert()
if err != nil {
t.Error(err)
}
}

48
app/main.go Normal file
View File

@ -0,0 +1,48 @@
package app
import (
"bytes"
"crypto/rand"
"crypto/tls"
)
const (
KeysDir = "./keys/"
TLSCertName = KeysDir + "tls.crt"
TLSKeyName = KeysDir + "tls.key"
)
type App struct {
CertPemBytes []byte
KeyPemBytes []byte
TLSConfig tls.Config
}
func (a *App) Init() error {
return a.generateKeyAndCert()
}
func (a *App) generateKeyAndCert() error {
crtWriter := bytes.NewBuffer([]byte{})
keyWriter := bytes.NewBuffer([]byte{})
err := GenerateKeyAndCert(crtWriter, keyWriter)
if err != nil {
return err
}
a.KeyPemBytes = keyWriter.Bytes()
a.CertPemBytes = crtWriter.Bytes()
return nil
}
func (a *App) MakeTLS() error {
cert, err := tls.X509KeyPair(a.CertPemBytes, a.KeyPemBytes)
if err != nil {
return err
}
a.TLSConfig = tls.Config{Certificates: []tls.Certificate{cert}, Rand: rand.Reader}
return nil
}

112
app/peer_discovery_test.go Normal file
View File

@ -0,0 +1,112 @@
package app
import (
"fmt"
"log"
mrand "math/rand"
"sync"
"testing"
"time"
"github.com/schollz/peerdiscovery"
)
func TestPeerDiscovery(t *testing.T) {
//wg := new(sync.WaitGroup)
for x:=0;x<10;x++{
t.Logf("attempting discovery %d", x+1)
ds, err := peerdiscovery.Discover(peerdiscovery.Settings{Limit: 1})
if err != nil {
t.Error(err)
}
//t.Logf("Read peer list of %s", "peer 1")
for _, d := range ds {
fmt.Printf("discovered '%s'\n", d.Address)
}
}
/*wg.Add(1)
go peerDiscovery(t, "peer 1", wg)
wg.Add(1)
go peerDiscovery(t, "peer 2", wg)
*/
//wg.Wait()
}
func peerDiscovery(t *testing.T, name string, wg *sync.WaitGroup) {
t.Logf("Begin discovery %s", name)
ds, err := peerdiscovery.Discover(peerdiscovery.Settings{Limit: 1})
if err != nil {
t.Error(err)
}
t.Logf("Read peer list of %s", name)
for _, d := range ds {
fmt.Printf("discovered '%s'\n", d.Address)
}
wg.Done()
}
func TestAnother(t *testing.T) {
fmt.Println("Scanning for 10 seconds to find LAN peers")
pl := randStringBytesMaskImprSrc(10)
fmt.Printf("Payload sending : '%s'\n", pl)
// discover peers
discoveries, err := peerdiscovery.Discover(peerdiscovery.Settings{
Limit: -1,
Payload: []byte(pl),
Delay: 500 * time.Millisecond,
TimeLimit: 10 * time.Second,
Notify: func(d peerdiscovery.Discovered) {
log.Println(d)
},
})
// print out results
if err != nil {
log.Fatal(err)
} else {
if len(discoveries) > 0 {
fmt.Printf("Found %d other computers\n", len(discoveries))
for i, d := range discoveries {
fmt.Printf("%d) '%s' with payload '%s'\n", i, d.Address, d.Payload)
}
} else {
fmt.Println("Found no devices. You need to run this on another computer at the same time.")
}
}
}
// src is seeds the random generator for generating random strings
var src = mrand.NewSource(time.Now().UnixNano())
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
letterIdxBits = 6 // 6 bits to represent a letter index
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
)
// RandStringBytesMaskImprSrc prints a random string
func randStringBytesMaskImprSrc(n int) string {
b := make([]byte, n)
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdxMax
}
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
b[i] = letterBytes[idx]
i--
}
cache >>= letterIdxBits
remain--
}
return string(b)
}

82
app/zmq4_test.go Normal file
View File

@ -0,0 +1,82 @@
package app
import (
"context"
"log"
"testing"
"time"
"github.com/go-zeromq/zmq4"
)
func zmq4Req() {
logger := log.New(log.Writer(), "rrclient: ", log.LstdFlags)
req := zmq4.NewReq(context.Background())
defer req.Close()
err := req.Dial("tcp://localhost:5559")
if err != nil {
logger.Fatalf("could not dial: %v", err)
}
for i := 0; i < 10; i++ {
err := req.Send(zmq4.NewMsgString("Hello"))
if err != nil {
logger.Fatalf("could not send greeting: %v", err)
}
msg, err := req.Recv()
if err != nil {
logger.Fatalf("could not recv greeting: %v", err)
}
logger.Printf("received reply %d [%s]\n", i, msg.Frames[0])
}
}
func TestZMQ4Req(t *testing.T) {
zmq4Req()
}
func zmq4Rep() {
logger := log.New(log.Writer(), "rrworker: ", log.LstdFlags)
// Socket to talk to clients
rep := zmq4.NewRep(context.Background())
defer rep.Close()
err := rep.Listen("tcp://*:5559")
if err != nil {
logger.Fatalf("could not dial: %v", err)
}
for {
// Wait for next request from client
msg, err := rep.Recv()
if err != nil {
logger.Fatalf("could not recv request: %v", err)
}
logger.Printf("received request: [%s]\n", msg.Frames[0])
// Do some 'work'
time.Sleep(time.Second)
// Send reply back to client
err = rep.Send(zmq4.NewMsgString("World"))
if err != nil {
logger.Fatalf("could not send reply: %v", err)
}
}
}
func TestZMQ4Rep(t *testing.T) {
zmq4Rep()
}
func TestZMQ4ReqRep(t *testing.T){
go zmq4Rep()
go zmq4Req()
time.Sleep(15 * time.Second)
}

72
app/zyre_test.go Normal file
View File

@ -0,0 +1,72 @@
package app
import (
"context"
"github.com/davecgh/go-spew/spew"
"github.com/go-zeromq/zyre"
"sync"
"testing"
"time"
)
func TestZyre(t *testing.T) {
z1, cncl1 := makeNode()
defer cncl1()
z2, cncl2 := makeNode()
defer cncl2()
z1.SetVerbose()
z2.SetVerbose()
err := z1.Start()
if err != nil {
spew.Dump(err)
}
defer z1.Stop()
err = z2.Start()
if err != nil {
spew.Dump(err)
}
defer z2.Stop()
wg := new(sync.WaitGroup)
//wg.Add(1)
go watchEvents(t, wg, z1)
//wg.Add(1)
go watchEvents(t, wg, z2)
z1.Join("TALK")
z2.Join("TALK")
time.Sleep(time.Second)
z1.Shout("TALK", []byte("I am here"))
time.Sleep(time.Second)
z1.Shout("TALK", []byte("Hi world"))
//wg.Wait()
time.Sleep(time.Second)
spew.Dump(z1.Peers(), z2.Peers())
}
func makeNode() (*zyre.Zyre, context.CancelFunc) {
ctx, cncl := context.WithCancel(context.Background())
z := zyre.NewZyre(ctx)
return z, cncl
}
func watchEvents(t *testing.T, wg *sync.WaitGroup, z *zyre.Zyre) {
select {
case e := <- z.Events():
t.Log(spew.Sdump(e))
if string(e.Msg) == "Hi world" {
//wg.Done()
return
}
}
}

11
main.go Normal file
View File

@ -0,0 +1,11 @@
package main
import "github.com/status-im/tcp-pair-sync-prototype/app"
func main() {
a := new(app.App)
err := a.Init()
if err != nil {
panic(err)
}
}

56
main/main.go Normal file
View File

@ -0,0 +1,56 @@
// Copyright 2020 The go-zeromq Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bufio"
"context"
"flag"
"fmt"
"log"
"os"
"github.com/go-zeromq/zyre"
)
func chat(ctx context.Context, input <-chan string, name string) {
node := zyre.NewZyre(ctx)
defer node.Stop()
err := node.Start()
if err != nil {
log.Fatalln(err)
}
node.Join("CHAT")
for {
select {
case e := <-node.Events():
fmt.Printf("\r%s%s> ", string(e.Msg), name)
case msg := <-input:
node.Shout("CHAT", []byte(msg))
}
}
}
func main() {
input := make(chan string)
name := flag.String("name", "Zyre", "Your name in the chat session")
flag.Parse()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go chat(ctx, input, *name)
fmt.Printf("%s> ", *name)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input <- fmt.Sprintf("%s: %s\n", *name, scanner.Text())
fmt.Printf("%s> ", *name)
}
if err := scanner.Err(); err != nil {
log.Fatalln("reading standard input:", err)
}
}