Add gob encoding of structs. Still very basic.
This commit is contained in:
parent
f17df4ce88
commit
f872453f16
56
client.go
56
client.go
@ -1,11 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/tardisx/netgiv/secure"
|
"github.com/tardisx/netgiv/secure"
|
||||||
)
|
)
|
||||||
@ -20,7 +20,7 @@ func (c *Client) Connect() error {
|
|||||||
|
|
||||||
conn, err := net.DialTCP("tcp", nil, serverAddress)
|
conn, err := net.DialTCP("tcp", nil, serverAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Problem connecting to server, is it running?\n")
|
return errors.New("problem connecting to server, is it running?\n")
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
@ -29,26 +29,46 @@ func (c *Client) Connect() error {
|
|||||||
sharedKey := secure.Handshake(conn)
|
sharedKey := secure.Handshake(conn)
|
||||||
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey}
|
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey}
|
||||||
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
// reader := bufio.NewReader(os.Stdin)
|
||||||
|
enc := gob.NewEncoder(&secureConnection)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
fmt.Print("> ")
|
|
||||||
// Read up to the newline character
|
|
||||||
msg, _ := reader.ReadBytes(0xA)
|
|
||||||
// Kill the newline char
|
|
||||||
msg = msg[:len(msg)-1]
|
|
||||||
|
|
||||||
_, err := secureConnection.Write(msg)
|
msg := secure.PacketStart{
|
||||||
|
OperationType: secure.OperationTypeSend,
|
||||||
response := make([]byte, 1024)
|
ClientName: "Justin Hawkins",
|
||||||
|
ProtocolVersion: "v1.0",
|
||||||
_, err = secureConnection.Read(response)
|
AuthToken: "abc123",
|
||||||
if err != nil {
|
|
||||||
fmt.Print("Connection to the server was closed.\n")
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%s\n", response)
|
// gob.Register(secure.PacketSendStart{})
|
||||||
|
err := enc.Encode(msg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := secure.PacketSendDataStart{
|
||||||
|
Filename: "foobar",
|
||||||
|
TotalSize: 3,
|
||||||
|
Data: []byte{0x20, 0x21, 0x22},
|
||||||
|
}
|
||||||
|
err = enc.Encode(data)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
log.Print("done that")
|
||||||
|
conn.Close()
|
||||||
|
|
||||||
|
break
|
||||||
|
// response := make([]byte, 1024)
|
||||||
|
|
||||||
|
// _, err = secureConnection.Read(response)
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Print("Connection to the server was closed.\n")
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fmt.Printf("%s\n", response)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
2
main.go
2
main.go
@ -3,9 +3,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
log.SetFlags(log.Lshortfile)
|
||||||
port := flag.Int("p", 9000, "Port to run server/client on.")
|
port := flag.Int("p", 9000, "Port to run server/client on.")
|
||||||
isServer := flag.Bool("s", false, "Set if running the server.")
|
isServer := flag.Bool("s", false, "Set if running the server.")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
116
secure/secure.go
116
secure/secure.go
@ -3,7 +3,10 @@ package secure
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"golang.org/x/crypto/nacl/box"
|
"golang.org/x/crypto/nacl/box"
|
||||||
@ -11,63 +14,126 @@ import (
|
|||||||
|
|
||||||
type SecureMessage struct {
|
type SecureMessage struct {
|
||||||
Msg []byte
|
Msg []byte
|
||||||
|
Size uint16
|
||||||
Nonce [24]byte
|
Nonce [24]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SecureMessage) toByteArray() []byte {
|
func (s *SecureMessage) toByteArray() []byte {
|
||||||
return append(s.Nonce[:], s.Msg[:]...)
|
length := []byte{0x0, 0x0}
|
||||||
|
binary.BigEndian.PutUint16(length, uint16(len(s.Msg)))
|
||||||
|
out := append(s.Nonce[:], length...)
|
||||||
|
out = append(out, s.Msg[:]...)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeterminePacketSize(data []byte) uint16 {
|
||||||
|
// first 24 bytes are the nonce, then the size
|
||||||
|
if len(data) < 26 {
|
||||||
|
log.Printf("packet is too small to be complete - %d bytes", len(data))
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
size := binary.BigEndian.Uint16(data[24:26])
|
||||||
|
size += 26 // add the length header and the nonce
|
||||||
|
log.Printf("size of packet inside the %d bytes is %d bytes", len(data), size)
|
||||||
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConstructSecureMessage(sm []byte) SecureMessage {
|
func ConstructSecureMessage(sm []byte) SecureMessage {
|
||||||
var nonce [24]byte
|
var nonce [24]byte
|
||||||
nonceArray := sm[:24]
|
nonceArray := sm[:24]
|
||||||
|
size := binary.BigEndian.Uint16(sm[24:26])
|
||||||
copy(nonce[:], nonceArray)
|
copy(nonce[:], nonceArray)
|
||||||
|
|
||||||
// Trim out all unnecessary bytes
|
// Trim out all unnecessary bytes
|
||||||
msg := bytes.Trim(sm[24:], "\x00")
|
// msg := bytes.Trim(sm[24:], "\x00")
|
||||||
|
|
||||||
return SecureMessage{Msg: msg, Nonce: nonce}
|
return SecureMessage{Msg: sm[26 : 26+size], Size: size, Nonce: nonce}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SecureConnection struct {
|
type SecureConnection struct {
|
||||||
Conn *net.TCPConn
|
Conn *net.TCPConn
|
||||||
SharedKey *[32]byte
|
SharedKey *[32]byte
|
||||||
|
Buffer *bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SecureConnection) Read(p []byte) (int, error) {
|
func (s *SecureConnection) Read(p []byte) (int, error) {
|
||||||
message := make([]byte, 2048)
|
message := make([]byte, 20408)
|
||||||
// Read the message from the buffer
|
// Read the message from the buffer
|
||||||
|
eof := false
|
||||||
|
|
||||||
|
log.Printf("READ: Start, buffer contains %d bytes", s.Buffer.Len())
|
||||||
|
|
||||||
n, err := s.Conn.Read(message)
|
n, err := s.Conn.Read(message)
|
||||||
|
|
||||||
secureMessage := ConstructSecureMessage(message)
|
if err != nil && err != io.EOF {
|
||||||
|
log.Printf("read: error in connection read %v", err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if err == io.EOF {
|
||||||
|
eof = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Printf("read: got %d bytes on the wire, error is %v", n, err)
|
||||||
|
// log.Printf("looks like %v", message[:n])
|
||||||
|
if eof {
|
||||||
|
log.Printf("eof is true - this is our final read!")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Buffer.Write(message[:n])
|
||||||
|
// log.Printf("read: appended them to the buffer which is now %d bytes", len(s.Buffer.Bytes()))
|
||||||
|
|
||||||
|
actualPacketEnd := DeterminePacketSize(s.Buffer.Bytes())
|
||||||
|
if actualPacketEnd == 0 {
|
||||||
|
log.Printf("packet too small?")
|
||||||
|
// panic("small")
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
secureMessage := ConstructSecureMessage(s.Buffer.Bytes()[:actualPacketEnd])
|
||||||
|
// log.Printf("Secure message from wire bytes: \n nonce: %v\n msg: %v\n size: %d\n", secureMessage.Nonce, secureMessage.Msg, secureMessage.Size)
|
||||||
decryptedMessage, ok := box.OpenAfterPrecomputation(nil, secureMessage.Msg, &secureMessage.Nonce, s.SharedKey)
|
decryptedMessage, ok := box.OpenAfterPrecomputation(nil, secureMessage.Msg, &secureMessage.Nonce, s.SharedKey)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, errors.New("Problem decrypting the message.\n")
|
return 0, errors.New("problem decrypting the message")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually copy it to the destination byte array
|
copy(p, decryptedMessage)
|
||||||
n = copy(p, decryptedMessage)
|
|
||||||
|
|
||||||
return n, err
|
// trim what we used off the buffer
|
||||||
|
newBuffer := s.Buffer.Bytes()[actualPacketEnd:]
|
||||||
|
s.Buffer = bytes.NewBuffer(newBuffer)
|
||||||
|
|
||||||
|
if eof && s.Buffer.Len() == 0 {
|
||||||
|
log.Printf("returning the final packet")
|
||||||
|
return len(decryptedMessage), io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("successfully read %d bytes", len(decryptedMessage))
|
||||||
|
return len(decryptedMessage), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SecureConnection) Write(p []byte) (int, error) {
|
func (s *SecureConnection) Write(p []byte) (int, error) {
|
||||||
|
// func (s *SecureConnection) Write(o encoding.BinaryMarshaler) (int, error) {
|
||||||
var nonce [24]byte
|
var nonce [24]byte
|
||||||
|
|
||||||
|
log.Printf("clear bytes: %v", p)
|
||||||
|
|
||||||
// Create a new nonce for each message sent
|
// Create a new nonce for each message sent
|
||||||
rand.Read(nonce[:])
|
rand.Read(nonce[:])
|
||||||
|
log.Printf("before encryption it is %d bytes", len(p))
|
||||||
encryptedMessage := box.SealAfterPrecomputation(nil, p, &nonce, s.SharedKey)
|
encryptedMessage := box.SealAfterPrecomputation(nil, p, &nonce, s.SharedKey)
|
||||||
sm := SecureMessage{Msg: encryptedMessage, Nonce: nonce}
|
sm := SecureMessage{Msg: encryptedMessage, Nonce: nonce}
|
||||||
|
|
||||||
// Write it to the connection
|
// Write it to the connection
|
||||||
return s.Conn.Write(sm.toByteArray())
|
wireBytes := sm.toByteArray()
|
||||||
|
log.Printf("putting %d bytes on the wire\n nonce: %v\n bytes: %v", len(wireBytes), nonce, wireBytes)
|
||||||
|
return s.Conn.Write(wireBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Handshake(conn *net.TCPConn) *[32]byte {
|
func Handshake(conn *net.TCPConn) *[32]byte {
|
||||||
var peerKey, sharedKey [32]byte
|
var peerKey, sharedKey [32]byte
|
||||||
|
|
||||||
|
log.Print("starting handshake")
|
||||||
publicKey, privateKey, _ := box.GenerateKey(rand.Reader)
|
publicKey, privateKey, _ := box.GenerateKey(rand.Reader)
|
||||||
|
|
||||||
conn.Write(publicKey[:])
|
conn.Write(publicKey[:])
|
||||||
@ -78,5 +144,33 @@ func Handshake(conn *net.TCPConn) *[32]byte {
|
|||||||
|
|
||||||
box.Precompute(&sharedKey, &peerKey, privateKey)
|
box.Precompute(&sharedKey, &peerKey, privateKey)
|
||||||
|
|
||||||
|
log.Printf("ending handshake, sk: %v", sharedKey)
|
||||||
|
|
||||||
return &sharedKey
|
return &sharedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OperationTypeEnum byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
OperationTypeSend OperationTypeEnum = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// PacketStart is sent from the client to the server at the beginning
|
||||||
|
// to authenticate and annonce the requested particular operation
|
||||||
|
type PacketStart struct {
|
||||||
|
OperationType OperationTypeEnum
|
||||||
|
ClientName string
|
||||||
|
ProtocolVersion string
|
||||||
|
AuthToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketSendDataStart struct {
|
||||||
|
Filename string
|
||||||
|
TotalSize uint32
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketSendDataNext struct {
|
||||||
|
Size uint16
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
44
server.go
44
server.go
@ -1,9 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/tardisx/netgiv/secure"
|
"github.com/tardisx/netgiv/secure"
|
||||||
)
|
)
|
||||||
@ -35,17 +40,46 @@ func (s *Server) Run() {
|
|||||||
|
|
||||||
func handleConnection(conn *net.TCPConn) {
|
func handleConnection(conn *net.TCPConn) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
|
conn.SetDeadline(time.Now().Add(time.Second))
|
||||||
|
|
||||||
sharedKey := secure.Handshake(conn)
|
sharedKey := secure.Handshake(conn)
|
||||||
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey}
|
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey, Buffer: &bytes.Buffer{}}
|
||||||
|
|
||||||
|
gob.Register(secure.PacketStart{})
|
||||||
|
gob.Register(secure.PacketSendDataStart{})
|
||||||
|
|
||||||
|
dec := gob.NewDecoder(&secureConnection)
|
||||||
|
|
||||||
|
// At this point we are in
|
||||||
for {
|
for {
|
||||||
msg := make([]byte, 1024)
|
|
||||||
_, err := secureConnection.Read(msg)
|
|
||||||
|
|
||||||
|
p1 := secure.PacketStart{}
|
||||||
|
|
||||||
|
log.Print("trying to decode something from wire")
|
||||||
|
err := dec.Decode(&p1)
|
||||||
|
if err == io.EOF {
|
||||||
|
log.Printf("connection has been closed")
|
||||||
|
return
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secureConnection.Write(msg)
|
log.Printf("Decoded packet:\n%#v", p1)
|
||||||
|
|
||||||
|
p2 := secure.PacketSendDataStart{}
|
||||||
|
|
||||||
|
err = dec.Decode(&p2)
|
||||||
|
if err == io.EOF {
|
||||||
|
log.Printf("connection has been closed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Decoded packet:\n%#v", p2)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user