This commit is contained in:
Justin Hawkins 2022-01-09 13:05:36 +10:30
commit f17df4ce88
7 changed files with 230 additions and 0 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"cSpell.words": [
"netgiv"
]
}

55
client.go Normal file
View File

@ -0,0 +1,55 @@
package main
import (
"bufio"
"errors"
"fmt"
"net"
"os"
"github.com/tardisx/netgiv/secure"
)
type Client struct {
port int
}
func (c *Client) Connect() error {
address := fmt.Sprintf("127.0.0.1:%d", c.port)
serverAddress, _ := net.ResolveTCPAddr("tcp", address)
conn, err := net.DialTCP("tcp", nil, serverAddress)
if err != nil {
return errors.New("Problem connecting to server, is it running?\n")
}
defer conn.Close()
fmt.Printf("Connection on %s\n", address)
sharedKey := secure.Handshake(conn)
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey}
reader := bufio.NewReader(os.Stdin)
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)
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
}

8
go.mod Normal file
View File

@ -0,0 +1,8 @@
module github.com/tardisx/netgiv
go 1.17
require (
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
)

4
go.sum Normal file
View File

@ -0,0 +1,4 @@
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

25
main.go Normal file
View File

@ -0,0 +1,25 @@
package main
import (
"flag"
"fmt"
)
func main() {
port := flag.Int("p", 9000, "Port to run server/client on.")
isServer := flag.Bool("s", false, "Set if running the server.")
flag.Parse()
if *isServer {
fmt.Printf("Server running on %d\n", *port)
s := Server{port: *port}
s.Run()
} else {
fmt.Printf("Client running on %d\n", *port)
c := Client{port: *port}
err := c.Connect()
if err != nil {
fmt.Print(err)
}
}
}

82
secure/secure.go Normal file
View File

@ -0,0 +1,82 @@
package secure
import (
"bytes"
"crypto/rand"
"errors"
"net"
"golang.org/x/crypto/nacl/box"
)
type SecureMessage struct {
Msg []byte
Nonce [24]byte
}
func (s *SecureMessage) toByteArray() []byte {
return append(s.Nonce[:], s.Msg[:]...)
}
func ConstructSecureMessage(sm []byte) SecureMessage {
var nonce [24]byte
nonceArray := sm[:24]
copy(nonce[:], nonceArray)
// Trim out all unnecessary bytes
msg := bytes.Trim(sm[24:], "\x00")
return SecureMessage{Msg: msg, Nonce: nonce}
}
type SecureConnection struct {
Conn *net.TCPConn
SharedKey *[32]byte
}
func (s *SecureConnection) Read(p []byte) (int, error) {
message := make([]byte, 2048)
// Read the message from the buffer
n, err := s.Conn.Read(message)
secureMessage := ConstructSecureMessage(message)
decryptedMessage, ok := box.OpenAfterPrecomputation(nil, secureMessage.Msg, &secureMessage.Nonce, s.SharedKey)
if !ok {
return 0, errors.New("Problem decrypting the message.\n")
}
// Actually copy it to the destination byte array
n = copy(p, decryptedMessage)
return n, err
}
func (s *SecureConnection) Write(p []byte) (int, error) {
var nonce [24]byte
// Create a new nonce for each message sent
rand.Read(nonce[:])
encryptedMessage := box.SealAfterPrecomputation(nil, p, &nonce, s.SharedKey)
sm := SecureMessage{Msg: encryptedMessage, Nonce: nonce}
// Write it to the connection
return s.Conn.Write(sm.toByteArray())
}
func Handshake(conn *net.TCPConn) *[32]byte {
var peerKey, sharedKey [32]byte
publicKey, privateKey, _ := box.GenerateKey(rand.Reader)
conn.Write(publicKey[:])
peerKeyArray := make([]byte, 32)
conn.Read(peerKeyArray)
copy(peerKey[:], peerKeyArray)
box.Precompute(&sharedKey, &peerKey, privateKey)
return &sharedKey
}

51
server.go Normal file
View File

@ -0,0 +1,51 @@
package main
import (
"fmt"
"net"
"os"
"github.com/tardisx/netgiv/secure"
)
type Server struct {
port int
}
func (s *Server) Run() {
address := fmt.Sprintf("127.0.0.1:%d", s.port)
networkAddress, _ := net.ResolveTCPAddr("tcp", address)
listener, err := net.ListenTCP("tcp", networkAddress)
if err != nil {
fmt.Print(err)
os.Exit(2)
}
for {
conn, err := listener.AcceptTCP()
if err != nil {
fmt.Print(err)
}
go handleConnection(conn)
}
}
func handleConnection(conn *net.TCPConn) {
defer conn.Close()
sharedKey := secure.Handshake(conn)
secureConnection := secure.SecureConnection{Conn: conn, SharedKey: sharedKey}
for {
msg := make([]byte, 1024)
_, err := secureConnection.Read(msg)
if err != nil {
break
}
secureConnection.Write(msg)
}
}