summaryrefslogtreecommitdiff
path: root/src/encryption.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/encryption.c')
-rw-r--r--src/encryption.c96
1 files changed, 92 insertions, 4 deletions
diff --git a/src/encryption.c b/src/encryption.c
index 692b46a..100b50f 100644
--- a/src/encryption.c
+++ b/src/encryption.c
@@ -179,7 +179,7 @@ int main(void) {
179 free(password); 179 free(password);
180 //*/// 180 //*///
181 181
182 //*// Example code for generating a password, derriving a secret key from it, and storing things properly 182 /*// Example code for generating a password, derriving a secret key from it, and storing things properly
183 183
184 // Initialization 184 // Initialization
185 checksodium(); 185 checksodium();
@@ -195,9 +195,9 @@ int main(void) {
195 // Store the password 195 // Store the password
196 if(crypto_pwhash_str(hpass, pass, strlen(pass) + 1, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0) 196 if(crypto_pwhash_str(hpass, pass, strlen(pass) + 1, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE) != 0)
197 error(1, errno, "Couldn't generate password, quitting..."); 197 error(1, errno, "Couldn't generate password, quitting...");
198 /* Don't know if I want to use MODERATE or SENSITIVE for this. SENSITIVE takes a little bit on my laptop, which honestly 198 // Don't know if I want to use MODERATE or SENSITIVE for this. SENSITIVE takes a little bit on my laptop, which honestly
199 // shouldn't be a problem, but it annoys me. MODERATE is quick and snappy, or at least quick enough that the slowdown is 199 // shouldn't be a problem, but it annoys me. MODERATE is quick and snappy, or at least quick enough that the slowdown is
200 // barely noticable. I might do MODERATE for testing and SENSITIVE for release */ 200 // barely noticable. I might do MODERATE for testing and SENSITIVE for release
201 201
202 sodium_munlock(pass, strlen(pass) + 1); 202 sodium_munlock(pass, strlen(pass) + 1);
203 free(pass); 203 free(pass);
@@ -206,7 +206,7 @@ int main(void) {
206 206
207 // Check if the password from the user is correct 207 // Check if the password from the user is correct
208 char *uin = NULL; int size = -1; 208 char *uin = NULL; int size = -1;
209 if((size = readwholebuffer(&uin, 20, STDIN_FILENO)) < 0) 209 if((size = readwholebuffer(&uin, 1, STDIN_FILENO)) < 0)
210 error(1, errno, "Could not read from stdin"); 210 error(1, errno, "Could not read from stdin");
211 sodium_mlock(uin, size); 211 sodium_mlock(uin, size);
212 212
@@ -218,6 +218,94 @@ int main(void) {
218 218
219 //*/// 219 //*///
220 220
221 //*// Example code for generating a key from a password and encrypting a test file
222
223 const char *dir = ".", *fname = "toBeEncrypted.test.txt", *pass = "this is a password";
224 char *path = NULL, *message = NULL, *efname = NULL;
225 int fd = -1;
226
227 // Message is just going to be a bunch of words from the dictionary
228 checksodium();
229 if(genpassword(&message, 1000) < 0)
230 error(1, errno, "Could not generate message to be encrypted");
231 if(!message)
232 abort();
233
234 // Get the temp file and write the message into it
235 if((fd = maketmp(dir)) < 0)
236 error(1, errno, "Could not make temp file to write to");
237
238 // Write to the file and link it into the system
239 remove(fname); // Make sure the new file can be linked into
240 write(fd, message, strlen(message));
241 asprintf(&path, "/proc/self/fd/%d", fd);
242 if(!path)
243 abort();
244 linkat(AT_FDCWD, path, AT_FDCWD, fname, AT_SYMLINK_FOLLOW);
245
246 free(path);
247 free(message);
248 close(fd);
249
250
251 // Time for encryption
252 unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
253 unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES];
254 crypto_secretstream_xchacha20poly1305_state state;
255 unsigned char salt[crypto_pwhash_SALTBYTES];
256
257 // Generate a salt for derriving the key
258 randombytes_buf(salt, sizeof(salt));
259
260 // Derrive the key from the password
261 if(crypto_pwhash(key, sizeof(key), pass, strlen(pass), salt, crypto_pwhash_OPSLIMIT_MODERATE, crypto_pwhash_MEMLIMIT_MODERATE, crypto_pwhash_ALG_DEFAULT) != 0)
262 error(1, ENOMEM, "Not enough memory to generate a key");
263
264 // Initialize the encryption stream's state
265 crypto_secretstream_xchacha20poly1305_init_push(&state, header, key);
266
267
268 // Deal with getting the file
269 if((fd = open(fname, O_RDONLY)) < 0)
270 error(1, errno, "Could not open test file to encrypt");
271 int tfd = -1;
272 if((tfd = maketmp(dir)) < 0) // Only because linking temp files is being annoying
273 error(1, errno, "Could not open temp file for encryption");
274
275 struct stat sb;
276 if(fstat(fd, &sb) < 0)
277 error(1, errno, "stat() error");
278
279 // Read chunks of the file, encrypt them, then write them into the tmp file
280 ssize_t bytesread = -1;
281 unsigned char *buf = xcalloc(sb.st_blksize + 1, sizeof(*buf));
282 unsigned char *cbuf = xcalloc((sb.st_blksize + 1) + crypto_secretstream_xchacha20poly1305_ABYTES, sizeof(*buf));
283 while((bytesread = read(fd, buf, sb.st_blksize)) >= 0) {
284 crypto_secretstream_xchacha20poly1305_push(&state, cbuf, NULL, buf, bytesread, NULL, 0, (bytesread > 0) ? 0 : crypto_secretstream_xchacha20poly1305_TAG_FINAL);
285 if(writewholebuffer(tfd, cbuf, bytesread) < 0)
286 error(1, errno, "write() error");
287
288 if(bytesread == 0)
289 break;
290 }
291 if(bytesread < 0)
292 error(1, errno, "read() error");
293
294 close(fd);
295
296 asprintf(&efname, "%s.enc", fname);
297 asprintf(&path, "/proc/self/fd/%d", tfd);
298 if(!path || !efname)
299 abort();
300 remove(efname); // Make sure an old version isn't sticking around
301 linkat(AT_FDCWD, path, AT_FDCWD, efname, AT_SYMLINK_FOLLOW);
302
303 close(tfd);
304 free(path);
305 free(efname);
306
307 //*///
308
221 return 0; 309 return 0;
222} 310}
223 311