mirror of https://github.com/schollz/croc.git
use keypair to validate
This commit is contained in:
parent
60e31803c9
commit
30c9c3317f
80
connect.go
80
connect.go
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -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"
|
||||
|
@ -43,6 +45,8 @@ type Connection struct {
|
|||
Wait bool
|
||||
bar *progressbar.ProgressBar
|
||||
rate int
|
||||
keypair keypair.KeyPair
|
||||
encryptedPassword string
|
||||
}
|
||||
|
||||
type FileMetaData struct {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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")
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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): ")
|
||||
|
@ -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 {
|
||||
|
|
94
relay.go
94
relay.go
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
|
31
utils.go
31
utils.go
|
@ -5,9 +5,11 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
math_rand "math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue