TorX is a C library enabling user interface developers to interface with Tor to create and manage hidden services for the purpose of transferring data peer to peer, primarily in the form of text, files, and data streams.
The developer was tired of having to manage dozens of anonymous email, XMPP accounts, and associated keys, on top of having to maintain anonymity. We all are.
The developer's friend's family member ended up on Interpol's "Red List" and the developer watched their friend struggle to maintain constant communication with their family member, sometimes going for weeks without communication, as their family member travelled the world using a combination of illicitly obtained passports and unlawful border crossings. When they were in contact, one day they would use a Korean instant messenger, the next day one from Pakistan, and on. It was tedious and unreliable.
The developer was inspired to solve this problem not just for the technically competent (like the developer), but also for the technically illiterate (like the developer's friend and their family member).
WARNING: Diagrams can be inaccurate, outdated, and unclear. With the exception of the "Message Diagram", these diagrams ARE incomplete and REQUIRE updating.
Handshake with V3Key / V3Auth Diagram: ________________________________________________________________________________ | SING <---VV[2]+PeerOnion[56]+PeerV3KeyB64.pub[52]--- Peer | | || (down) | | \/ | | Gen_CTRL | | + PeerV3Key ---VV[2]+CtrlOnion[56]+V3KeyB64.pub[52]---> Peer | | (up) || | | \/ | | (Brings up PeerOnion with V3Key) | |_______________________________________________________________________________|
Private Group Handshake with Signed Messaging Diagram: (Note: Group_Ctrl is passed in Group_offer when PeerCount == 0, and is signed in GROUP_OFFER_ACCEPT(_FIRST) _________________________________________________________________________________________________________________________ | GROUP_OFFER(_FIRST) ---GroupID[32]+PeerCount[4]+InviteRequired[1](+Group_Ctrl[56]+ed25519_pk[32])---> Invitee | | || | | \/ | | (Accepts invitation(+Signs creator Group_Ctrl)) | | (Generate Group_CTRL+Keypair) | | Inviter <---GroupID[32]+Group_Ctrl[56]+ed25519_pk[32](+InvitationSignature[64])--- GROUP_OFFER_ACCEPT(_FIRST) | | || | | if(peercount > 0) ---PEERLIST---> Invitee, who trusts it if !peerlist && group[g].n > 0 | | || | | \/ | | (Sign Invitee's Group_Ctrl) (Sign invitee + Provide invitor invitation) | | GROUP_OFFER_ACCEPT_REPLY ---GroupID[32]+Group_Ctrl[56]+ed25519_pk[32]+InviteeSignature[64] | | || +InvitorSignature[64]---> Invitee | | || || | | \/ \/ | | (group_add_peer --> Connect/Chat) (group_add_peer --> Connect/Chat) | |_______________________________________________________________________________________________________________________|
Public Group Handshake with Signed Messaging Diagram: _________________________________________________________________________________________________________________________ | (Someone scans the Public Group ID off a QR code) | | (Generate Group_CTRL+Keypair) | | GROUP_BROADCAST ---> All online peers ---> All their online peers (promulgates through network) | | | | (Someone in Group) ---> (decrypts GROUP_BROADCAST) ---> GROUP_PUBLIC_ENTRY_REQUEST ---> New peer | | (group_add_peer --> Connect/Chat) | | || | | \/ | | (Someone in Group) <--- GROUP_PUBLIC_ENTRY_REQUEST | | || | | \/ | | (group_add_peer --> Connect/Chat) | |_______________________________________________________________________________________________________________________|
Connecting to other peers after joining a private group (this message is in-group): TODO _________________________________________________________________________________________________________________________ | | | GROUP_REQUEST_PEERLIST ---[0]---> Group_Peer | | || | | || | | Group_Ctrl <---(Signature[64])(Timestamp[4+4])+Peercount[4]+Onions[56*peercount] \/ | | || +Ed25519_pk(s)[32*peercount]+InvitationSignature(s)[64*peercount]--- GROUP_PEERLIST | | || | | \/ | | (add new peers) | | GROUP_ENTRY_REQUEST ---GroupID[32]+Group_Ctrl[56]+ed25519_pk[32]+InvitationSignature[64]---> (new) Group_Peer(s)| | || | | \/ | | Group_Ctrl <---[0]-- GROUP_ENTRY_REQUEST_REPLY_OK | | (update status) (add new peer) | | (Connect/Chat) (Connect/Chat) | |_______________________________________________________________________________________________________________________|
Message Diagram (2024/05/31 version, current). Applies to all protocols except ENUM_PROTOCOL_FILE_PIECE. Integers are in network-order. _________________________________________________________________________________________________________________________________________________________________ | Packet Len [2] uint16_t Unsigned, every packet. Not included in .message_len | | Protocol [2] uint16_t Signed, every packet. Not included in .message_len | | Message Len [4] uint32_t Signed, only in first packet. Not included in .message_len | | Message [.message_len] Included in .message_len | | { '\0' } { [1] } Only where message is expected to a string, included in .message_len (therefore signed if applicable) | | { Time } { [4] uint32_t } Only on dated messages, included in .message_len (therefore signed if applicable) | | { NSTime } { [4] uint32_t } Only on dated messages, included in .message_len (therefore signed if applicable) | | { Signature } { [crypto_sign_BYTES] } Only on signed messages, included in .message_len (NOT ITSELF SIGNED) | |_______________________________________________________________________________________________________________________________________________________________|
Base protocols Diagrams (2024/05/31 version, current). Describes content of "Message" from the "Message Diagram". [Numbers] are byte counts. 1-8 bytes are unsigned int in network order (Big endian). _________________________________________________________________________________________________________________________________________________________________________________ | ENUM_PROTOCOL_FILE_OFFER CHECKSUM[64] + SIZE[8] + MODIFIED[4] + FILENAME (no null termination) | | ENUM_PROTOCOL_FILE_OFFER_PRIVATE CHECKSUM[64] + SIZE[8] + MODIFIED[4] + FILENAME (no null termination) | | ENUM_PROTOCOL_FILE_PAUSE CHECKSUM[64] | | ENUM_PROTOCOL_FILE_CANCEL CHECKSUM[64] | | ENUM_PROTOCOL_FILE_OFFER_GROUP HashOfHashes + Splits[1] + CHECKSUM_BIN_LEN *(splits + 1)) + SIZE[8] + MODIFIED[4] + FILENAME (no null termination) | | ENUM_PROTOCOL_FILE_OFFER_GROUP_DATE_SIGNED HashOfHashes + Splits[1] + CHECKSUM_BIN_LEN *(splits + 1)) + SIZE[8] + MODIFIED[4] + FILENAME (no null termination) | | ENUM_PROTOCOL_FILE_OFFER_PARTIAL HashOfHashes + Splits[1] + CHECKSUM_BIN_LEN *(splits + 1)) + SIZE[8] + split_progress[section][8] *(splits + 1) | | ENUM_PROTOCOL_FILE_REQUEST CHECKSUM[64] + START[8] + END[8] | | ENUM_PROTOCOL_GROUP_BROADCAST crypto_box_SEALBYTES[48] + ( Salt[16] + Onion[56] + ed25519_pk[32] ) | | ENUM_PROTOCOL_GROUP_PUBLIC_ENTRY_REQUEST crypto_box_SEALBYTES[48] + ( Salt[16] + Onion[56] + ed25519_pk[32] ) | | ENUM_PROTOCOL_GROUP_PRIVATE_ENTRY_REQUEST Onion[56] + ed25519_pk[32] + Invitation[64] (invitation is signature of onion + pk by some invitor from group) | | ENUM_PROTOCOL_GROUP_REQUEST_PEERLIST Peercount[4] | | ENUM_PROTOCOL_GROUP_PEERLIST Peercount[4] + onions[56*peercount] + ed25519_pk[56*peercount] { + invitations[64*peercount] } | | ENUM_PROTOCOL_GROUP_OFFER GROUP_ID[32] + Peercount[4] + invite_required[1] | | ENUM_PROTOCOL_GROUP_OFFER_FIRST GROUP_ID[32] + Peercount[4] + invite_required[1] + Onion[56] + ed25519_pk[32] (to be signed by invitee) | | ENUM_PROTOCOL_GROUP_OFFER_ACCEPT GROUP_ID[32] + Onion[56] + ed25519_pk[32] (to be signed by invitor) | | ENUM_PROTOCOL_GROUP_OFFER_ACCEPT_FIRST GROUP_ID[32] + Onion[56] + ed25519_pk[32] + Invitation[64] (we sign invitor/group-creator's onion + pk) | | ENUM_PROTOCOL_GROUP_OFFER_ACCEPT_REPLY GROUP_ID[32] + Onion[56] + ed25519_pk[32] + Invitation[64] + Invitation[64] (1st: new invite for them; 2nd: our invite) | | ENUM_PROTOCOL_PIPE_AUTH Onion[56] | | ENUM_PROTOCOL_PROPOSE_UPGRADE protocol_version[2] | | ENUM_PROTOCOL_KILL_CODE User generated explanation ('My house got raided!' etc) | | ENUM_PROTOCOL_UTF8_TEXT User generated data ('hey how are you?' etc) | | ENUM_PROTOCOL_UTF8_TEXT_DATE_SIGNED User generated data ('hey how are you?' etc) | | ENUM_PROTOCOL_UTF8_TEXT_PRIVATE User generated data ('hey how are you?' etc) | | "other" UI developers can register their own text/binary/stream protocols with the protocol_registration function | |_______________________________________________________________________________________________________________________________________________________________________________|
ENUM_PROTOCOL_FILE_PIECE Diagram (2024/05/31 version, current) _________________________________________________________________________________________________________________________________________________________________ | Packet Len [2] uint16_t Unsigned, every packet. | | Protocol [2] uint16_t Unsigned, every packet. | | Truncated File Checksum [4] unsigned char Unsigned, every packet. To distingush between data from multiple files sent on the same connection. | | Start position [8] uint64_t Unsigned, every packet. Offset from the start of the file. | | Data (up to packet size) Unsigned, every packet. Up to PACKET_SIZE_MAX - 16 (sum of above bytes) of data | |_______________________________________________________________________________________________________________________________________________________________|
Data stored in plaintext on disk (2025/01/10 version, current) ________________________________________________________________________________________________ | .split Files CHECKSUM_BIN_LEN + Splits[1] + split_progress[section][8] *(splits + 1) | | Anything intentionally stored in plaintext to any of the databases. | |_______________________________________________________________________________________________|
As of intial pre-release (November 2024), this is absolute bleeding-edge alpha software. It's not ready to be used with untrusted peers at this time.
Two proof-of-concept TorX UI clients are currently available for Android, Windows, and Linux. It will soon be available for Mac/OSX. Later we intend for it to be available on iOS.
For Android users, please install F-Droid, then click "Settings" --> "Repositories" --> "+" --> "Scan QR Code" (or "Enter repository URL manually" --> https://torx-chat.github.io/)
Alternatively (unsafe), download the TorX.apk file directly, but then you will not get automatic updates.
For Linux users and others, we're intending to put together some packages but currently you should get it from source and contact us for build support.
At the present time, due to the alpha status of the software, the preferred method of obtaining support is on IRC. The following channels exist, in order of preference:
The lead developer's IRC nick is "TorX" and their client supports OTR (Off The Record) encryption. Please do not do anything in the channels that violates the respective network's Terms of Service. If you need help connecting to IRC, ask ChatGPT.
If absolutely necessary, the developer can be contacted by email:
Click here to see our unified schedule and TODO lists.
We need experienced contributors for the following key technical roles:
You are also welcome to offer contribution of other services:
Contributors are expected to:
Contributions can be provided publically or privately. Contributors are welcome to provide their contributions anonymously.
Contributors' private lives are not our concern. If your public or private life actions cause harm to the image of the project, we may ban your pseudonym, which could require you to evade the ban in order to continue providing your much valued contributions to the project.
If you are interested, join one of our IRC channels
Donations will be provided to the developer of TorX in a personal capacity. Donations will either be received directly (if in cryptocurrency) or provided through an intermediary (all other payment methods). Payments received other than through cryptocurrency are subject to fees by the payment processor. No taxes will be paid (donations constitute gifts), but donations are not tax deductible.
Monero is preferred. Interac EMT is without fees (Canada only). Wire transfer has fees for sending *and* receiving, so is only appropriate for donations of >$500.
Signal gets >$50,000,000 a year for less security than TorX intends to offer. Send $50,000,000 to TorX and development will be supported until the robots take over.