-
-
Save xor-gate/512cbed932148667a71f54c511c57bb3 to your computer and use it in GitHub Desktop.
Golang AES-CFB encrypted TCP stream
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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