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.
- Concatenate password and the string "~`!@#$%^&*()_-+=123456x7890" (without quotes)
- Hash this data
- Make sure result from first hash is lowercase hexadecimal
- Normalize login name (lowercase, no spaces)
- Concatenate login name, first hash, and salt from server
- 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
- Concatenate password and the string "~`!@#$%^&*()_-+=123456x7890" (without quotes)
- Hash this data
- Make sure result from first hash is lowercase hexadecimal
- Concatenate asymmetric key, salt from client, first hash, and the string "92840293!~`#@$^%&*{}_-+q=" (without quotes)
- Hash this data
Pseudocode: Hash(AsymmetricKey + ServerSalt + Lowercase(Enhex(Hash("mypassword" + "~`!@#$%^&*()_-+=123456x7890"))) + "92840293!~`#@$^%&*{}_-+q=")
Login sequence
- Connect TCP socket to connect.unfairnet.com, port 1189
- Send request for salt (Outgoing 1,1)
- Server will send you the salt (Incoming 1,1)
- Send the login packet containing username/password (Outgoing 1,2)*
- Server will send you the formatted username, and a verification hash (Incoming 1,2)**
- Send a status update (Outgoing 1,3)
- 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
Type 2 - Logout
Type 3 - Messaging
Type 4 - Chats
Type 15 - Buddy information
Outgoing packet types
Type 1 - Login
Type 2 - Logout
Type 3 - Messaging
Type 4 - Chats
Type 15 - Buddy information
Type 18 - 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
- Regular disconnect
- Invalid packet
- Outdated protocol version, please update before reconnecting
- Unregistered username
- Invalid password
- Banned account
- Banned IP
- Banned client
- Login rate limit
- Satellite Server ability revoked
- Session terminated by administrator
- SSL connection required
- Connection timeout
- Database error
- All servers full, please try reconnecting in a few minutes
- Cookie invalid
- Max connections per IP
- Invalid hash type
- Cannot connect to client
- Account not activated
- Unexpected error
- Invalid encryption type
- Username signed on from a different location
- Server rebooting
- Outdated client version, please update before reconnecting
- Rate limit disconnect
- Decryption error
- Server failed to load encryption key
Chat user types
- Normal
- Operator
- Owner
- Admin
Status types
- Offline
- Online
- Away
- Mobile
Hash types
Encryption types
RSA key sizes
- 3072-bit
- 7680-bit
- 15360-bit