Authenticated IRC

C · Needham-Schroeder · AES-256 · Diffie-Hellman

A multi-user chat server in C where users have to authenticate before they can talk, and group conversations are end-to-end keyed between their members. I built it to implement a classic key-distribution protocol from the paper down to the sockets, rather than only reading the message diagrams.

Two services, one server

The server runs two listeners on separate ports: a key distribution centre (KDC) and the chat server itself. Each accepts connections concurrently so several clients can be served at once. Every user has a long-term symmetric key derived ahead of time with a password-based key derivation function, and that long-term key is what the authentication protocol bootstraps from.

Needham-Schroeder authentication

Logging in follows the Needham-Schroeder scheme. A client first talks to the KDC, sending a fresh nonce along with its identity and the name of the chat server it wants to reach. The KDC mints a session key and a ticket, encrypts the reply under the user's long-term key, and sends it back. The client then presents the ticket to the chat server, which is what finally lets it in.

The nonce is the anti-replay anchor: the client checks that the value echoed back matches the one it sent, so a recorded KDC reply cannot be replayed at it later. After that handshake the client and the chat server share a session key and all further traffic rides on it.

Group keys via multi-party Diffie-Hellman

Broadcasting to everyone is easy; the interesting case is a private group. When a user creates a group and invites others, the members run a multi-party Diffie-Hellman exchange so the group ends up with a shared secret that the server itself never holds. The initiator establishes a key with the first member, then folds in each additional member by passing the current shared secret encrypted under the new member's public key and mixing in their contribution. Group messages are encrypted under that derived key with AES-256, so users outside the group cannot read them.

Commands

What I took from it

Implementing Needham-Schroeder by hand is the clearest way to see why the nonce exchange matters, and why the protocol was later patched against replay. It is a study build, the long-term keys and the textbook handshake are not how I would ship a real chat system, but wiring up a KDC, ticket validation, and a group key agreement on top of raw sockets made the whole family of authentication protocols click.