Skip to content

AndroidIRCx/znce2e

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

znce2e - End-to-End Encryption for ZNC

ZNC module Reference Protocol Platform ZNC libsodium

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.

Features

  • 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

Algorithms

  • 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

Build status

Implemented and smoke-tested in WSL/Linux:

  • include/e2e_core.h / src/e2e_core.c portable crypto core
  • tests/core_test.c core round-trip/self-test coverage
  • modules/znc/znce2e.cpp ZNC network module
  • scripts/build-znc-linux.sh Linux build helper
  • scripts/build-znc-windows-msys2.sh Windows/MSYS2 build helper
  • scripts/smoke-wsl-test-znc.sh live ZNC command smoke test
  • tests/znc/run-linux-smoke.sh full 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

Build

Linux / WSL prerequisites

Ubuntu/WSL:

sudo apt-get update
sudo apt-get install -y build-essential pkg-config znc znc-dev libsodium-dev python3 openssl

Linux build command

bash scripts/run-core-tests-linux.sh
bash scripts/build-znc-linux.sh

The module is written to:

build/znc/znce2e.so

Full Linux smoke test

bash tests/znc/run-linux-smoke.sh

This 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.

Install on Linux ZNC

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 build note

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:

  1. Use the znc-buildmod shipped with or built for the target Windows ZNC.
  2. If ZNC is from MSYS2/MinGW, build inside that same MSYS2 environment.
  3. 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.sh

This script intentionally refuses to run from cmd.exe, PowerShell, or Git Bash because those shells do not prove ABI compatibility with Windows ZNC.

ZNC Usage

Load the module as a network module:

/msg *status loadmod znce2e
/msg *znce2e help
/msg *znce2e selftest

Commands

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

DM encryption flow

  1. Share or request a DM key:
/msg *znce2e sharekey <nick>
/msg *znce2e requestkey <nick>
  1. When an offer arrives, accept or reject it:
/msg *znce2e accept <nick>
/msg *znce2e reject <nick>
  1. Send an encrypted DM:
/msg *znce2e encmsg <nick> This private message is encrypted
  1. 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.

Channel encryption flow

  1. Generate a channel key:
/msg *znce2e chan generate #secret
  1. Share or request the channel key:
/msg *znce2e chan share #secret <nick>
/msg *znce2e chan request #secret <nick>
  1. Send an encrypted channel message:
/msg *znce2e chan send #secret This channel message is encrypted
  1. 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.

Protocol

The module uses the same IRC message formats as the AndroidIRCX/mIRC e2e.dll protocol.

DM key request

!enc-req

DM key offer / accept

!enc-offer {"v":1,"idPub":"...","encPub":"...","sig":"..."}
!enc-accept {"v":1,"idPub":"...","encPub":"...","sig":"..."}

sig is an Ed25519 signature over encPub.

DM encrypted message

!enc-msg {"v":1,"from":"<encPub>","nonce":"...","cipher":"..."}

Channel key share

!chanenc-key {"v":1,"channel":"#chan","network":"NetworkName","key":"...","createdAt":123}

Channel encrypted message

!chanenc-msg {"v":1,"nonce":"...","cipher":"..."}

Security Notes

What is strong

  • 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

Important trust boundary

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.

Known limitations

  • 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.

Testing and Interop

Automated Linux smoke test:

bash tests/znc/run-linux-smoke.sh

Manual interop checklist:

docs/INTEROP_TESTING.md

Use that checklist before claiming compatibility with a specific mIRC, AndroidIRCX, or Windows ZNC target environment.

Files

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

Related project

License

Open source for educational use. Uses libsodium (ISC license).

Disclaimer: experimental code, use at your own risk.

About

ZNC AndroidIRCx E2E Module

Resources

Security policy

Stars

Watchers

Forks

Contributors