Skip to content

jason-conway/parcel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

250 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

parcel: An ultra-lightweight, cross-platform, end-to-end encrypted, terminal-based group messaging application

CI CodeFactor goto counter

Supported Platforms

Linux, BSD, Darwin/macOS, Windows, and iOS (kind of) on x86-64, x86, AArch32, and AArch64 architectures.

Installation

Linux, BSD, Darwin/macOS

After cloning the repository, simply

make install

to build and install both parcel and parceld under /usr/local/bin.

Optionally, PREFIX can be set in order to change the install location.

make PREFIX=~/.parcel install

iOS

Both the parcel client and daemon run without modification on iOS devices using ish.

Windows

The simplest way to build parcel on Windows is using w64devkit.

The pre-built mini release variant is just over 50 MB and contains everything needed to build parcel from source.

Once cloned, simply

make install

Note that, by default, the binaries will be installed at %HOMEPATH%\parcel

Windows Binaries

Alternatively, download prebuilt binaries from Github.

Please note, however, that these builds are cross-compiled for x86_64 Windows from an AArch64 MacBook Pro and only minimally tested using Wine through Rosetta 2 on an unsupported version of macOS.

Usage

Print usage information with -h:

    usage: parcel [-lhd] [-a ADDR] [-p PORT] [-u NAME]
      -a ADDR  server address (www.example.com, 111.222.333.444)
      -p PORT  server port (default: 2315)
      -u NAME  username displayed alongside sent messages
      -l       use computer login as username
      -h       print this usage information

If the target server is on the default port, then the only required arguments are server address and username. Passing the flag -l on launch sets the username as the computer login.

If a required argument is not provided, then it is prompted at startup.

Security

Parcel encrypts and decrypts message data using AES128.

Messages are authenticated using CMAC (OMAC1) to guarantee message authenticity and data integrity. The CMAC tag authenticates ciphertext rather than plaintext, allowing the message to be authenticated prior to decryption.

Key Exchange

The parcel daemon, parceld, generates a random 32-byte control key at startup. After establishing a secured channel, this key is shared with the client and used to decrypt TYPE_CTRL messages from the daemon.

The control key is used only once, with TYPE_CTRL messages containing the next control keys as part of its encrypted contents.

Upon recieving and decrypting a control message, the parcel clients perform a multi-party

Elliptic-curve Diffie-Hellman key exchange using Curve25519, at which point all clients posess a new shared key. A new group key is derived whenever the number of clients changes.

Frequently Asked Questions

But why though?

Windows Considerations

parcel uses standard ANSI X3.64 (ISO 6429) escape sequences for in-band signaling. Despite having been standardized since 1979, they lacked proper support in Windows until the Windows 10 Anniversery Update in 2016.

If you're running this version or newer, parcel should properly configure the console automatically. In the unlikely case that parcel is unable to configure the console, you can try adding the following registry key to globally enable Virtual Terminal Processing.

REG ADD HKCU\CONSOLE /f /v VirtualTerminalLevel /t REG_DWORD /d 1

If an earlier version of Windows is being used or if parcel is being run from a different shell, the extra console configuration will fail silently and parcel will continue as normal.

The number of active clients supported by parceld is determined by FD_SETSIZE. As a result, parceld supports a maximum of 64 active clients when running on Windows.

Windows support for UTF-8 has been improving in recent years, with Windows Version 1903 introducing the ability to set UTF-8 as an active process's codepage. Parcel takes advantage of this and embeds the required XML to set the process codepage directly into the application binary. Additionally, the console's codepage is set to UTF-8 at runtime, although this only works for console output... because despite UTF-8 becoming standarized in 1993, there remains no way to read UTF-8 input in Windows. To combat this, UTF-16 input is read in one character at a time using ReadConsoleW() and encoded as UTF-8 with WideCharToMultiByte(). It might not be ideal but gets the job done.

Client-Side Commands

All commands start with a slash followed by the command itself.

Command Description
/list List available commands
/x Exit the server and close parcel
/username Change username
/encinfo Display active session and control keys
/file Send a file
/clear Clear the screen
/version Display application version

Commands can be parsed once enough has been typed to become unambiguous, i.e., the username command can be entered as /u, clear can be /c, etcetera.

Commands are interactive only, no need to supply arguments.

Wire Format

Cable Framing Layer

All wire messages are encapsulated in a cable structure for transmission between client and daemon. The cable provides a framing layer that allows the receiver to know exactly how much data to expect.

The cable structure consists of two components:

magic contains the 6-byte magic number parcel for validation.

length contains the 8-byte total length of the cable (including the 14-byte header and the entire wire payload).

The complete transmission format is:

[magic (6 bytes) | length (8 bytes) | wire (variable)]

Wire Structure

The wire consists of an authentication section, header, and data payload.

Authentication Section (48 bytes):

mac_outer contains the 16-byte MAC of the entire wire (inner MAC, IV, header, and data sections).

mac_inner contains the 16-byte MAC of the wire header only, preventing length oracle attacks.

iv contains the 16-byte Initialization Vector required for cipher block chaining. Sent as plaintext, as it needs only to be random- not secret.

Header (16 bytes):

magic contains the 6-byte magic number "-wire-".

wire_len contains the 8-byte total length of the entire wire.

alignment is a 1-byte field indicating padding bytes added to align data with the AES block size.

type is a 1-byte field indicating the message type (see Wire Types below).

Data:

data contains one or more 16-byte chunks of encrypted data.

The complete wire structure is:

[mac_outer (16) | mac_inner (16) | iv (16) | magic (6) | wire_len (8) | alignment (1) | type (1) | data (variable)]

Wire Types

The following message types are defined:

TYPE_TEXT

Standard text messages sent between clients. Contains UTF-8 encoded chat messages.

TYPE_FILE

File transfer messages. The data section contains a wire_file_message struct with the filename, file size, and file data.

TYPE_STAT

Status messages automatically sent by clients to inform others of connection state changes (join, leave, username changes).

TYPE_CTRL

Control messages sent only by the daemon to trigger group key exchange operations. The data section contains a wire_ctrl_message struct with a control function, function arguments, and the renewed control key. These messages trigger a GDHKE (Group Diffie-Hellman Key Exchange) sequence to update session keys.

TYPE_SESSION_KEY

Session key distribution messages used during the multi-party key exchange protocol. Contains public keys or derived key material for establishing the shared session key.

TYPE_NONE and TYPE_ERROR

Internal types used for initialization and error handling. Not transmitted over the network.

About

Multiplatform, lightweight, and secure group messaging

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages