UNet Protocol Documentation



1. Introduction

For the purposes of this documentation all example packets and packet fragments will be shown as hexadecimal.

Each data packet sent to/from the UNet server has a header in this format:
[2 bytes Data length][1 byte Type][1 byte Subtype]

Example - a packet of type 1, subtype 1 containing 18 bytes of data will look like this:
00140101

The data is formatted as subpackets, consisting of a length, type, and data. The length will be one or two bytes, depending on packet type/subtype, as noted in the documentation.
Subpacket types are expected to be unique. If your packet contains two subpackets of type 5, one of them will be ignored by the server.

Example - a subpacket of type 5 (using one length byte) containing the word "testing":
080574657374696e67

Encrypted packets are identical except that before attaching the packet header, you should encrypt the data. Example:
Plaintext: 001d0112 080174657374696e67 080274657374696e67 080374657374696e67
Encrypted: 001d0112[Encrypted Data]
Keep in mind that the encrypted data length may not be the same as the plaintext length due to padding, so do not calculate the header Data Length until the encryption is completed.

2. General

Keep-alives

The server must recieve data from the client every 60 seconds or it will be disconnected. It is recommended that you send keep-alive packets every 25-55 seconds to prevent this from happening.

Password Hashing

Regardless of which hash type you choose to use, the input data and method of hashing is the same.
  1. Concatenate password and the string "~`!@#$%^&*()_-+=123456x7890" (without quotes)
  2. Hash this data
  3. Make sure result from first hash is lowercase hexadecimal
  4. Normalize login name (lowercase, no spaces)
  5. Concatenate login name, first hash, and salt from server
  6. Hash this data
Pseudocode: Lowercase(Enhex(Hash(StripSpaces(Lowercase("My User Name")) + Lowercase(Enhex(Hash("mypassword" + "~`!@#$%^&*()_-+=123456x7890"))) + ServerSalt)))

Encryption

The server includes an asymmetric public key when returning the salt for hashing your password. Use this to encrypt the packet you return containing your password and a symmetric key for encrypting future packets.

If your password was correct the server will return a hash along with your formatted username. This hash should be used to verify that the asymmetric key you received was legitimate. If the hash is not valid the user should disconnect from the server.

All the symmetric ciphers are expected to use CBC and PKCS5 Padding.
The CBC initialization vector (IV) should be the same as the block size of the cipher (128-bits for AES/Serpent/Twofish)
The initial IV is chosen by the client and used for both incoming and outgoing data. Note that the IV is never reset - the last block of cyphertext should always be the current IV!
If the data portion of a packet is empty it should not be encrypted - it should be left blank.

The RSA uses OAEP Padding with SHA-512, and the public key is provided to the client X509 encoded

Please remember that only the data portion of packets is encrypted - the header of the packet (first 4 bytes) is always left unencrypted!

Asymmetric hashing

  1. Concatenate password and the string "~`!@#$%^&*()_-+=123456x7890" (without quotes)
  2. Hash this data
  3. Make sure result from first hash is lowercase hexadecimal
  4. Concatenate asymmetric key, salt from client, first hash, and the string "92840293!~`#@$^%&*{}_-+q=" (without quotes)
  5. Hash this data
Pseudocode: Hash(AsymmetricKey + ServerSalt + Lowercase(Enhex(Hash("mypassword" + "~`!@#$%^&*()_-+=123456x7890"))) + "92840293!~`#@$^%&*{}_-+q=")

Login sequence

  1. Connect TCP socket to connect.unfairnet.com, port 1189
  2. Send request for salt (Outgoing 1,1)
  3. Server will send you the salt (Incoming 1,1)
  4. Send the login packet containing username/password (Outgoing 1,2)*
  5. Server will send you the formatted username, and a verification hash (Incoming 1,2)**
  6. Send a status update (Outgoing 1,3)
  7. Send a buddy list request (Outgoing 1,10)
* Encrypted with the asymmetric key the server supplied to you
** Incoming 1,2 and all further packets to and from the server are encrypted using the symmetric key you supplied to the server

Only once these steps are complete (in this order) will you be allowed to send any other packet types (including keep-alives). Sending other packets, or sending any of these steps out of order will return an invalid packet error, and most likely disconnect you from the server.

3. Packet Type Index

Incoming packet types

Type 1 - Login
Subtype 1 - Login salt
Subtype 2 - Formatted name
Type 2 - Logout
Subtype 1 - Logout reason
Type 3 - Messaging
Subtype 1 - IM
Subtype 3 - Offline IM
Subtype 5 - System IM
Type 4 - Chats
Subtype 1 - User entered chat
Subtype 4 - User left chat
Subtype 7 - Chat message
Subtype 8 - Chat log
Subtype 9 - Buddy entered chat
Subtype 10 - Buddy left chat
Subtype 11 - Buddy type (admin/op/etc)
Subtype 17 - Chat formatting
Subtype 18 - Chat newlines
Subtype 20 - System chat message
Subtype 23 - Join request (owners)
Subtype 24 - Join request result
Subtype 26 - Join failed
Subtype 27 - Join pending
Subtype 28 - Chat invite
Subtype 29 - Join rated
Subtype 49 - Public chat list
Type 15 - Buddy information
Subtype 1 - Add buddy
Subtype 2 - Remove buddy
Subtype 5 - Buddy status


Outgoing packet types

Type 1 - Login
Subtype 1 - Request salt
Subtype 2 - Send login
Subtype 3 - Set status
Subtype 10 - Request buddy list
Type 2 - Logout
Subtype 1 - Logout
Type 3 - Messaging
Subtype 1 - IM
Type 4 - Chats
Subtype 1 - Join chat
Subtype 4 - Leave chat
Subtype 7 - Chat message
Subtype 12 - Add op
Subtype 13 - Remove op
Subtype 14 - Kick user
Subtype 15 - Ban user
Subtype 16 - Unban user
Subtype 17 - Toggle formatting
Subtype 18 - Toggle newlines
Subtype 24 - Approve/deny user join
Subtype 25 - Chat mode
Subtype 28 - Chat invite
Subtype 49 - Public chat list
Subtype 50 - Toggle logging
Subtype 51 - Chat history
Type 15 - Buddy information
Subtype 1 - Add buddy
Subtype 2 - Remove buddy
Subtype 5 - Change status
Type 18 - Keep-alive
Subtype 2 - Keep-alive


4. Incoming packet types

Type 1 - Login

Subtype 1 - Login salt

Subpacket length bytes: 2
Data:
[1] x bytes binary, Salt
[2] x bytes binary, RSA public key

Subtype 2 - Formatted name

Subpacket length bytes: 1
* This and all further packets to and from the server are encrypted using the symmetric key you supplied to the server in (Outgoing 1,2)
Data:
[1] x bytes binary, Verify hash for RSA public key
[2] x bytes ascii, Formatted user name

Type 2 - Logout

Subtype 1 - Logout reason

Subpacket length bytes: 1
Data:
[1] 1 byte binary, Disconnect reason *See section 6.1

Type 3 - Messaging

Subtype 1 - IM

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Message

Subtype 3 - Offline IM

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Message
[3] x bytes ascii, Message time in seconds

Subtype 5 - System IM

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Message

Type 4 - Chats

Subtype 1 - User entered chat

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 4 - User left chat

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 7 - Chat message

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name
[3] x bytes ascii, Message

Subtype 8 - Chat log

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name
[3] x bytes ascii, Message
[4] x bytes ascii, Message time in seconds

Subtype 9 - Buddy entered chat

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name

Subtype 10 - Buddy left chat

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name

Subtype 11 - Buddy type (admin/op/etc)

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name
[3] 1 byte binary, Buddy type *See section 6.2

Subtype 17 - Chat formatting

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] 1 byte binary, Chat formatting *Client should strip HTML formatting = 0, Display formatting = 1

Subtype 18 - Chat newlines

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] 1 byte binary, Chat newlines *Client should replace newlines with spaces = 0, Display newlines = 1

Subtype 20 - System chat message

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Message

Subtype 23 - Join request (owners)

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Chat name

Subtype 24 - Join request result

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] 1 byte binary, 0 = denied, 1 = approved

Subtype 26 - Join failed

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 27 - Join pending

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 28 - Chat invite

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Chat name

Subtype 29 - Join rated

Subpacket length bytes: 1
Data: None

Subtype 49 - Public chat list

Subpacket length bytes: 1
Data:
[x] x bytes ascii, Chat name and member count - formatted as name:count

Type 15 - Buddy information

Subtype 1 - Add buddy

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name

Subtype 2 - Remove buddy

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name

Subtype 5 - Buddy status

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Buddy name
[2] 1 byte binary, Status ID *See section 6.3
[3] x bytes ascii, Online since - time in seconds
[4] x bytes ascii, Status message



5. Outgoing packet types

Type 1 - Login

Subtype 1 - Request salt

Subpacket length bytes: 1
*To obtain the client name, version, and author ID please log into your account page on http://unfairnet.com/
Data:
[1] 1 byte binary, Protocol version *Currently version 2
[2] x bytes ascii, Client name
[3] 1 byte binary, Client major version
[4] 1 byte binary, Client minor version
[5] 1 byte binary, Client revision version
[6] 2 bytes binary, Client author ID
[7] 1 byte binary, RSA key size (currently ignored, always 3072-bit for testing) *See section 6.6

Subtype 2 - Send login

Subpacket length bytes: 1
*Packet data encrypted with RSA public key from server in (Incoming 1,1)
Data:
[1] 1 byte binary, Hash type *See section 6.4
[2] x bytes ascii, Enhexed password hash
[3] x bytes ascii, User name
[4] 1 bytes binary, Requested verify RSA hash type *See section 6.4
[5] 6 bytes binary, RSA Salt
[6] 1 bytes binary, Symmetric encryption type *See section 6.5
[7] x bytes binary, Symmetric encryption key
[8] x bytes binary, CBC initialization vector with length equal to symmetric block size

Subtype 3 - Set status

Subpacket length bytes: 2
Data:
[1] 1 byte binary, Status ID *See section 6.3
[2] x bytes ascii, Status message

Subtype 10 - Request buddy list

Subpacket length bytes: 1
Data: None

Type 2 - Logout

Subtype 1 - Logout

Subpacket length bytes: 1
Data: None

Type 3 - Messaging

Subtype 1 - IM

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Message

Type 4 - Chats

Subtype 1 - Join chat

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 4 - Leave chat

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 7 - Chat message

Subpacket length bytes: 2
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Message

Subtype 12 - Add op

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name

Subtype 13 - Remove op

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name

Subtype 14 - Kick user

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name

Subtype 15 - Ban user

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name

Subtype 16 - Unban user

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[2] x bytes ascii, Buddy name

Subtype 17 - Toggle formatting

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 18 - Toggle newlines

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 24 - Approve/deny user join

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Chat name
[3] 1 byte binary, Approve = 1, Deny = 0

Subtype 25 - Chat mode

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name
[1] 1 byte binary, Chat mode, 1 = Request, 2 = Private, 3 = Public

Subtype 28 - Chat invite

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name
[2] x bytes ascii, Chat name

Subtype 49 - Public chat list

Subpacket length bytes: 1
Data: None

Subtype 50 - Toggle logging

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Subtype 51 - Chat history

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Chat name

Type 15 - Buddy information

Subtype 1 - Add buddy

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name

Subtype 2 - Remove buddy

Subpacket length bytes: 1
Data:
[1] x bytes ascii, Buddy name

Subtype 5 - Change status

Subpacket length bytes: 2
Data:
[1] 1 byte binary, Status ID *See section 6.3
[2] x bytes ascii, Status message

Type 18 - Keep-alive

Subtype 2 - Keep-alive

Subpacket length bytes: 1
Data: None



6. Codes and types

Disconnect

  1. Regular disconnect
  2. Invalid packet
  3. Outdated protocol version, please update before reconnecting
  4. Unregistered username
  5. Invalid password
  6. Banned account
  7. Banned IP
  8. Banned client
  9. Login rate limit
  10. Satellite Server ability revoked
  11. Session terminated by administrator
  12. SSL connection required
  13. Connection timeout
  14. Database error
  15. All servers full, please try reconnecting in a few minutes
  16. Cookie invalid
  17. Max connections per IP
  18. Invalid hash type
  19. Cannot connect to client
  20. Account not activated
  21. Unexpected error
  22. Invalid encryption type
  23. Username signed on from a different location
  24. Server rebooting
  25. Outdated client version, please update before reconnecting
  26. Rate limit disconnect
  27. Decryption error
  28. Server failed to load encryption key

Chat user types

  1. Normal
  2. Operator
  3. Owner
  4. Admin

Status types

  1. Offline
  2. Online
  3. Away
  4. Mobile

Hash types

  1. MD5
  2. SHA256
  3. SHA512

Encryption types

  1. AES
  2. Serpent
  3. Twofish

RSA key sizes

  1. 3072-bit
  2. 7680-bit
  3. 15360-bit