Skip to content

AugustoAmaral/distributed-chat-assignment

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Distributed Chat (SD Assignment) 👋

License: ISC

A tiny distributed chat built with Node.js and Express for a Distributed Systems (SD) assignment. Each instance runs an HTTP server and a simple CLI so peers can register each other and exchange encrypted messages.

Overview

This app runs a local HTTP server and an interactive CLI menu:

  • You start the server on a machine/port.
  • You “Add IP” to register a remote peer. A mutual registration happens automatically: the remote stores your identity, and you store the remote’s identity.
  • You can then send messages to any registered peer. Messages are encrypted end-to-end with a shared key derived from both peers’ identity objects.
  • You can list messages received, filter by user, and manage the local peer list.

Key files:

  • src/server.js: HTTP server, routes, CLI loop bootstrap
  • src/client.js: CLI flow and actions for each menu option
  • src/utils.js: utilities (I/O, HTTP calls, cryptography, formatting)

Requirements

  • Node.js 14+ (CommonJS project)

Install

npm install

Run

Start the server and open the CLI:

npm start

For auto-reload during development:

npm run dev

By default, the server listens on port 3000 (see src/server.js).

CLI Menu

When the server starts, you’ll see a menu with options:

  1. List IPs — show the known peer list
  2. Add IP — register a new peer (format: 127.0.0.1:3001)
  3. Remove IP — remove a peer by index
  4. List messages — show all messages or filter by user name
  5. Send message — pick a peer and send an encrypted message
  6. Exit — terminate the app

Notes:

  • “Add IP” performs a two-way handshake using the /cadastro endpoint: the remote stores your identity; you store the remote’s identity (from the response).
  • “Send message” uses the /mensagem endpoint on the selected peer.

How peers identify and authenticate

Each instance defines its identity in src/server.js as meusDados:

var meusDados = {
	ip: '127.0.0.1',
	nome: 'Jhonatan',
	porta: '3000',
	chave: 'chaveUltraSecreta'
}
  • ip: your host/IP address reachable by peers
  • nome: a human-friendly name
  • porta: the port your server listens on (string)
  • chave: a shared identifier used to look up the sender on message receipt

Important: The chave value is used for sender lookup (basic authentication), not as the actual encryption key.

Endpoints

All endpoints accept/return plain text or JSON as noted.

  1. POST /cadastro
  • Request headers: ip, nome, porta, chave (describing the caller)
  • Behavior: the receiver stores the caller’s identity in its local list and responds with its own identity (meusDados) as JSON
  • Response: 200 OK and JSON body { ip, nome, porta, chave }
  1. POST /mensagem
  • Request headers: chave (sender’s chave)
  • Request body: AES-encrypted message (text)
  • Behavior: the receiver verifies the sender by matching chave with a known peer; if found, it decrypts and stores both the plaintext and ciphertext
  • Responses:
    • 200 OK with Ok on success
    • 500 with Usuário não cadastrado if the sender is unknown

Encryption model (CryptoJS AES)

Messages are encrypted symmetrically using crypto-js AES. The encryption key is derived from the two peers’ identity objects:

  • Encryption: AES.encrypt(message, JSON.stringify([sender, receiver]))
  • Decryption: AES.decrypt(ciphertext, JSON.stringify([sender, receiver]))

Where sender and receiver are full identity objects as exchanged via /cadastro.

Security note: This is an academic/demo scheme. Deriving a key from JSON-serialized identity objects is not secure for production. There is no integrity/authentication of headers beyond the simple chave lookup.

Data structures

  • Identity (meusDados / peer entry)

     { ip: string; nome: string; porta: string; chave: string }
  • Message entry (stored on receiver)

     { ip: string; nome: string; porta: string; mensagem: string; mensagemCriptografada: string }
  • Peer list: Array<Identity>

  • Message list: Array<MessageEntry>

Typical flow (example with two peers)

  1. Prepare two instances:

    • Peer A: in src/server.js, keep porta = 3000, set meusDados.nome, meusDados.chave as you like.
    • Peer B: duplicate the project (or run on another machine) and change porta and meusDados.porta (e.g., 3001), update meusDados.nome and meusDados.chave.
  2. Start both:

    • On each, run npm start.
  3. On Peer A, choose “Add IP” and enter 127.0.0.1:3001 (or the Peer B host:port).

    • Peer B will log the registration.
    • Peer A now has Peer B in its list.
  4. Send messages:

    • On Peer A, choose “Send message”, type the content, select Peer B by index.
    • Peer B will receive, decrypt, and store the message.
  5. Inspect messages on the receiver via “List messages”. Filter by user or show all.

Configuration tips

  • To change the listening port, edit porta in src/server.js and keep meusDados.porta in sync.
  • Ensure meusDados.ip is reachable by the remote peer (e.g., LAN IP, not just 127.0.0.1 across machines).
  • The menu uses standard input; run each instance in its own terminal.

Troubleshooting

  • “Usuário não cadastrado” on /mensagem:

    • Register the sender on the receiver using “Add IP” (only one side needs to add; the handshake stores identities on both sides).
    • Verify chave matches the stored identity.
  • “Falha ao enviar a mensagem”:

    • Check the IP/port are correct and reachable from the sender.
    • Confirm the remote server is running and not blocked by a firewall.
  • No messages shown:

    • Ensure you sent to the correct peer index.
    • Use “List messages” and enter 0 to see all.

Authors

👤 Augusto Amaral, Matheus Dias, Leonardo Nascimento, Bruno Palmeira de Oliveira

License

ISC — see the badge above. If you add a LICENSE file, reference it here.

Stars

If this project helped you, give it a ⭐️!

About

Trabalho de SD

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published