A standalone, dependency-free TLS 1.3 state machine for Go. Ideal for adding TLS support to any byte-oriented transport.
-
100% RFC8446 Compliant: Feel free to open an issue if you find non compliant behaviour
-
Extremely performant: Almost 2x faster than crypto/tls in some cases
-
Pure state machine: No built-in networking; you feed/send raw bytes.
-
Zero heap allocations in hot paths via buffer reuse.
-
Cipher Suites:
TLS_CHACHA20_POLY1305_SHA256TLS_AES_128_GCM_SHA256TLS_AES_256_GCM_SHA384
-
NamedGroups:
X25519X25519MLKEM768(hybrid post-quantum KEM)P-256(aka:secp256r1/prime256v1)P-384(aka:secp384r1/prime384v1)P-512(aka:secp512r1/prime512v1)
-
SignatureSchemes:
ECDSA_SECP256R1_SHA256ECDSA_SECP384R1_SHA384ECDSA_SECP521R1_SHA512RSA_PSS_RSAE_SHA256RSA_PSS_RSAE_SHA384RSA_PSS_RSAE_SHA512ED25519
go get github.com/41Baloo/TLStatefunc main() {
// 1. Load your cert + key
certificate, err := TLState.CreateCertificateFromFile("server.crt", "server.key")
if err != nil {
panic(err)
}
cfg := TLState.NewConfig(certificate)
// 2. Accept connections in plain TCP...
ln, _ := net.Listen("tcp", ":8443")
log.Println("TLState server listening via plain TCP on :8443")
for {
conn, _ := ln.Accept()
go handle(conn, cfg)
}
}
func handle(c net.Conn, cfg *TLState.Config) {
defer c.Close()
// 3. Get a fresh state
state, _ := TLState.Get()
defer TLState.Put(state)
state.SetConfig(cfg)
buf := byteBuffer.Get()
defer byteBuffer.Put(buf)
// 4. Loop: read → Feed() → send handshake/data → Read()/Write()
tmp := make([]byte, 64*1024)
for {
n, err := c.Read(tmp)
if err != nil {
return
}
buf.Write(tmp[:n])
// Process handshake or pass-through
resp, err := state.Feed(buf)
if resp == TLState.Responded { // First check for response status
c.Write(buf.B)
}
if err != nil { // The handle errors
if err != io.EOF {
log.Printf("Error Feeding: %s", err.Error())
}
c.Close()
return
}
buf.Reset()
if !state.IsHandshakeDone() {
continue
}
// Once handshake is done, decrypt incoming...
for {
resp, err := state.Read(buf)
if err != nil {
if buf.Len() != 0 {
// Respond with leftover responded data before bailing
c.Write(buf.B)
}
log.Printf("Error Reading: %s", err.Error())
return
}
if resp != TLState.Responded {
break
}
}
if buf.Len() > 0 {
// buf.B now contains plaintext application data
log.Printf("%s => %s", c.RemoteAddr(), buf)
// echo back encrypted
err := state.Write(buf)
if err != nil {
log.Printf("Error Writing: %s", err.Error())
return
}
c.Write(buf.B)
}
buf.Reset()
}
}| Method | Description |
|---|---|
TLState.Get() (*State) |
Acquire a new state (fresh key-pair). |
TLState.Put(state) |
Return to pool, resetting all internal buffers and secrets. |
state.SetConfig(cfg) |
Attach your Config (cert, key, cipher list). Required before any handshake. |
state.IsHandshakeDone() |
Returns true once the TLS 1.3 handshake completes. |
| Method | Signature | Action |
|---|---|---|
Feed(inOut *byteBuffer.ByteBuffer) |
(ResponseState, error) |
Consumes incoming record bytes; may write handshake replies. |
Read(out *byteBuffer.ByteBuffer) |
(ResponseState, error) |
Decrypts and appends one application-data record into out. |
Write(inOut *byteBuffer.ByteBuffer) |
error |
Encrypts plaintext in inOut → ciphertext in same buffer. |
- Buffers are from
github.com/valyala/bytebufferpooland reused intensively. - Check each call’s
ResponseStateto know if you must sendbuffer.Bback over the wire.
You are very welcome to contibute and to help us improve TLState. Simply open a PR. However, be aware thatwe make use of some pretty hacky optimizations:
-
Many functions write into pre-allocated buffers instead of returning values.
-
Non-standard Control Flow: For more performance we make use of some pretty hacky optimizations
-
Many functions write into pre-allocated buffers instead of returning values.
-
ResponseState return values indicate whether a buffer got filled:
None→ nothing written / should not be usedResponded→ output is ready in your buffer
-
Buffer parameters are (usually) named:
inbuffer will be used to read fromoutbuffer will be used to output the resultinOutbuffer will both be used to read and output
-
Disclaimer: TLState is still a work in progress. It is not ready for production use. Always validate security before deploying.