Skip to content

Commit

Permalink
use keypair to validate
Browse files Browse the repository at this point in the history
  • Loading branch information
schollz committed Jun 23, 2018
1 parent 60e3180 commit 30c9c33
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 31 deletions.
80 changes: 59 additions & 21 deletions connect.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
Expand All @@ -18,6 +19,7 @@ import (
"time"

"github.com/dustin/go-humanize"
"github.com/schollz/messagebox/keypair"
"github.com/schollz/peerdiscovery"
"github.com/schollz/progressbar"
tarinator "github.com/schollz/tarinator-go"
Expand All @@ -43,6 +45,8 @@ type Connection struct {
Wait bool
bar *progressbar.ProgressBar
rate int
keypair keypair.KeyPair
encryptedPassword string
}

type FileMetaData struct {
Expand Down Expand Up @@ -73,6 +77,7 @@ func NewConnection(config *AppConfig) (*Connection, error) {
c.Yes = config.Yes
c.rate = config.Rate
c.Local = config.Local
c.keypair, _ = keypair.New()

if c.Local {
c.Yes = true
Expand Down Expand Up @@ -213,6 +218,10 @@ func (c *Connection) Run() error {
if err := SplitFile(c.File.Name+".enc", c.NumberOfConnections); err != nil {
return err
}
// remove the file now since we still have pieces
if err := os.Remove(c.File.Name + ".enc"); err != nil {
return err
}

// get file hash
var err error
Expand All @@ -221,14 +230,10 @@ func (c *Connection) Run() error {
return err
}
// get file size
c.File.Size, err = FileSize(c.File.Name + ".enc")
c.File.Size, err = FileSize(c.File.Name)
if err != nil {
return err
}
// remove the file now since we still have pieces
if err := os.Remove(c.File.Name + ".enc"); err != nil {
return err
}

// remove compressed archive
if c.File.IsDir {
Expand All @@ -241,16 +246,19 @@ func (c *Connection) Run() error {
fmt.Fprintf(os.Stderr, "Code is: %s\n", c.Code)

// broadcast local connection from sender
log.Debug("settings payload to ", c.Code)
go func() {
go peerdiscovery.Discover(peerdiscovery.Settings{
Limit: 1,
TimeLimit: 600 * time.Second,
Delay: 50 * time.Millisecond,
Payload: []byte(c.Code),
})
runClientError <- c.runClient("localhost")
}()
if c.Server == "" {
log.Debug("settings payload to ", c.Code)
go func() {
go peerdiscovery.Discover(peerdiscovery.Settings{
Limit: 1,
TimeLimit: 600 * time.Second,
Delay: 50 * time.Millisecond,
Payload: []byte(c.Code),
})
runClientError <- c.runClient("localhost")
}()

}
}

log.Debug("checking code validity")
Expand Down Expand Up @@ -330,19 +338,19 @@ func (c *Connection) runClient(serverName string) error {
log.Error(err)
}
encryptedMetaData, salt, iv := Encrypt(metaData, c.Code)
sendMessage("s."+c.HashedCode+"."+hex.EncodeToString(encryptedMetaData)+"-"+salt+"-"+iv, connection)
sendMessage("s."+c.keypair.Public+"."+c.HashedCode+"."+hex.EncodeToString(encryptedMetaData)+"-"+salt+"-"+iv, connection)
} else {
log.Debugf("telling relay (%s): %s", c.Server, "r."+c.Code)
if c.Wait {
// tell server to wait for sender
sendMessage("r."+c.HashedCode+".0.0.0", connection)
sendMessage("r."+c.keypair.Public+"."+c.HashedCode+".0.0.0", connection)
} else {
// tell server to cancel if sender doesn't exist
sendMessage("c."+c.HashedCode+".0.0.0", connection)
sendMessage("c."+c.keypair.Public+"."+c.HashedCode+".0.0.0", connection)
}
}
if c.IsSender { // this is a sender
log.Debug("waiting for ok from relay")
log.Debugf("[%d] waiting for ok from relay", id)
message = receiveMessage(connection)
if message == "timeout" {
responses.Lock()
Expand All @@ -359,10 +367,33 @@ func (c *Connection) runClient(serverName string) error {
responses.gotConnectionInUse = true
responses.Unlock()
} else {
log.Debug("got ok from relay")
// message is IP address, lets check next message
log.Debugf("[%d] got ok from relay: %s", id, message)
publicKeyRecipient := receiveMessage(connection)
if id == 0 {
fmt.Fprintf(os.Stderr, "\nSending (->%s)..\n", message)
fmt.Fprintf(os.Stderr, "\nSending (->%s@%s)..\n", publicKeyRecipient, message)
// check if okay again
// TODO
encryptedPassword, err := c.keypair.Encrypt([]byte(RandStringBytesMaskImprSrc(20)), publicKeyRecipient)
if err != nil {
panic(err)
}
// encrypt files

c.encryptedPassword = base64.StdEncoding.EncodeToString(encryptedPassword)
}
log.Debugf("[%d] waiting for 0 thread to encrypt", id)
for {
if c.encryptedPassword != "" {
break
}
time.Sleep(10 * time.Millisecond)
}
log.Debugf("sending encrypted passphrase: %s", c.encryptedPassword)
sendMessage(c.encryptedPassword, connection)
// wait for relay go
receiveMessage(connection)

// wait for pipe to be made
time.Sleep(100 * time.Millisecond)
// Write data from file
Expand Down Expand Up @@ -399,6 +430,9 @@ func (c *Connection) runClient(serverName string) error {
} else if strings.Split(sendersAddress, ":")[0] == "127.0.0.1" {
sendersAddress = strings.Replace(sendersAddress, "127.0.0.1", c.Server, 1)
}
// now get public key
publicKeySender := receiveMessage(connection)

// have the main thread ask for the okay
if id == 0 {
encryptedBytes, err := hex.DecodeString(encryptedData)
Expand Down Expand Up @@ -436,6 +470,7 @@ func (c *Connection) runClient(serverName string) error {
fmt.Fprintf(os.Stderr, "Will not overwrite file!")
os.Exit(1)
}
fmt.Fprintf(os.Stderr, "incoming file from "+publicKeySender+"\n")
getOK := "y"
if !c.Yes {
getOK = getInput("ok? (y/n): ")
Expand Down Expand Up @@ -466,6 +501,9 @@ func (c *Connection) runClient(serverName string) error {
if !gotOK {
sendMessage("not ok", connection)
} else {
sendMessage("ok", connection)
c.encryptedPassword = receiveMessage(connection)
log.Debugf("[%d] got encrypted passphrase: %s", id, c.encryptedPassword)
sendMessage("ok", connection)
log.Debug("receive file")
if id == 0 {
Expand Down
94 changes: 84 additions & 10 deletions relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ type connectionMap struct {
sender map[string]net.Conn
metadata map[string]string
potentialReceivers map[string]struct{}
rpublicKey map[string]string
spublicKey map[string]string
passphrase map[string]string
receiverReady map[string]bool
sync.RWMutex
}

Expand Down Expand Up @@ -64,7 +68,11 @@ func (r *Relay) Run() {
r.connections.receiver = make(map[string]net.Conn)
r.connections.sender = make(map[string]net.Conn)
r.connections.metadata = make(map[string]string)
r.connections.spublicKey = make(map[string]string)
r.connections.rpublicKey = make(map[string]string)
r.connections.passphrase = make(map[string]string)
r.connections.potentialReceivers = make(map[string]struct{})
r.connections.receiverReady = make(map[string]bool)
r.connections.Unlock()
r.runServer()
}
Expand Down Expand Up @@ -124,12 +132,13 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) {

sendMessage("who?", connection)
m := strings.Split(receiveMessage(connection), ".")
if len(m) < 3 {
if len(m) < 4 {
logger.Debug("exiting, not enough information")
sendMessage("not enough information", connection)
return
}
connectionType, codePhrase, metaData := m[0], m[1], m[2]
connectionType, publicKey, codePhrase, metaData := m[0], m[1], m[2], m[3]
logger.Debugf("got connection from %s", publicKey)
key := codePhrase + "-" + strconv.Itoa(id)

switch connectionType {
Expand All @@ -142,9 +151,11 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) {
r.connections.Lock()
r.connections.metadata[key] = metaData
r.connections.sender[key] = connection
r.connections.spublicKey[key] = publicKey
r.connections.Unlock()
// wait for receiver
receiversAddress := ""
receiversPublicKey := ""
isTimeout := time.Duration(0)
for {
if CONNECTION_TIMEOUT <= isTimeout {
Expand All @@ -154,16 +165,38 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) {
r.connections.RLock()
if _, ok := r.connections.receiver[key]; ok {
receiversAddress = r.connections.receiver[key].RemoteAddr().String()
logger.Debug("got receiver")
r.connections.RUnlock()
break
}
if _, ok := r.connections.rpublicKey[key]; ok {
receiversPublicKey = r.connections.rpublicKey[key]
}
r.connections.RUnlock()
if receiversAddress != "" && receiversPublicKey != "" {
break
}
time.Sleep(100 * time.Millisecond)
isTimeout += 100 * time.Millisecond
}
logger.Debug("telling sender ok")
sendMessage(receiversAddress, connection)
sendMessage(receiversPublicKey, connection)
// TODO ASK FOR OKAY HERE TOO
logger.Debug("waiting for encrypted passphrase")
encryptedPassphrase := receiveMessage(connection)
r.connections.Lock()
r.connections.passphrase[key] = encryptedPassphrase
r.connections.Unlock()

// wait for receiver ready
for {
r.connections.RLock()
if _, ok := r.connections.receiverReady[key]; ok {
r.connections.RUnlock()
break
}
r.connections.RUnlock()
}
// go reciever ready tell sender to go
sendMessage("go", connection)
logger.Debug("preparing pipe")
r.connections.Lock()
con1 := r.connections.sender[key]
Expand Down Expand Up @@ -192,20 +225,28 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) {
// add as a potential receiver
r.connections.Lock()
r.connections.potentialReceivers[key] = struct{}{}
r.connections.rpublicKey[key] = publicKey
r.connections.receiver[key] = connection
r.connections.Unlock()
// wait for sender's metadata
sendersAddress := ""
sendersPublicKey := ""
for {
r.connections.RLock()
if _, ok := r.connections.metadata[key]; ok {
if _, ok2 := r.connections.sender[key]; ok2 {
sendersAddress = r.connections.sender[key].RemoteAddr().String()
logger.Debug("got sender meta data")
r.connections.RUnlock()
break
}
}
if _, ok := r.connections.spublicKey[key]; ok {
sendersPublicKey = r.connections.spublicKey[key]
logger.Debugf("got sender public key: %s", sendersPublicKey)
}
r.connections.RUnlock()
if sendersAddress != "" && sendersPublicKey != "" {
break
}
if connectionType == "c" {
sendMessage("0-0-0-0.0.0.0", connection)
// sender is not ready so delete connection
Expand All @@ -219,16 +260,49 @@ func (r *Relay) clientCommuncation(id int, connection net.Conn) {
// send meta data
r.connections.RLock()
sendMessage(r.connections.metadata[key]+"-"+sendersAddress, connection)
sendMessage(sendersPublicKey, connection)
r.connections.RUnlock()

// now get passphrase
sendersPassphrase := ""
for {
r.connections.RLock()
if _, ok := r.connections.passphrase[key]; ok {
sendersPassphrase = r.connections.passphrase[key]
logger.Debugf("got sender passphrase: %s", sendersPassphrase)
}
r.connections.RUnlock()
if sendersPassphrase != "" {
break
}
}

// check for receiver's consent
consent := receiveMessage(connection)
logger.Debugf("consent: %s", consent)
if consent == "ok" {
logger.Debug("got consent")
r.connections.Lock()
r.connections.receiver[key] = connection
r.connections.Unlock()
// wait for encrypted passphrase
encryptedPassphrase := ""
for {
r.connections.RLock()
if _, ok := r.connections.passphrase[key]; ok {
encryptedPassphrase = r.connections.passphrase[key]
logger.Debugf("got passphrase: %s", r.connections.passphrase[key])
}
r.connections.RUnlock()
if encryptedPassphrase != "" {
break
}
time.Sleep(10 * time.Millisecond)
}
sendMessage(encryptedPassphrase, connection)
}
receiveMessage(connection)
time.Sleep(10 * time.Millisecond)
r.connections.Lock()
r.connections.receiverReady[key] = true
r.connections.Unlock()
default:
logger.Debugf("Got unknown protocol: '%s'", connectionType)
}
Expand Down
31 changes: 31 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import (
"fmt"
"io"
"math"
math_rand "math/rand"
"net"
"os"
"strconv"
"time"

"github.com/pkg/errors"
)
Expand Down Expand Up @@ -173,3 +175,32 @@ func GetLocalIP() string {
}
return bestIP
}

// src is seeds the random generator for generating random strings
var src = math_rand.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)
}

0 comments on commit 30c9c33

Please sign in to comment.