diff options
-rw-r--r-- | INSTALL.md | 18 | ||||
-rw-r--r-- | auto_tests/encryptsave_test.c | 10 | ||||
-rw-r--r-- | toxencryptsave/toxencryptsave.c | 94 | ||||
-rw-r--r-- | toxencryptsave/toxencryptsave.h | 136 |
4 files changed, 165 insertions, 93 deletions
@@ -59,10 +59,10 @@ You should get and install [libsodium](https://github.com/jedisct1/libsodium): | |||
59 | ```bash | 59 | ```bash |
60 | git clone git://github.com/jedisct1/libsodium.git | 60 | git clone git://github.com/jedisct1/libsodium.git |
61 | cd libsodium | 61 | cd libsodium |
62 | git checkout tags/0.7.0 | 62 | git checkout tags/1.0.0 |
63 | ./autogen.sh | 63 | ./autogen.sh |
64 | ./configure && make check | 64 | ./configure && make check |
65 | sudo checkinstall --install --pkgname libsodium --pkgversion 0.7.0 --nodoc | 65 | sudo checkinstall --install --pkgname libsodium --pkgversion 1.0.0 --nodoc |
66 | sudo ldconfig | 66 | sudo ldconfig |
67 | cd .. | 67 | cd .. |
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 |
75 | git clone git://github.com/jedisct1/libsodium.git | 75 | git clone git://github.com/jedisct1/libsodium.git |
76 | cd libsodium | 76 | cd libsodium |
77 | git checkout tags/0.7.0 | 77 | git checkout tags/1.0.0 |
78 | ./autogen.sh | 78 | ./autogen.sh |
79 | ./configure | 79 | ./configure |
80 | make check | 80 | make check |
@@ -137,7 +137,7 @@ brew list libsodium | |||
137 | 137 | ||
138 | Configure include and lib folder and build again: | 138 | Configure 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/ |
141 | make | 141 | make |
142 | make install | 142 | make install |
143 | ``` | 143 | ``` |
@@ -354,7 +354,7 @@ Now we will build sodium crypto library: | |||
354 | ```bash | 354 | ```bash |
355 | git clone https://github.com/jedisct1/libsodium/ | 355 | git clone https://github.com/jedisct1/libsodium/ |
356 | cd libsodium | 356 | cd libsodium |
357 | git checkout tags/0.7.0 | 357 | git 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 |
360 | make | 360 | make |
@@ -409,10 +409,10 @@ When installing MinGW, make sure to select the MSYS option in the installer. | |||
409 | MinGW 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. | 409 | MinGW 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 | ||
411 | First download the source tarball from https://download.libsodium.org/libsodium/releases/ and build it. | 411 | First download the source tarball from https://download.libsodium.org/libsodium/releases/ and build it. |
412 | Assuming that you got the libsodium-0.7.0.tar.gz release: | 412 | Assuming that you got the libsodium-1.0.0.tar.gz release: |
413 | ```cmd | 413 | ```cmd |
414 | tar -zxvf libsodium-0.7.0.tar.gz | 414 | tar -zxvf libsodium-1.0.0.tar.gz |
415 | cd libsodium-0.7.0 | 415 | cd libsodium-1.0.0 |
416 | ./configure | 416 | ./configure |
417 | make | 417 | make |
418 | make install | 418 | make install |
@@ -536,7 +536,7 @@ OS X homebrew: | |||
536 | brew install libconfig | 536 | brew install libconfig |
537 | ``` | 537 | ``` |
538 | OS X non-homebrew: | 538 | OS X non-homebrew: |
539 | Grab the following [package] (http://www.hyperrealm.com/libconfig/), uncompress and install | 539 | Grab the following [package](http://www.hyperrealm.com/libconfig/), uncompress and install |
540 | 540 | ||
541 | See this [readme](other/bootstrap_daemon/README.md) on how to set up the bootstrap daemon. | 541 | See 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 | } |
149 | END_TEST | 155 | END_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 | ||
43 | int tox_pass_encryption_extra_length() | 43 | int 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 | ||
53 | int 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). */ |
60 | uint32_t tox_encrypted_size(const Tox *tox) | 65 | uint32_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 | */ | ||
77 | int 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 | */ |
77 | int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) | 99 | int 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 | */ | ||
109 | int 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 | */ |
212 | int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) | 237 | int 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 | */ |
242 | int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) | 270 | int 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 | */ |
273 | int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) | 300 | int 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 | */ |
296 | int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key) | 317 | int 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 | */ |
319 | int tox_is_save_encrypted(const uint8_t *data) | 334 | int 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 | |||
342 | int 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" { | |||
35 | typedef struct Tox Tox; | 35 | typedef 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... |
40 | int tox_pass_encryption_extra_length(); | 40 | int tox_pass_encryption_extra_length(); |
41 | 41 | ||
42 | int tox_pass_key_length(); | 42 | int tox_pass_key_length(); |
43 | 43 | ||
44 | /* This "module" provides functions analogous to tox_load and tox_save in toxcore | 44 | int 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). */ |
51 | uint32_t tox_encrypted_size(const Tox *tox); | 47 | uint32_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 |
65 | int 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 | */ |
77 | int 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 | */ |
96 | int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength); | 94 | int 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 | */ | ||
105 | int 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 | */ |
104 | int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key); | 112 | int 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 | */ |
112 | int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out); | 132 | int 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 | */ |
137 | int 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 | */ | ||
146 | int 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 | */ |
123 | int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out); | 159 | int 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 | */ |
130 | int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength); | 167 | int 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 | */ | ||
175 | int 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 | */ |
144 | int tox_is_save_encrypted(const uint8_t *data); | 189 | int tox_is_data_encrypted(const uint8_t *data); |
190 | int 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 | } |