ZNC network module for AndroidIRCX/mIRC-compatible IRC end-to-end encryption.
znce2e lets users keep the same encrypted IRC protocol used by the mIRC e2e.dll project while connecting through ZNC. It can encrypt private messages, exchange DM keys, share channel keys, decrypt incoming encrypted payloads, and auto-encrypt normal outgoing messages before they leave the bouncer.
Reference protocol implementation:
https://github.com/AndroidIRCx/e2e.dll
This repository is intentionally separate from e2e.dll: the mIRC project remains the protocol reference, while this project builds the ZNC module.
- ZNC network module named
znce2e - Compatible IRC wire format with AndroidIRCX/mIRC
e2e.dll - DM key exchange with
!enc-offer,!enc-accept, and!enc-req - Encrypted private messages with
!enc-msg - Channel key generation, sharing, requesting, removing, and encrypted sending
- Encrypted channel messages with
!chanenc-msg - Optional auto-encrypt for outgoing DM/channel messages typed normally by the attached IRC client
- Fail-secure behavior: if encryption was requested but the key is missing, plaintext is blocked
- Linux/WSL build with ZNC's module toolchain
- Windows ZNC build path documented for ABI-compatible MSYS2/MinGW or target
znc-buildmod - Portable libsodium crypto core with standalone tests
- GitHub Actions build for Linux core + ZNC module
- Identity/signature: Ed25519
- Key exchange: X25519 Diffie-Hellman
- Shared key derivation: X25519 DH output hashed to 32 bytes with
crypto_generichash - Message encryption: XChaCha20-Poly1305 IETF AEAD
- Encoding: URL-safe base64 without padding
- Channel encryption: shared random 32-byte symmetric channel key
Implemented and smoke-tested in WSL/Linux:
include/e2e_core.h/src/e2e_core.cportable crypto coretests/core_test.ccore round-trip/self-test coveragemodules/znc/znce2e.cppZNC network modulescripts/build-znc-linux.shLinux build helperscripts/build-znc-windows-msys2.shWindows/MSYS2 build helperscripts/smoke-wsl-test-znc.shlive ZNC command smoke testtests/znc/run-linux-smoke.shfull disposable integration harness
Verified output includes:
RESULT: PASS
znce2e module 0.1.0, znce2e-core/0.1.0, libsodium 1.0.18
Auto-encrypted channel message to #znce2etest.
Auto-encrypt blocked plaintext channel message to #znce2etest: missing channel key.
INTEGRATION RESULT: PASS
Ubuntu/WSL:
sudo apt-get update
sudo apt-get install -y build-essential pkg-config znc znc-dev libsodium-dev python3 opensslbash scripts/run-core-tests-linux.sh
bash scripts/build-znc-linux.shThe module is written to:
build/znc/znce2e.so
bash tests/znc/run-linux-smoke.shThis creates a disposable ZNC datadir, starts a temporary ZNC instance, connects as a test IRC client, and verifies the module through *znce2e commands.
Important: the harness recreates ~/.znc-znce2e-test by default. Do not point ZNC_TEST_DATADIR at a production ZNC datadir.
Unload first if the module is already loaded:
/msg *status unloadmod znce2e
Copy and load:
mkdir -p ~/.znc/modules
cp build/znc/znce2e.so ~/.znc/modules//msg *status loadmod znce2e
/msg *znce2e selftest
Never overwrite a loaded ZNC module binary. Unload it first or ZNC may crash.
Windows ZNC modules are C++ ABI-sensitive. The module must be built with the same compiler/runtime/toolchain as the target ZNC process.
Preferred order:
- Use the
znc-buildmodshipped with or built for the target Windows ZNC. - If ZNC is from MSYS2/MinGW, build inside that same MSYS2 environment.
- Use Visual Studio only if the target ZNC itself was built with a compatible MSVC toolchain and matching headers/libs are available.
MSYS2 helper:
bash scripts/build-znc-windows-msys2.shThis script intentionally refuses to run from cmd.exe, PowerShell, or Git Bash because those shells do not prove ABI compatibility with Windows ZNC.
Load the module as a network module:
/msg *status loadmod znce2e
/msg *znce2e help
/msg *znce2e selftest
help Show module commands
version Show module/core/libsodium versions
selftest Run crypto self-test
status Show non-secret module state
showraw on|off Show or hide raw !enc-* / !chanenc-* protocol lines
genkeys Generate self identity if missing
sharekey <nick> Send !enc-offer to nick
requestkey <nick> Send !enc-req to nick
accept <nick> Accept pending !enc-offer and send !enc-accept
reject <nick> Reject pending offer and send !enc-reject
encmsg <nick> <message> Send encrypted private message
chan generate <#chan> Generate/store channel key
chan share <#chan> <nick> Send channel key to nick via !chanenc-key
chan request <#chan> <nick> Ask nick to share a channel key
chan remove <#chan> Delete stored channel key and disable auto channel encryption
chan send <#chan> <message> Send encrypted channel message
auto dm on|off <nick> Auto-encrypt normal outgoing DMs to nick
auto chan on|off <#chan> Auto-encrypt normal outgoing channel messages
- Share or request a DM key:
/msg *znce2e sharekey <nick>
/msg *znce2e requestkey <nick>
- When an offer arrives, accept or reject it:
/msg *znce2e accept <nick>
/msg *znce2e reject <nick>
- Send an encrypted DM:
/msg *znce2e encmsg <nick> This private message is encrypted
- Optional auto-encrypt for normal typed DMs:
/msg *znce2e auto dm on <nick>
/msg <nick> This will be encrypted before leaving ZNC
If the DM key is missing, auto dm blocks the plaintext and reports the error instead of sending it.
- Generate a channel key:
/msg *znce2e chan generate #secret
- Share or request the channel key:
/msg *znce2e chan share #secret <nick>
/msg *znce2e chan request #secret <nick>
- Send an encrypted channel message:
/msg *znce2e chan send #secret This channel message is encrypted
- Optional auto-encrypt for normal typed channel messages:
/msg *znce2e auto chan on #secret
/msg #secret This will be encrypted before leaving ZNC
If the channel key is missing, auto chan blocks the plaintext and reports the error instead of sending it.
The module uses the same IRC message formats as the AndroidIRCX/mIRC e2e.dll protocol.
!enc-req
!enc-offer {"v":1,"idPub":"...","encPub":"...","sig":"..."}
!enc-accept {"v":1,"idPub":"...","encPub":"...","sig":"..."}
sig is an Ed25519 signature over encPub.
!enc-msg {"v":1,"from":"<encPub>","nonce":"...","cipher":"..."}
!chanenc-key {"v":1,"channel":"#chan","network":"NetworkName","key":"...","createdAt":123}
!chanenc-msg {"v":1,"nonce":"...","cipher":"..."}
- Authenticated encryption with XChaCha20-Poly1305
- Ed25519 signature verification for key offers
- Random nonces per message
- libsodium primitives instead of custom cryptography
- Fail-secure auto-encrypt behavior when keys are missing
ZNC is inside the trust boundary. The module decrypts messages inside the ZNC process and stores keys in ZNC module state. A ZNC admin, shell admin, malicious module, debugger, process dump, or compromised host can potentially access plaintext and keys.
Use TLS between your IRC client and ZNC. If client-to-ZNC traffic is not encrypted, plaintext can cross that link even though the server-side IRC payload is encrypted.
- No perfect forward secrecy / no ratchet
- No replay protection yet
- Channel keys are shared by everyone who receives the key
- Key verification UX is minimal; use out-of-band verification for high assurance
- Encrypted-at-rest storage for ZNC module state is not implemented yet
- IRC line length limits still apply after JSON/base64 expansion
See SECURITY.md for the full threat model.
Automated Linux smoke test:
bash tests/znc/run-linux-smoke.shManual interop checklist:
docs/INTEROP_TESTING.md
Use that checklist before claiming compatibility with a specific mIRC, AndroidIRCX, or Windows ZNC target environment.
include/e2e_core.h Portable crypto API
src/e2e_core.c Portable libsodium implementation
modules/znc/znce2e.cpp ZNC network module
modules/znc/README.md ZNC module-specific usage notes
scripts/run-core-tests-linux.sh Core Linux test runner
scripts/build-znc-linux.sh Linux ZNC module build helper
scripts/build-znc-windows-msys2.sh Windows/MSYS2 build helper
scripts/smoke-wsl-test-znc.sh Live ZNC command smoke test
tests/core_test.c Portable crypto core test
tests/znc/run-linux-smoke.sh Disposable ZNC integration harness
docs/BUILDING.md Build notes
docs/INTEROP_TESTING.md Manual interop checklist
SECURITY.md Threat model and security policy
- Reference protocol / mIRC implementation: https://github.com/AndroidIRCx/e2e.dll
- ZNC: https://znc.in
- libsodium: https://libsodium.gitbook.io/doc/
Open source for educational use. Uses libsodium (ISC license).
Disclaimer: experimental code, use at your own risk.