QuarkDash Go - pure Golang implementation of hybrid post-quantum algorythm. It provides provides post-quantum security, high performance, and attack resistance.
**This is an official protocol port from QuarkDash Typescript Implementation v1.2.0 (clean Go, minimum of dependencies).
Have a questions? Contact me
Paper | About | Get Started | TypeScript Version
QuarkDash Crypto - It is a hybrid cryptographic protocol that provides post-quantum security, high performance, and attack resistance. This library can be used as shared solution for your Go applications / server. Written on pure Go (carefully ported from TS). Dependency-free.
Algorithm Scheme can be found here
πΉ Lightweight library with zero dependencies;
πΉ Powerful crypto algorithm written in Go;
πΉ Extremely fast (great for realtime and IoT applications);
πΉ Production ready with benchmarks;
- Asymmetric key exchange: Ring-LWE (N=256, Q=7681, ROOT=5685) / R-Ring-LWE (Q=12289, ROOT=8340);
- Symmetric encryption: ChaCha20 (RFC 7539, 64B block) or lightweight Gimli (48B block) with lazy keystream generation;
- Key Derivation Function (KDF): SHAKE256 + HKDF-style expand;
- Message Authentication Code (MAC): SHAKE256(keyβdata) 32B, constant-time verify, reusable buffer;
- Hash: SHA-256 / SHA-512 and SHAKE-256;
- Replay protection: timestamp (LE64) + sequence number (LE32) + sliding window;
- Passphrase KDF: PBKDF2-HMAC-SHA256 / Argon2id-lite;
- Transports: WebSocket / HTTP / gRPC wrappers.
- Key rotation: by bytes / messages / time.
quarkdash-go/
βββ go.mod # module github.com/DevsDaddy/quarkdash-go (Go 1.23)
βββ quarkdash.go # QuarkDash protocol core (handshake, Encrypt/Decrypt, rekey)
βββ api.go # public facade - reexport for TS API compatible
βββ cipher/ # symmetric ciphers with lazy keystream
β βββ cipher.go # CipherType, NewCipher
β βββ keystream.go # LazyKeystream (LRU 64 blocks, Seek/Tell/XorInto)
β βββ chacha.go # ChaCha20 (20 rounds, 64B block)
β βββ gimli.go # Gimli (24 rounds, 48B block)
βββ hash/ # Hashes
β βββ shake.go # SHAKE256 (Keccak-f[1600], 24 rounds, rate 136)
β βββ sha.go # SHA-256 / SHA-512 (stdlib, wrappers)
βββ core/ # Basic primitives
β βββ utils.go # Core helpers: ConcatBytes, RandomBytes, SecureZero, ConstantTimeEqual, LE helpers
β βββ kdf.go # QuarkDashKDF (SHAKE256, HKDF-like)
β βββ mac.go # QuarkDashMAC (SHAKE256, reusable buffer)
βββ ringlwe/ # Postquantum exchange (KEM)
β βββ ringlwe.go # BaseRingLWE, RingLWE, RRLWE, NTT, polynomes, security
βββ rekey/ # Key rotation
β βββ rekey.go # RekeyPolicy, Build/ParseRekeyPayload, DeriveRekeyMaterial
βββ passphrase/ # KDF from password
β βββ passphrase.go # PBKDF2, Argon2id-lite, DerivePassphrase
βββ transport/ # Transport wrappers
β βββ http.go # QDHTTP (EncryptBody, Middleware, EncryptRequest)
β βββ grpc.go # QDGRPC (EncryptMessage, ServerInterceptor, WrapClient)
β βββ websocket.go # QDWebSocket (Send/SendJSON, OnDecrypted)
βββ quarkdash_test.go # Main algorythm tests
βββ features_test.go # Main features tests
βββ bench_test.go # Benchmarks
βββ README.md
If you need a full description of algorythm - Welcome to our WIKI
go get github.com/DevsDaddy/quarkdash-goRequires Go 1.23+. Without cgo, without external dependencies (only stdlib).
import qd "github.com/DevsDaddy/quarkdash-go"
alice := qd.New(qd.WithCipher(qd.CipherChaCha20))
bob := qd.New(qd.WithCipher(qd.CipherChaCha20))
aPub := alice.GenerateKeyPair() // 1024B
bPub := bob.GenerateKeyPair()
ct, _ := alice.InitializeSession(bPub, true) // Alice β initiator
_, _ = bob.InitializeSession(aPub, false)
_ = bob.FinalizeSession(ct) // Bob β receiver
plain := qd.TextToBytes("Hello QuarkDash π!")
enc, _ := alice.Encrypt(plain) // [12B meta | ciphertext | 32B MAC]
dec, _ := bob.Decrypt(enc)
fmt.Println(qd.BytesToText(dec)) // Hello QuarkDash π!alice := qd.New(qd.WithCipher(qd.CipherGimli))
bob := qd.New(qd.WithCipher(qd.CipherGimli))
// same handshakekey, nonce := qd.RandomBytes(32), qd.RandomBytes(12)
chacha, _ := qd.NewQuarkDashChaCha(key, nonce)
ks := chacha.CreateKeystream() // ChaChaKeystream (64B block)
chunk := ks.GetBytes(1024, 512) // custom offset without recompute of all stream
enc := ks.Xor(plain, 1024) // XOR with offset
ks.Seek(0)
block := ks.GenerateBlock(1) // 64B block #1
// Gimli works same - but with 48B block
gimli, _ := qd.NewQuarkDashGimli(key, nonce)
gks := gimli.CreateKeystream()alice := qd.New(qd.WithCipher(qd.CipherChaCha20), qd.WithRekeyPolicy(qd.RekeyPolicy{AfterBytes: 64*1024*1024, AfterMessages: 10000}))
bob := qd.New(qd.WithCipher(qd.CipherChaCha20))
// ... handshake ...
token, _ := alice.Rekey() // encrypt payload with old session, when derive new keys
_ = bob.ApplyRekey(token) // decrypt using old session, when derive
if alice.NeedsRekey() { token, _ := alice.Rekey(); bob.ApplyRekey(token) }
cnt, bytes, msgs, _, _ := alice.GetRekeyStats()salt := qd.GenerateSalt(32)
k1 := qd.PBKDF2SyncBytes([]byte("password"), salt, 100000, 32) // RFC 6070 compatible
k2 := qd.Argon2idSyncBytes([]byte("password"), salt, 32, 3, 32)
key, salt := qd.DerivePassphrase("my secret", qd.PassphraseOptions{Algorithm: "argon2id"})
sess, mac := qd.DeriveKeyForQuarkDash("password", salt, qd.PassphraseOptions{Algorithm: "pbkdf2"})// HTTP
httpAlice := qd.NewQDHTTP(alice)
httpBob := qd.NewQDHTTP(bob)
body, hdr, _ := httpAlice.EncryptBodyWithHeaders(map[string]string{"hello":"world"})
var out map[string]string
_ = httpBob.DecryptToJSON(body, &out)
http.Handle("/", httpAlice.Middleware(handler))
// gRPC
grpcAlice := qd.NewQDGRPC(alice)
grpcBob := qd.NewQDGRPC(bob)
enc, _ := grpcAlice.EncryptMessage([]byte("payload"))
dec, _ := grpcBob.DecryptMessage(enc)
// WebSocket
wsAlice := qd.WrapWebSocket(alice, rawWS) // rawWS implements transport.WSLike
_ = wsAlice.Send(qd.TextToBytes("hello ws"))
wsAlice.OnDecrypted(func(d []byte){ fmt.Println(string(d)) })Launched at Intel i5-13420H, Go 1.25, Fedora linux, 16GB RAM:
# Basic benchmark with go bench:
go test -bench=. -benchmem
# Full featured benchmark with table:
go test -bench-report -v -run TestBenchmarkReport| Benchmark | Time/op (ms) | Ops/sec | Speed (if available) |
|---|---|---|---|
| Key Generation | 0.421 ms | 2375 | - |
| Encapsulate | 0.812 ms | 1231 | - |
| Encrypt 1KB | 0.011 ms | 94994 | - |
| Decrypt 1KB | 0.002 ms | 401375 | - |
| Encrypt 1MB | 10.275 ms | 97 | 97.32 MB/s |
| Decrypt 1MB | 2.295 ms | 436 | 435.69 MB/s |
| ChaCha20 raw 1MB | 6.805 ms | 147 | 146.96 MB/s |
| Gimli raw 1MB | 8.009 ms | 125 | 124.85 MB/s |
| Category | Symbols |
|---|---|
| Core | New(opts...) *QuarkDash, GenerateKeyPair() []byte, InitializeSession(peer []byte, initiator bool) ([]byte,error), FinalizeSession(ct []byte) error, Encrypt([]byte)([]byte,error), Decrypt([]byte)([]byte,error), Dispose() |
| KDF/MAC | QuarkDashKDF, QuarkDashMAC, Shake256Hash, SHA256Hash |
| Cipher | CipherType, NewQuarkDashChaCha, NewQuarkDashGimli, ChaChaKeystream, GimliKeystream |
| Utils | TextToBytes, BytesToText, RandomBytes, ConcatBytes, BytesToHex |
| Passphrase | GenerateSalt, PBKDF2SyncBytes, Argon2idSyncBytes, DerivePassphrase, DeriveKeyForQuarkDash |
| Rekey (Key rotation) | RekeyPolicy, DefaultRekeyPolicy, NeedsRekey(), Rekey(), ApplyRekey() |
| Ring LWE | NewRRLWE(), NewRingLWE(), NTTProtectionOptions |
| Transport | NewQDHTTP, NewQDGRPC, WrapWebSocket, WSLike |
go test ./... -cover # 66%
go test -run TestLarge -count=1
go test -bench=. -benchtime=2x # benchmarks
go vet ./... # stats
go test -race ./... # raceBelow I've outlined a brief step-by-step flowchart of how the algorithm works. If you need more detailed information, please visit the Wiki.
Step-by-Step Algorithm:
- Key Pair Generation (using RingβLWE);
- Session Setup (using SHAKE-256 emulated KEM);
- Session Key Flow (KDF);
- Message Encryption (AEAD);
- Decryption;
Have a questions? Contact me
QuarkDash Crypto library is distributed under the MIT license. You can use it however you like. I would appreciate any feedback and suggestions for improvement. Full license text can be found here
