summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL.md18
-rw-r--r--auto_tests/encryptsave_test.c10
-rw-r--r--toxencryptsave/toxencryptsave.c94
-rw-r--r--toxencryptsave/toxencryptsave.h136
4 files changed, 165 insertions, 93 deletions
diff --git a/INSTALL.md b/INSTALL.md
index 14d2ef67..0f88b084 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -59,10 +59,10 @@ You should get and install [libsodium](https://github.com/jedisct1/libsodium):
59```bash 59```bash
60git clone git://github.com/jedisct1/libsodium.git 60git clone git://github.com/jedisct1/libsodium.git
61cd libsodium 61cd libsodium
62git checkout tags/0.7.0 62git checkout tags/1.0.0
63./autogen.sh 63./autogen.sh
64./configure && make check 64./configure && make check
65sudo checkinstall --install --pkgname libsodium --pkgversion 0.7.0 --nodoc 65sudo checkinstall --install --pkgname libsodium --pkgversion 1.0.0 --nodoc
66sudo ldconfig 66sudo ldconfig
67cd .. 67cd ..
68``` 68```
@@ -74,7 +74,7 @@ this will install the libs to /usr/local/lib and the headers to /usr/local/inclu
74```bash 74```bash
75git clone git://github.com/jedisct1/libsodium.git 75git clone git://github.com/jedisct1/libsodium.git
76cd libsodium 76cd libsodium
77git checkout tags/0.7.0 77git checkout tags/1.0.0
78./autogen.sh 78./autogen.sh
79./configure 79./configure
80make check 80make check
@@ -137,7 +137,7 @@ brew list libsodium
137 137
138Configure include and lib folder and build again: 138Configure include and lib folder and build again:
139```bash 139```bash
140./configure --with-libsodium-headers=/usr/local/Cellar/libsodium/0.7.0/include/ --with-libsodium-libs=/usr/local/Cellar/libsodium/0.7.0/lib/ 140./configure --with-libsodium-headers=/usr/local/Cellar/libsodium/1.0.0/include/ --with-libsodium-libs=/usr/local/Cellar/libsodium/1.0.0/lib/
141make 141make
142make install 142make install
143``` 143```
@@ -354,7 +354,7 @@ Now we will build sodium crypto library:
354```bash 354```bash
355git clone https://github.com/jedisct1/libsodium/ 355git clone https://github.com/jedisct1/libsodium/
356cd libsodium 356cd libsodium
357git checkout tags/0.7.0 357git checkout tags/1.0.0
358./autogen.sh 358./autogen.sh
359./configure --host="$WINDOWS_TOOLCHAIN" --prefix="$PREFIX_DIR" --disable-shared --enable-static 359./configure --host="$WINDOWS_TOOLCHAIN" --prefix="$PREFIX_DIR" --disable-shared --enable-static
360make 360make
@@ -409,10 +409,10 @@ When installing MinGW, make sure to select the MSYS option in the installer.
409MinGW will install an "MinGW shell" (you should get a shortcut for it), make sure to perform all operations (i.e., generating/running configure script, compiling, etc.) from the MinGW shell. 409MinGW will install an "MinGW shell" (you should get a shortcut for it), make sure to perform all operations (i.e., generating/running configure script, compiling, etc.) from the MinGW shell.
410 410
411First download the source tarball from https://download.libsodium.org/libsodium/releases/ and build it. 411First download the source tarball from https://download.libsodium.org/libsodium/releases/ and build it.
412Assuming that you got the libsodium-0.7.0.tar.gz release: 412Assuming that you got the libsodium-1.0.0.tar.gz release:
413```cmd 413```cmd
414tar -zxvf libsodium-0.7.0.tar.gz 414tar -zxvf libsodium-1.0.0.tar.gz
415cd libsodium-0.7.0 415cd libsodium-1.0.0
416./configure 416./configure
417make 417make
418make install 418make install
@@ -536,7 +536,7 @@ OS X homebrew:
536brew install libconfig 536brew install libconfig
537``` 537```
538OS X non-homebrew: 538OS X non-homebrew:
539Grab the following [package] (http://www.hyperrealm.com/libconfig/), uncompress and install 539Grab the following [package](http://www.hyperrealm.com/libconfig/), uncompress and install
540 540
541See this [readme](other/bootstrap_daemon/README.md) on how to set up the bootstrap daemon. 541See this [readme](other/bootstrap_daemon/README.md) on how to set up the bootstrap daemon.
542 542
diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c
index 85952392..3045fbfa 100644
--- a/auto_tests/encryptsave_test.c
+++ b/auto_tests/encryptsave_test.c
@@ -99,8 +99,8 @@ START_TEST(test_save_friend)
99 // now test compaitibilty with tox_encrypted_load, first manually... 99 // now test compaitibilty with tox_encrypted_load, first manually...
100 uint8_t out1[size], out2[size]; 100 uint8_t out1[size], out2[size];
101 printf("Trying to decrypt from pw:\n"); 101 printf("Trying to decrypt from pw:\n");
102 uint32_t sz1 = tox_pass_decrypt(data2+TOX_ENC_SAVE_MAGIC_LENGTH, size-TOX_ENC_SAVE_MAGIC_LENGTH, pw, pwlen, out1); 102 uint32_t sz1 = tox_pass_decrypt(data2, size, pw, pwlen, out1);
103 uint32_t sz2 = tox_pass_key_decrypt(data2+TOX_ENC_SAVE_MAGIC_LENGTH, size-TOX_ENC_SAVE_MAGIC_LENGTH, key, out2); 103 uint32_t sz2 = tox_pass_key_decrypt(data2, size, key, out2);
104 ck_assert_msg(sz1 == sz2, "differing output sizes"); 104 ck_assert_msg(sz1 == sz2, "differing output sizes");
105 ck_assert_msg(memcmp(out1, out2, sz1) == 0, "differing output data"); 105 ck_assert_msg(memcmp(out1, out2, sz1) == 0, "differing output data");
106 106
@@ -145,6 +145,12 @@ START_TEST(test_keys)
145 sz = tox_pass_decrypt(encrypted, 44+tox_pass_encryption_extra_length(), "123qweasdzxc", 12, out1); 145 sz = tox_pass_decrypt(encrypted, 44+tox_pass_encryption_extra_length(), "123qweasdzxc", 12, out1);
146 ck_assert_msg(sz == 44, "sz isn't right"); 146 ck_assert_msg(sz == 44, "sz isn't right");
147 ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 3 failed"); 147 ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 3 failed");
148
149 uint8_t salt[tox_pass_salt_length()];
150 ck_assert_msg(0 == tox_get_salt(encrypted, salt), "couldn't get salt");
151 uint8_t key2[tox_pass_key_length()];
152 tox_derive_key_with_salt("123qweasdzxc", 12, salt, key2);
153 ck_assert_msg(0 == memcmp(key, key2, tox_pass_key_length()), "salt comparison failed");
148} 154}
149END_TEST 155END_TEST
150 156
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
index 6567eb96..b6453a89 100644
--- a/toxencryptsave/toxencryptsave.c
+++ b/toxencryptsave/toxencryptsave.c
@@ -36,9 +36,9 @@
36#endif 36#endif
37 37
38#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ 38#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \
39 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES) 39 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
40 40
41#define TOX_PASS_KEY_LENGTH (crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES) 41#define TOX_PASS_KEY_LENGTH (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES)
42 42
43int tox_pass_encryption_extra_length() 43int tox_pass_encryption_extra_length()
44{ 44{
@@ -50,6 +50,11 @@ int tox_pass_key_length()
50 return TOX_PASS_KEY_LENGTH; 50 return TOX_PASS_KEY_LENGTH;
51} 51}
52 52
53int tox_pass_salt_length()
54{
55 return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
56}
57
53/* This "module" provides functions analogous to tox_load and tox_save in toxcore 58/* This "module" provides functions analogous to tox_load and tox_save in toxcore
54 * Clients should consider alerting their users that, unlike plain data, if even one bit 59 * Clients should consider alerting their users that, unlike plain data, if even one bit
55 * becomes corrupted, the data will be entirely unrecoverable. 60 * becomes corrupted, the data will be entirely unrecoverable.
@@ -59,7 +64,24 @@ int tox_pass_key_length()
59/* return size of the messenger data (for encrypted saving). */ 64/* return size of the messenger data (for encrypted saving). */
60uint32_t tox_encrypted_size(const Tox *tox) 65uint32_t tox_encrypted_size(const Tox *tox)
61{ 66{
62 return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH + TOX_ENC_SAVE_MAGIC_LENGTH; 67 return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
68}
69
70/* This retrieves the salt used to encrypt the given data, which can then be passed to
71 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted
72 * data with this module can be used as input.
73 *
74 * returns -1 if the magic number is wrong
75 * returns 0 otherwise (no guarantee about validity of data)
76 */
77int tox_get_salt(uint8_t *data, uint8_t *salt)
78{
79 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
80 return -1;
81
82 data += TOX_ENC_SAVE_MAGIC_LENGTH;
83 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
84 return 0;
63} 85}
64 86
65/* Generates a secret symmetric key from the given passphrase. out_key must be at least 87/* Generates a secret symmetric key from the given passphrase. out_key must be at least
@@ -76,19 +98,28 @@ uint32_t tox_encrypted_size(const Tox *tox)
76 */ 98 */
77int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) 99int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key)
78{ 100{
101 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
102 randombytes(salt, sizeof salt);
103 return tox_derive_key_with_salt(passphrase, pplength, salt, out_key);
104}
105
106/* Same as above, except with use the given salt for deterministic key derivation.
107 * The salt must be tox_salt_length() bytes in length.
108 */
109int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key)
110{
79 if (pplength == 0) 111 if (pplength == 0)
80 return -1; 112 return -1;
81 113
82 uint8_t passkey[crypto_hash_sha256_BYTES]; 114 uint8_t passkey[crypto_hash_sha256_BYTES];
83 crypto_hash_sha256(passkey, passphrase, pplength); 115 crypto_hash_sha256(passkey, passphrase, pplength);
84 /* First derive a key from the password */ 116
117 uint8_t key[crypto_box_KEYBYTES];
118
119 /* Derive a key from the password */
85 /* http://doc.libsodium.org/key_derivation/README.html */ 120 /* http://doc.libsodium.org/key_derivation/README.html */
86 /* note that, according to the documentation, a generic pwhash interface will be created 121 /* note that, according to the documentation, a generic pwhash interface will be created
87 * once the pwhash competition (https://password-hashing.net/) is over */ 122 * once the pwhash competition (https://password-hashing.net/) is over */
88 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
89 uint8_t key[crypto_box_KEYBYTES];
90 randombytes(salt, sizeof salt);
91
92 if (crypto_pwhash_scryptsalsa208sha256( 123 if (crypto_pwhash_scryptsalsa208sha256(
93 key, sizeof(key), passkey, sizeof(passkey), salt, 124 key, sizeof(key), passkey, sizeof(passkey), salt,
94 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ 125 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
@@ -123,13 +154,17 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *
123 * need them to decrypt the data 154 * need them to decrypt the data
124 */ 155 */
125 156
126 /* first add the prefix */ 157 /* first add the magic number */
127 uint8_t nonce[crypto_box_NONCEBYTES]; 158 memcpy(out, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
128 random_nonce(nonce); 159 out += TOX_ENC_SAVE_MAGIC_LENGTH;
129 160
161 /* then add the rest prefix */
130 memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 162 memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
131 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 163 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
132 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 164 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
165
166 uint8_t nonce[crypto_box_NONCEBYTES];
167 random_nonce(nonce);
133 memcpy(out, nonce, crypto_box_NONCEBYTES); 168 memcpy(out, nonce, crypto_box_NONCEBYTES);
134 out += crypto_box_NONCEBYTES; 169 out += crypto_box_NONCEBYTES;
135 170
@@ -172,11 +207,6 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3
172 uint8_t temp_data[temp_size]; 207 uint8_t temp_data[temp_size];
173 tox_save(tox, temp_data); 208 tox_save(tox, temp_data);
174 209
175 /* the output data consists of, in order: magic number, enc_data */
176 /* first add the magic number */
177 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
178 data += TOX_ENC_SAVE_MAGIC_LENGTH;
179
180 /* now encrypt */ 210 /* now encrypt */
181 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); 211 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data);
182} 212}
@@ -194,11 +224,6 @@ int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key)
194 uint8_t temp_data[temp_size]; 224 uint8_t temp_data[temp_size];
195 tox_save(tox, temp_data); 225 tox_save(tox, temp_data);
196 226
197 /* the output data consists of, in order: magic number, enc_data */
198 /* first add the magic number */
199 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
200 data += TOX_ENC_SAVE_MAGIC_LENGTH;
201
202 /* encrypt */ 227 /* encrypt */
203 return tox_pass_key_encrypt(temp_data, temp_size, key, data); 228 return tox_pass_key_encrypt(temp_data, temp_size, key, data);
204} 229}
@@ -211,9 +236,12 @@ int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key)
211 */ 236 */
212int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) 237int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out)
213{ 238{
214 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) 239 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH
240 || 0 != memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH))
215 return -1; 241 return -1;
216 242
243 data += TOX_ENC_SAVE_MAGIC_LENGTH;
244
217 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 245 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
218 //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 246 //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
219 uint8_t nonce[crypto_box_NONCEBYTES]; 247 uint8_t nonce[crypto_box_NONCEBYTES];
@@ -241,12 +269,11 @@ int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *ke
241 */ 269 */
242int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) 270int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out)
243{ 271{
244
245 uint8_t passkey[crypto_hash_sha256_BYTES]; 272 uint8_t passkey[crypto_hash_sha256_BYTES];
246 crypto_hash_sha256(passkey, passphrase, pplength); 273 crypto_hash_sha256(passkey, passphrase, pplength);
247 274
248 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 275 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
249 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 276 memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
250 277
251 /* derive the key */ 278 /* derive the key */
252 uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 279 uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
@@ -272,12 +299,6 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase,
272 */ 299 */
273int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) 300int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength)
274{ 301{
275 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
276 return -1;
277
278 data += TOX_ENC_SAVE_MAGIC_LENGTH;
279 length -= TOX_ENC_SAVE_MAGIC_LENGTH;
280
281 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 302 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
282 uint8_t temp_data[decrypt_length]; 303 uint8_t temp_data[decrypt_length];
283 304
@@ -295,12 +316,6 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *
295 */ 316 */
296int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key) 317int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key)
297{ 318{
298 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
299 return -1;
300
301 data += TOX_ENC_SAVE_MAGIC_LENGTH;
302 length -= TOX_ENC_SAVE_MAGIC_LENGTH;
303
304 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 319 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
305 uint8_t temp_data[decrypt_length]; 320 uint8_t temp_data[decrypt_length];
306 321
@@ -316,10 +331,15 @@ int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8
316 * returns 1 if it is encrypted 331 * returns 1 if it is encrypted
317 * returns 0 otherwise 332 * returns 0 otherwise
318 */ 333 */
319int tox_is_save_encrypted(const uint8_t *data) 334int tox_is_data_encrypted(const uint8_t *data)
320{ 335{
321 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) 336 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0)
322 return 1; 337 return 1;
323 else 338 else
324 return 0; 339 return 0;
325} 340}
341
342int tox_is_save_encrypted(const uint8_t *data)
343{
344 return tox_is_data_encrypted(data);
345}
diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h
index 14334ea7..169f736c 100644
--- a/toxencryptsave/toxencryptsave.h
+++ b/toxencryptsave/toxencryptsave.h
@@ -35,46 +35,44 @@ extern "C" {
35typedef struct Tox Tox; 35typedef struct Tox Tox;
36#endif 36#endif
37 37
38// these two functions provide access to these defines in toxencryptsave.c, which 38// these functions provide access to these defines in toxencryptsave.c, which
39//otherwise aren't actually available in clients... 39// otherwise aren't actually available in clients...
40int tox_pass_encryption_extra_length(); 40int tox_pass_encryption_extra_length();
41 41
42int tox_pass_key_length(); 42int tox_pass_key_length();
43 43
44/* This "module" provides functions analogous to tox_load and tox_save in toxcore 44int tox_pass_salt_length();
45 * Clients should consider alerting their users that, unlike plain data, if even one bit
46 * becomes corrupted, the data will be entirely unrecoverable.
47 * Ditto if they forget their password, there is no way to recover the data.
48 */
49 45
50/* return size of the messenger data (for encrypted saving). */ 46/* return size of the messenger data (for encrypted Messenger saving). */
51uint32_t tox_encrypted_size(const Tox *tox); 47uint32_t tox_encrypted_size(const Tox *tox);
52 48
53/* Generates a secret symmetric key from the given passphrase. out_key must be at least 49/* This "module" provides functions analogous to tox_load and tox_save in toxcore,
54 * tox_pass_key_length() bytes long. 50 * as well as functions for encryption of arbitrary client data (e.g. chat logs).
55 * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
56 * This function is fairly cheap, but irungentoo insists that you be allowed to
57 * cache the result if you want, to minimize computation for repeated encryptions.
58 * The password is zeroed after key derivation.
59 * The key should only be used with the other functions in this module, as it
60 * includes a salt.
61 * 51 *
62 * returns 0 on success 52 * It is conceptually organized into two parts. The first part are the functions
63 * returns -1 on failure 53 * with "key" in the name. To use these functions, first derive an encryption key
64 */ 54 * from a password with tox_derive_key_from_pass, and use the returned key to
65int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key); 55 * encrypt the data. The second part takes the password itself instead of the key,
66 56 * and then delegates to the first part to derive the key before de/encryption,
67/* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output 57 * which can simplify client code; however, key derivation is very expensive
68 * array must be at least data_len + tox_pass_encryption_extra_length() bytes long. 58 * compared to the actual encryption, so clients that do a lot of encryption should
69 * key must be tox_pass_key_length() bytes. 59 * favor using the first part intead of the second part.
70 * If you already have a symmetric key from somewhere besides this module, simply
71 * call encrypt_data_symmetric in toxcore/crypto_core directly.
72 * 60 *
61 * The encrypted data is prepended with a magic number, to aid validity checking
62 * (no guarantees are made of course).
73 * 63 *
74 * returns 0 on success 64 * Clients should consider alerting their users that, unlike plain data, if even one bit
75 * returns -1 on failure 65 * becomes corrupted, the data will be entirely unrecoverable.
66 * Ditto if they forget their password, there is no way to recover the data.
67 */
68
69
70/******************************* BEGIN PART 2 *******************************
71 * For simplicty, the second part of the module is presented first. The API for
72 * the first part is analgous, with some extra functions for key handling. If
73 * your code spends too much time using these functions, consider using the part
74 * 1 functions instead.
76 */ 75 */
77int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out);
78 76
79/* Encrypts the given data with the given passphrase. The output array must be 77/* Encrypts the given data with the given passphrase. The output array must be
80 * at least data_len + tox_pass_encryption_extra_length() bytes long. This delegates 78 * at least data_len + tox_pass_encryption_extra_length() bytes long. This delegates
@@ -95,39 +93,86 @@ int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase
95 */ 93 */
96int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength); 94int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength);
97 95
98/* Save the messenger data encrypted with the given key from tox_derive_key. 96/* Decrypts the given data with the given passphrase. The output array must be
99 * data must be at least tox_encrypted_size(). 97 * at least data_len - tox_pass_encryption_extra_length() bytes long. This delegates
98 * to tox_pass_key_decrypt.
99 *
100 * tox_encrypted_load() is a good example of how to use this function.
101 *
102 * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success
103 * returns -1 on failure
104 */
105int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out);
106
107/* Load the messenger from encrypted data of size length.
100 * 108 *
101 * returns 0 on success 109 * returns 0 on success
102 * returns -1 on failure 110 * returns -1 on failure
103 */ 111 */
104int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key); 112int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength);
105 113
106/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by 114
107 * tox_derive_key_from_pass. 115/******************************* BEGIN PART 1 *******************************
116 * And now part "1", which does the actual encryption, and is rather less cpu
117 * intensive than part one. The first 3 functions are for key handling.
118 */
119
120/* Generates a secret symmetric key from the given passphrase. out_key must be at least
121 * tox_pass_key_length() bytes long.
122 * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
123 * The password is zeroed after key derivation.
124 * The key should only be used with the other functions in this module, as it
125 * includes a salt.
126 * Note that this function is not deterministic; to derive the same key from a
127 * password, you also must know the random salt that was used. See below.
108 * 128 *
109 * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success 129 * returns 0 on success
110 * returns -1 on failure 130 * returns -1 on failure
111 */ 131 */
112int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out); 132int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key);
113 133
114/* Decrypts the given data with the given passphrase. The output array must be 134/* Same as above, except with use the given salt for deterministic key derivation.
115 * at least data_len - tox_pass_encryption_extra_length() bytes long. This delegates 135 * The salt must be tox_salt_length() bytes in length.
116 * to tox_pass_key_decrypt. 136 */
137int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key);
138
139/* This retrieves the salt used to encrypt the given data, which can then be passed to
140 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted
141 * data with this module can be used as input.
117 * 142 *
118 * tox_encrypted_load() is a good example of how to use this function. 143 * returns -1 if the magic number is wrong
144 * returns 0 otherwise (no guarantee about validity of data)
145 */
146int tox_get_salt(uint8_t *data, uint8_t *salt);
147
148/* Now come the functions that are analogous to the part 2 functions. */
149
150/* Encrypt arbitrary with a key produced by tox_derive_key_. The output
151 * array must be at least data_len + tox_pass_encryption_extra_length() bytes long.
152 * key must be tox_pass_key_length() bytes.
153 * If you already have a symmetric key from somewhere besides this module, simply
154 * call encrypt_data_symmetric in toxcore/crypto_core directly.
119 * 155 *
120 * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success 156 * returns 0 on success
121 * returns -1 on failure 157 * returns -1 on failure
122 */ 158 */
123int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out); 159int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out);
124 160
125/* Load the messenger from encrypted data of size length. 161/* Save the messenger data encrypted with the given key from tox_derive_key.
162 * data must be at least tox_encrypted_size().
126 * 163 *
127 * returns 0 on success 164 * returns 0 on success
128 * returns -1 on failure 165 * returns -1 on failure
129 */ 166 */
130int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength); 167int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key);
168
169/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
170 * tox_derive_key_from_pass.
171 *
172 * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success
173 * returns -1 on failure
174 */
175int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out);
131 176
132/* Load the messenger from encrypted data of size length, with key from tox_derive_key. 177/* Load the messenger from encrypted data of size length, with key from tox_derive_key.
133 * 178 *
@@ -141,7 +186,8 @@ int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8
141 * returns 1 if it is encrypted 186 * returns 1 if it is encrypted
142 * returns 0 otherwise 187 * returns 0 otherwise
143 */ 188 */
144int tox_is_save_encrypted(const uint8_t *data); 189int tox_is_data_encrypted(const uint8_t *data);
190int tox_is_save_encrypted(const uint8_t *data); // poorly-named alias for backwards compat (oh irony...)
145 191
146#ifdef __cplusplus 192#ifdef __cplusplus
147} 193}