Skip to content

Instantly share code, notes, and snippets.

@xor-gate
Forked from cyantarek/client.go
Last active August 18, 2024 06:21
Show Gist options
  • Save xor-gate/512cbed932148667a71f54c511c57bb3 to your computer and use it in GitHub Desktop.
Save xor-gate/512cbed932148667a71f54c511c57bb3 to your computer and use it in GitHub Desktop.
Golang AES-CFB encrypted TCP stream
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
"net"
)
func main() {
key := []byte("example key 1234")
conn, err := net.Dial("tcp", "127.0.0.1:1337")
if err != nil {
panic(err)
}
defer func() {
fmt.Println("Bye")
conn.Close()
}()
block, cipherErr := aes.NewCipher(key)
if cipherErr != nil {
fmt.Errorf("Can't create cipher:", cipherErr)
return
}
iv := make([]byte, aes.BlockSize)
if _, randReadErr := io.ReadFull(rand.Reader, iv); randReadErr != nil {
fmt.Errorf("Can't build random iv", randReadErr)
return
}
_, prefixWriteErr := conn.Write([]byte("XGE"))
if prefixWriteErr != nil {
fmt.Errorf("Can't send HELLO:", prefixWriteErr)
return
}
_, ivWriteErr := conn.Write(iv)
if ivWriteErr != nil {
fmt.Errorf("Can't send IV:", ivWriteErr)
return
} else {
fmt.Println("IV Sent")
}
stream := cipher.NewCFBEncrypter(block, iv)
data := [][]byte{
[]byte("Test one"),
[]byte("Hello crypto"),
[]byte("Hello word"),
[]byte("Hello excel"),
[]byte("Hello powerpoint"),
}
for _, d := range data {
encrypted := make([]byte, len(d))
stream.XORKeyStream(encrypted, d)
_, writeErr := conn.Write(encrypted)
if writeErr != nil {
fmt.Errorf("Write failed:", writeErr)
return
}
//fmt.Println("Encrypted Data Written:", string(d), encrypted, writeLen)
}
}
module xor-gate.org/src/hackerman
go 1.22.5
require (
github.com/searKing/golang/go v1.2.118
golang.org/x/net v0.28.0
)
require (
golang.org/x/sys v0.23.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/time v0.5.0 // indirect
)
github.com/searKing/golang/go v1.2.118 h1:YbusiPCCToN3xj9dXotkI7HGt294cdQaOYU8Otp1dLY=
github.com/searKing/golang/go v1.2.118/go.mod h1:ibu7hWUbf4uqMFFQmlA1HQZMwFtYLr88K8QtXbYT6yk=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"io"
"net"
)
func main() {
ln, err := net.Listen("tcp", "127.0.0.1:9080")
if err != nil {
panic(err)
}
key := []byte("example key 1234")
fmt.Println("Started Listening")
if err != nil {
panic(err)
}
for {
conn, err := ln.Accept()
if err != nil {
fmt.Errorf(
"Error while handling request from",
conn.RemoteAddr(),
":",
err,
)
}
go func(conn net.Conn) {
defer func() {
fmt.Println(
conn.RemoteAddr(),
"Closed",
)
conn.Close()
}()
block, blockErr := aes.NewCipher(key)
if blockErr != nil {
fmt.Println("Error creating cipher:", blockErr)
return
}
iv := make([]byte, 16)
ivReadLen, ivReadErr := conn.Read(iv)
if ivReadErr != nil {
fmt.Println("Can't read IV:", ivReadErr)
return
}
iv = iv[:ivReadLen]
if len(iv) < aes.BlockSize {
fmt.Println("Invalid IV length:", len(iv))
return
}
fmt.Println("Received IV:", iv)
stream := cipher.NewCFBDecrypter(block, iv)
fmt.Println("Hello", conn.RemoteAddr())
buf := make([]byte, 4096)
for {
rLen, rErr := conn.Read(buf)
if rErr == nil {
stream.XORKeyStream(buf[:rLen], buf[:rLen])
fmt.Println("Data:", string(buf[:rLen]), rLen)
continue
}
if rErr == io.EOF {
stream.XORKeyStream(buf[:rLen], buf[:rLen])
fmt.Println("Data:", string(buf[:rLen]), rLen, "EOF -")
break
}
fmt.Errorf(
"Error while reading from",
conn.RemoteAddr(),
":",
rErr,
)
break
}
}(conn)
}
}
package main
import (
"context"
"log"
"net/http"
"fmt"
"net"
"sync"
"os"
"io"
"bytes"
"os/signal"
"crypto/aes"
"crypto/cipher"
"github.com/searKing/golang/go/net/mux"
)
const (
testHTTP1Resp = "http1"
)
var key []byte = []byte("example key 1234")
type testHTTP1Handler struct{}
func (h *testHTTP1Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, testHTTP1Resp)
}
func serveHTTP(errCh chan<- error, l net.Listener) {
var mu sync.Mutex
conns := make(map[net.Conn]struct{})
defer func() {
mu.Lock()
for c := range conns {
if err := c.Close(); err != nil {
//errCh <- err
fmt.Println("Close err:", err)
}
}
mu.Unlock()
}()
s := &http.Server{
Handler: &testHTTP1Handler{},
ConnState: func(c net.Conn, state http.ConnState) {
mu.Lock()
switch state {
case http.StateNew:
fmt.Println("new http conn")
conns[c] = struct{}{}
case http.StateClosed:
delete(conns, c)
}
mu.Unlock()
},
}
if err := s.Serve(l); err != mux.ErrListenerClosed {
fmt.Println("Serve err:", err)
//errCh <- err
}
}
func serveSecureTCP(l net.Listener) {
var err error
fmt.Println("Started Listening on secure channel")
if err != nil {
panic(err)
}
for {
conn, err := l.Accept()
if err != nil {
fmt.Errorf(
"Error while handling request from",
conn.RemoteAddr(),
":",
err,
)
}
go func(conn net.Conn) {
defer func() {
fmt.Println(
conn.RemoteAddr(),
"Closed",
)
conn.Close()
}()
block, blockErr := aes.NewCipher(key)
if blockErr != nil {
fmt.Println("Error creating cipher:", blockErr)
return
}
prefix := make([]byte, 3)
prefixReadLen, prefixReadErr := conn.Read(prefix)
if prefixReadErr != nil || prefixReadLen != cap(prefix) {
fmt.Println("Cant read prefix... secure channel disallowed")
return
}
if !bytes.Contains(prefix, []byte("XGE")) {
fmt.Println("Invalid HELO")
return
}
fmt.Println("HELO OK from", conn.RemoteAddr())
iv := make([]byte, 16)
ivReadLen, ivReadErr := io.ReadFull(conn, iv)
if ivReadErr != nil {
fmt.Println("Can't read IV:", ivReadErr)
return
}
iv = iv[:ivReadLen]
if len(iv) < aes.BlockSize {
fmt.Println("Invalid IV length:", len(iv))
return
}
fmt.Println("Received IV:", iv)
stream := cipher.NewCFBDecrypter(block, iv)
fmt.Println("Hello", conn.RemoteAddr())
buf := make([]byte, 4096)
for {
rLen, rErr := conn.Read(buf)
if rErr == nil {
stream.XORKeyStream(buf[:rLen], buf[:rLen])
fmt.Println("Data:", string(buf[:rLen]), rLen)
continue
}
if rErr == io.EOF {
stream.XORKeyStream(buf[:rLen], buf[:rLen])
fmt.Println("Data:", string(buf[:rLen]), rLen, "EOF -")
break
}
fmt.Errorf(
"Error while reading from",
conn.RemoteAddr(),
":",
rErr,
)
break
}
}(conn)
}
}
func main() {
srv := mux.NewServer()
defer srv.Close()
// Otherwise, we match it againts HTTP1 methods. If matched,
// it is sent through the "httpl" listener.
httpl := mux.HandleListener(mux.HTTP1Fast())
// If not matched by HTTP, we assume it is an RPC connection.
securel := mux.HandleListener(mux.Any())
// Then we used the muxed listeners.
// See safeServe in github.com/searKing/golang/go/net/mux/mux_helper_test.go
go serveHTTP(nil, httpl)
go serveSecureTCP(securel)
idleConnsClosed := make(chan struct{})
go func() {
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt)
<-sigint
// We received an interrupt signal, shut down.
if err := srv.Shutdown(context.Background()); err != nil {
// Error from closing listeners, or context timeout:
log.Printf("mux server Shutdown: %v", err)
}
close(idleConnsClosed)
}()
if err := srv.ListenAndServe("localhost:1337"); err != mux.ErrServerClosed {
// Error starting or closing listener:
log.Printf("mux server ListenAndServe: %v", err)
}
<-idleConnsClosed
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment