├── README.md
├── SUMMARY.md
├── appendix
└── ToxIdenticons.md
├── badge
├── rec.png
└── req.png
├── communication
├── calls.md
├── file_transfers.md
├── friend_requests.md
├── group_chats.md
└── message_formatting.md
├── data_storage
├── data_storage.md
└── export_format.md
├── general_requirements
└── general_requirements.md
├── message_persistence
└── message_persistence.md
├── rationale
└── rationale.md
└── user_identification
├── avatar.md
└── tox_id.md
/README.md:
--------------------------------------------------------------------------------
1 | Introduction
2 | ============
3 |
4 | - This document is intended to define behaviours that are not enforced by
5 | toxcore, but are otherwise required/recommended to ensure proper client
6 | interoperability as well as best security practices.
7 |
8 | - For a Tox client to be endorsed/supported by the Tox Project, it must, at
9 | minimum, comply with every  point in this document (except
10 | where otherwise stated). For this reason, things that are 
11 | should not be needlessly specific.
12 |
13 | - Sometimes, it is not immediately obvious why certain points exist in this
14 | document. For this purpose, there is a Rationale section, where explanations
15 | will be given.
16 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | * [Introduction](README.md)
4 | * [General Requirements](general_requirements/general_requirements.md)
5 | * [User Identification]()
6 | * [Tox ID](user_identification/tox_id.md)
7 | * [Avatar](user_identification/avatar.md)
8 | * [Communication]()
9 | * [Friend Requests](communication/friend_requests.md)
10 | * [Group Chats](communication/group_chats.md)
11 | * [Calls](communication/calls.md)
12 | * [File Transfers](communication/file_transfers.md)
13 | * [Message Formatting](communication/message_formatting.md)
14 | * [Message Persistence](message_persistence/message_persistence.md)
15 | * [Data Storage](data_storage/data_storage.md)
16 | * [Export Format](data_storage/export_format.md)
17 | * [Rationale](rationale/rationale.md)
18 |
--------------------------------------------------------------------------------
/appendix/ToxIdenticons.md:
--------------------------------------------------------------------------------
1 | # ToxIdenticon (= Tox Default Avatar)
2 |
3 | This is the specification of an Identicon generation algorithm, tailored to the use
4 | in the Tox network. For the reference implementation see
5 | https://github.com/qTox/qTox/blob/master/src/widget/tool/identicon.cpp
6 |
7 | ## steps to create the needed color values
8 |
9 | ***0)*** use the 32 bytes of the **Tox Public Key** as input, see
10 |
11 | https://github.com/TokTok/spec/blob/master/spec.md#messenger
12 |
13 | ***1)*** calculate the SHA-256 of the **Tox Public Key**
14 |
15 | ```
16 | pk_hash = SHA256(Tox Public Key);
17 | ```
18 |
19 | ***2)*** take the last 6 bytes of `pk_hash` and store them as `hashpart_1` (zero based index 26 - 31)
20 |
21 | ***3)*** reinterpret `hashpart_1` as unsigned integer, MSB first and store as `hue_uint_1`
22 |
23 | ```
24 | // example for C99 and C++ (do NOT use this in Java!!)
25 | // hashpart_1 is an array of type uint8_t
26 | uint64_t hue_uint_1 = hashpart_1[0];
27 |
28 | // convert the bytes to an uint
29 | for (int i = 1; i < 6; ++i) {
30 | hue_uint_1 = hue_uint_1 << 8;
31 | hue_uint_1 += hashpart_1[i];
32 | }
33 | ```
34 |
35 | ***4)*** normalize `hue_uint_1` to a float of the range 0.0 - 1.0 and store as `hue_color_1`
36 |
37 | ```
38 | // be careful to do the division as float!
39 | // 0xFFFF FFFF FFFF = 281474976710655, the maximum with 48 bits
40 | // '.0' is appended to ensure float division (C and similar languages)
41 | hue_color1 = hue_bytes1 / 281474976710655.0;
42 | ```
43 | ***5)*** `sat_color_1 = 0.5`, `lig_color_1 = 0.3` these are constants choosen to look good
44 |
45 | ***6)*** convert `[hue, sat, lig]_color_1` from HSL to RGB and store as `color1_rbg`
46 |
47 | see https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
48 |
49 | ***7)*** take the next last 6 bytes of `PkHash` and store them as `hashpart2` (zero based index 20 - 25)
50 |
51 | ***8)*** reinterpret and normalize the bytes as in steps ***3)*** and ***4)*** and store as `hue_color_2`
52 |
53 | ***9)*** `sat_color_2 = 0.5`, `lig_color_2 = 0.8` these are constants choosen to look good
54 |
55 | ***10)*** convert `[hue, sat, lig]_color_2` from HSL to RGB and store as `color2_rbg` as in step 6)
56 |
57 | ## steps to create the the Dots on a square grid (5 x 5)
58 |
59 | *pseudo code*:
60 |
61 | ```
62 | for (row = 0; row < 5; ++row)
63 | {
64 | for (col = 0; col < 5; ++col)
65 | {
66 | // mirror on row2
67 | columnIdx = abs( ((col*2)-4) / 2 )
68 | pos = row * 3 + columnIdx
69 | // use one byte from the hash per dot
70 | byte_used = byte **pos** of **pk_hash**
71 | // check if byte_used is even or odd
72 | color_used = byte_used % 2
73 |
74 | if (color_used == 0)
75 | {
76 | // even, use color1
77 | dot has color **color1_rbg**
78 | }
79 | else
80 | {
81 | // odd, use color2
82 | dot has color **color2_rbg**
83 | }
84 | }
85 | }
86 | ```
87 |
88 | now draw those dots on a grid like:
89 |
90 | | **Grid** | | | ||
91 | | ----------- | ----------:| ---:|---:|---:|
92 | | row0/col0 | * | * | * | row0/col4 |
93 | | * | * | * | * | * |
94 | | * | * | * | * | * |
95 | | * | * | * | * | * |
96 | | row4/col0 | * | * | * | row4/col4 |
97 |
98 | This can now be scaled to fit your needs.
99 |
100 | ## Examples
101 |
102 | Echobot ***Tox ID*** 0x76518406F6A9F2217E8DC487CC783C25CC16A15EB36FF32E335A235342C48A39218F515C39A6 // in Hex
103 |
104 | ### steps to create the color values
105 |
106 | 0) ***Tox Public Key*** = 0x76518406F6A9F2217E8DC487CC783C25CC16A15EB36FF32E335A235342C48A39 // in Hex
107 | 1) ***pk_hash*** = 0xecac3754ece2a229dc40f0adff6e3041b8ce4a44c8ec3bd778f90dfd3529e5b7 // in Hex
108 | 2) ***hashpart_1*** = 0x0dfd3529e5b7 // in Hex
109 | 3) ***hue_uint_1*** = 15381169825207 // in Decimal
110 | 4) ***hue_color_1*** = 0.054644894 // is [~ 19.6175 °] on a color wheel, range [0.0 .. 1.0]
111 | 5)
112 | - ***sat_color_1*** = 0.5 (is [50 %], range [0.0 .. 1.0])
113 | - ***lig_color_1*** = 0.3 (is [30 %], range [0.0 .. 1.0])
114 | 6) ***color1_rbg*** = 114, 63, 38 // [r, g, b] color values for 8bit per color
115 |
116 | 7) ***hashpart_2*** = 0xc8ec3bd778f9 // in Hex
117 | 8)
118 | - ***hue_uint_2*** = 220916941814009 // decimal
119 | - ***hue_color_2*** = 0.78485465 // is [~ 281.7628 °] on a color wheel, range [0.0 .. 1.0]
120 | 9)
121 | - ***sat_color_2*** = 0.5 // is [50 %], range [0.0 .. 1.0]
122 | - ***lig_color_2*** = 0.8 // is [80 %], range [0.0 .. 1.0]
123 | 10) ***color2_rbg*** = 214, 178, 229 // [r, g, b] color values for 8bit per color
124 |
125 | *Note:* The color values can slightly differ, because of different HSV2RGB conversion formulas
126 | and the use of `float`. In practice this should not be noticeable by the human eye.
127 |
128 |
129 | ### color the dots
130 |
131 | ```
132 | **hash_01** = 0xecac3754ece2a229dc40f0adff6e3041b8ce4a44c8ec3bd778f90dfd3529e5b7 // in Hex
133 |
134 | for (row = 0; row < 5; ++row)
135 | {
136 | for (col = 0; col < 5; ++col)
137 | {
138 | columnIdx = abs( ((col*2)-4) / 2 )
139 | // example: col=0 row=0 columnIdx=2
140 |
141 | pos = row * 3 + columnIdx
142 | // pos = 2 // in **hash_01**
143 |
144 | byte_used = byte **pos** of **hash_01**
145 | // byte_used = 0x37 // in Hex (= 55 in decimal)
146 |
147 | color_used = byte_used % 2
148 | // color_used = 1 // lighter color
149 |
150 | if (color_used == 0)
151 | {
152 | // left upper dot has the ligher color
153 | dot has color **color1_rbg**
154 | }
155 | else
156 | {
157 | dot has color **color2_rbg**
158 | }
159 | }
160 | }
161 | ```
162 |
163 |
164 | http://www.rapidtables.com/convert/color/hsl-to-rgb.htm
165 |
166 | ### Resulting Identicon for square images:
167 |
168 |
169 |
170 | ### Resulting Identicon for round images:
171 | fill extra space on background with ***color1_rbg***
172 |
173 |
174 |
--------------------------------------------------------------------------------
/badge/rec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tox/Tox-Client-Standard/86e5641cb98d72de3809a3fed82444acdd88ace9/badge/rec.png
--------------------------------------------------------------------------------
/badge/req.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tox/Tox-Client-Standard/86e5641cb98d72de3809a3fed82444acdd88ace9/badge/req.png
--------------------------------------------------------------------------------
/communication/calls.md:
--------------------------------------------------------------------------------
1 | Calls
2 | -----
3 |
4 | - **3.3.1**  A client that supports audio/video calling must keep the
5 | audio and video streams in sync.
6 |
7 | - **3.3.2**  A client should not automatically answer a call. A user must
8 | explicitly answer the call.
9 |
10 | - **3.3.3**  If the client provides an option to automatically answer
11 | calls, its default setting must be to disallow automatic answering of calls.
12 |
--------------------------------------------------------------------------------
/communication/file_transfers.md:
--------------------------------------------------------------------------------
1 | File Transfers
2 | --------------
3 |
4 | - **3.4.1**  A client should not automatically accept inbound file
5 | transfers.
6 |
7 | - **3.4.2**  If the client provides an option to automatically accept
8 | file transfers, its default setting must be to disallow automatic accepting
9 | of file transfers.
10 |
--------------------------------------------------------------------------------
/communication/friend_requests.md:
--------------------------------------------------------------------------------
1 | Friend Requests
2 | ---------------
3 |
4 | - **3.1.1**  A Tox client may not automatically add friends. A user
5 | must explicitly accept friend requests.
6 |
7 | - **3.1.2**  A client must provide a mechanism by which the user may
8 | see the 32-byte public key of any client initiating a friend request. The key
9 | must be displayed in hexadecimal.
10 |
--------------------------------------------------------------------------------
/communication/group_chats.md:
--------------------------------------------------------------------------------
1 | Group Chats
2 | -----------
3 |
4 | - **3.2.1**  A client should not automatically add a user to a group
5 | chat. A user should be required to explicitly accept group chat invitations.
6 |
7 | - **3.2.2**  If the client provides an option to automatically accept
8 | group invitations, its default setting must be to disallow automatic
9 | accepting of invitations.
10 |
11 | - **3.2.3**  When a user attempts to leave a group, before proceeding,
12 | the client should warn the user that their group credentials will be
13 | permanently lost.
14 | - This only applies to the new groupchat implementation and may otherwise be ignored.
15 |
--------------------------------------------------------------------------------
/communication/message_formatting.md:
--------------------------------------------------------------------------------
1 | Message Formatting
2 | ------------------
3 |
4 | - **3.5.1**  A client must encode emoticons as Unicode emoji.
5 |
6 | - **3.5.2**  A receiving client will make a best-effort to display
7 | text exactly as it was sent, and must not transform the text in any way.
8 | - The above rule does not apply if malformed UTF-8 text is received. In
9 | this case, a client may transform the text to any extent necessary to
10 | make it displayable.
11 |
12 | - **3.5.3**  A sending client must not insert or remove any bytes from
13 | the original input.
14 |
15 | - **3.5.4**  Sent messages must be encoded in UTF-8.
16 |
--------------------------------------------------------------------------------
/data_storage/data_storage.md:
--------------------------------------------------------------------------------
1 | Data Storage
2 | ============
3 |
4 | A client is allowed to store profile data internally in any format.
5 |
6 | - **5.0.1**  A client must give the user the option to encrypt their
7 | .tox data file.
8 | - This option must be presented on creation of a new profile.
9 |
10 | - **5.0.2**  A client should give the user the option to decrypt
11 | encrypted profile data.
12 |
13 | - **5.0.3**  If a client's internal storage format deviates from the
14 | Export format defined in [Export Format](export_format.md), it will provide
15 | the ability to export its data into the Export format.
16 |
17 | - **5.0.4**  A client should store its profile data, in the
18 | Export format, in one of the standard platform-specific locations given
19 | below:
20 | - Unix-like : `$XDG_DATA_HOME/tox` and `$HOME/.local/share` if `$XDG_DATA_HOME` is not defined
21 | - Windows : `%APPDATA%/tox/`
22 | - Mac OS X : `~/Library/Application Support/Tox`
23 |
24 |
--------------------------------------------------------------------------------
/data_storage/export_format.md:
--------------------------------------------------------------------------------
1 | Export Format
2 | -------------
3 |
4 | - **5.1.1**  A Toxcore data file saved in the root of the client's
5 | working directory, with the file name `.tox`
6 |
7 | - **5.1.2**  If the client supports user avatars, they will be stored
8 | under the `avatars/` directory in the root of the client's working directory.
9 |
10 | - **5.1.3**  Avatars are named according to the following format:
11 | `PK.png`, where PK is the 64-character hexadecimal public key of its owner.
12 |
13 | - An example file hierarchy:
14 |
15 | ```
16 | +-----------------------------------------------------------------------------------+
17 | | / (client working dir) |
18 | | | |
19 | | +-- tox_save.tox |
20 | | +-- avatars/ |
21 | | | |
22 | | +-- E62DACF4C0DD23156F745874CBDBCD3D3E356F51C67921F7D91A7938CEB87933.png |
23 | | +-- DD2A1340FECE441206B5F3D202E6146E76617270214499B72C5511FCE839F85B.png |
24 | +-----------------------------------------------------------------------------------+
25 | ```
26 |
--------------------------------------------------------------------------------
/general_requirements/general_requirements.md:
--------------------------------------------------------------------------------
1 | General Requirements
2 | ====================
3 |
4 | - **1.0.1**  Clients must not use any form of unencrypted
5 | communication.
6 |
7 | - **1.0.2**  If a client is configured to use a proxy, but is not also
8 | configured to use a forced TCP connection, it must warn the user that their
9 | IP address may not be hidden.
10 |
11 | - **1.0.3**  When a client is configured to use a proxy, and is also
12 | configured to force a TCP connection, all traffic that does not use the proxy
13 | must be blocked, including (but not limited to) DNS and HTTPS-based username
14 | lookups.
15 |
16 | - **1.0.4**  All features supported by the tox.h, toxav.h and
17 | toxencryptsave.h APIs that are used by the client must be fully functional without
18 | the usage of third-party services.
19 |
--------------------------------------------------------------------------------
/message_persistence/message_persistence.md:
--------------------------------------------------------------------------------
1 | Message Persistence
2 | ===================
3 |
4 | - **4.0.1**  A client should provide the ability to save its
5 | message history, and provide a persistent view of that history across client
6 | restarts.
7 |
8 | - **4.0.2**  Message persistence should be disabled by
9 | default.
10 | - Clients may provide users with a setting to enable message persistence by
11 | default.
12 | - If stored message logs are not encrypted, clients must make the user aware
13 | of this fact if they enable message persistence.
14 | -  If message persistence is enabled by default,
15 | all message logs stored on the device must be encrypted using the cryptography
16 | functions provided by the Tox API, or a comparably reputable, free and open
17 | source cryptography library.
18 |
--------------------------------------------------------------------------------
/rationale/rationale.md:
--------------------------------------------------------------------------------
1 | Rationale
2 | ============
3 |
4 | The purpose of the rationale is to expound on clauses for which the purpose may
5 | be confusing or unobvious. The criteria for including a clause in this document
6 | is somewhat arbitrary; inclusion is decided on a case by case basis, usually in
7 | response to questions or confusion within the Tox development community.
8 |
9 | - **1.0.2** If a user's client is configured to use a proxy, it is reasonable
10 | to assume that the user may be attempting to mask their IP address.
11 | Therefore, users must be made aware that UDP traffic may bypass the proxy and
12 | reveal their IP address.
13 |
14 | - **1.0.3** If a user's client is configured to use a proxy with UDP
15 | connections disabled, it must be assumed that the user's intent is to mask
16 | their IP address. Therefore, it should not be possible to bypass the proxy.
17 |
18 | - **1.0.4** Third-party services cannot be accounted for by the Tox Project and
19 | are contrary to the decentralized nature of Tox. They may be unreliable,
20 | insecure, or otherwise compromised. Therefore the user should always have the
21 | option to use the client in a fully functional manner (with respect to the
22 | functionality made available via the Tox API) without being forced to use
23 | third party services.
24 |
25 | - **2.3.3** PNG images are currently the only image type supported by the Tox
26 | core library.
27 |
28 | - **2.3.10** This will ensure that the avatar is unset for all of the user's
29 | friends (as long as their clients comply with the avatar protocol as
30 | described in this document).
31 |
32 | - **3.1.1** When a friend request is accepted, certain identifying information
33 | may become available to initiator of the request. To protect user privacy,
34 | this must not occur without the user's explicit consent.
35 |
36 | - **3.1.2** This provides a way for users to verify the identity of the
37 | requestor out-of-band (e.g. over the phone or in person) before accepting the
38 | request.
39 |
40 | - **3.2.2** When a user joins a group, certain identifying information may
41 | become available to all peers in the group. To protect user privacy,
42 | this must not occur without the user's explicit consent.
43 |
44 | - **3.2.3** A peer's identity in a group, which includes their group public key
45 | and role/permissions, is persistent across client restarts. However, this
46 | identity is permanently lost when the client explicitly leaves the group.
47 |
48 | - **4.0.2** As message history may be stored on a user's device in plaintext,
49 | it is a matter of security to ensure that this does not occur without the
50 | user's explicit consent.
51 |
52 | - **5.0.1** The .tox data file contains all of the information required to steal
53 | a user's identity. Therefore users should always have and be aware of the
54 | option to encrypt this file.
55 |
--------------------------------------------------------------------------------
/user_identification/avatar.md:
--------------------------------------------------------------------------------
1 | Avatar
2 | ------
3 |
4 | - **2.2.1**  A Tox client should allow the user to provide an image
5 | representation of themselves to be sent to friends.
6 |
7 | - **2.2.2**  If a Tox client does not support avatars, all received
8 | file transfers of the type `TOX_FILE_KIND_AVATAR` must be cancelled
9 | immediately.
10 |
11 | Avatar support in Tox clients is not required. The points below are applicable only to clients that provide avatar support.
12 |
13 | - **2.2.3**  Avatars must be PNG images.
14 |
15 | - **2.2.4**  The maximum size of the encoded avatar data is 65536
16 | bytes (64KiB).
17 |
18 | - **2.2.5**  Clients must display avatars at a 1:1 aspect ratio.
19 |
20 | - **2.2.6**  A client may only transmit avatars with an aspect ratio of 1:1. If the user has chosen a non-square avatar, the client must transmit the square portion of the avatar displayed to the user. In the case that the user's client doesn't display avatars, the client must pad the avatar evenly on two sides with transparent rectangles, in order to create a square.
21 |
22 | - **2.2.7**  The user must be allowed to unset the avatar.
23 |
24 | - **2.2.8**  When a friend comes online, and an avatar is set, the
25 | client will send a file transfer of type `TOX_FILE_KIND_AVATAR`, where the
26 | file ID is the hash of the avatar data that will be sent.
27 |
28 | - **2.2.9**  When a user sets a new avatar, the client will send a
29 | file transfer of type `TOX_FILE_KIND_AVATAR` to all friends, where the file
30 | ID is the hash of the avatar data that will be sent.
31 |
32 | - **2.2.10**  When a user unsets an avatar, the client will send an
33 | avatar file transfer of size 0 to all friends. In this case, the file ID is
34 | undefined.
35 |
36 | - **2.2.11**  When a file transfer of type `TOX_FILE_KIND_AVATAR` is received:
37 | - The client must check the file ID against a previously-saved hash of the
38 | friend's avatar. If it is the same, the client must cancel the transfer,
39 | and use the previously-stored avatar.
40 | - The client must check the file size against the maximum size. If it is
41 | greater, the transfer must be cancelled.
42 | - If the file size is 0, the transfer must be cancelled, and any cached
43 | avatar data for that friend must be purged.
44 | - If the transfer does not meet any of the conditions for cancellation, the
45 | avatar must be saved and displayed, and the hash of the file must be
46 | stored alongside the avatar itself.
47 | - The client must keep at least one unmodified copy of the avatar on disk.
48 | Any modificaion for display purposes must be done only in memory, or in a
49 | temporary file.
50 | - **2.2.12**  If a client wants to display Identicons
51 | (a graphical representation of the public key) instead of avatars, it must
52 | do so using the algorithm specified in [/appendixToxIdenticons.md](/appendix/ToxIdenticons.md)
53 |
--------------------------------------------------------------------------------
/user_identification/tox_id.md:
--------------------------------------------------------------------------------
1 | Tox ID
2 | ------
3 |
4 | - **2.1.1**  The Tox ID must be represented as a 76-character
5 | hexadecimal string. Alternative forms are acceptable, but the client must
6 | expose this standard form somewhere.
7 |
8 | - **2.1.2**  A client must clearly expose functionality to allow the user to change their nospam identifier
9 |
--------------------------------------------------------------------------------