commit e4bb76769006c9584d3b8c4b099133bcae74e643 Author: Ignacio Rivero Date: Sun Mar 31 15:01:50 2024 -0300 Initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fe8d211 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +salty: salty.o + cc ./build/salty.o -o ./build/salty -lsodium -I. + rm ./build/salty.o + +salty.o: build + cc -c salty.c -o ./build/salty.o -lsodium -I. + +build: + mkdir -p ./build + +install: + install -m 755 ./build/salty /usr/local/bin/salty diff --git a/pawstd.h b/pawstd.h new file mode 100644 index 0000000..3810971 --- /dev/null +++ b/pawstd.h @@ -0,0 +1,86 @@ +/* + * This is free and unencumbered software released into the public domain. + * + * For more information, please refer to + */ + +//Regular text +#define BLK "\e[0;30m" +#define RED "\e[0;31m" +#define GRN "\e[0;32m" +#define YEL "\e[0;33m" +#define BLU "\e[0;34m" +#define MAG "\e[0;35m" +#define CYN "\e[0;36m" +#define WHT "\e[0;37m" + +//Regular bold text +#define BBLK "\e[1;30m" +#define BRED "\e[1;31m" +#define BGRN "\e[1;32m" +#define BYEL "\e[1;33m" +#define BBLU "\e[1;34m" +#define BMAG "\e[1;35m" +#define BCYN "\e[1;36m" +#define BWHT "\e[1;37m" + +//Regular underline text +#define UBLK "\e[4;30m" +#define URED "\e[4;31m" +#define UGRN "\e[4;32m" +#define UYEL "\e[4;33m" +#define UBLU "\e[4;34m" +#define UMAG "\e[4;35m" +#define UCYN "\e[4;36m" +#define UWHT "\e[4;37m" + +//Regular background +#define BLKB "\e[40m" +#define REDB "\e[41m" +#define GRNB "\e[42m" +#define YELB "\e[43m" +#define BLUB "\e[44m" +#define MAGB "\e[45m" +#define CYNB "\e[46m" +#define WHTB "\e[47m" + +//High intensty background +#define BLKHB "\e[0;100m" +#define REDHB "\e[0;101m" +#define GRNHB "\e[0;102m" +#define YELHB "\e[0;103m" +#define BLUHB "\e[0;104m" +#define MAGHB "\e[0;105m" +#define CYNHB "\e[0;106m" +#define WHTHB "\e[0;107m" + +//High intensty text +#define HBLK "\e[0;90m" +#define HRED "\e[0;91m" +#define HGRN "\e[0;92m" +#define HYEL "\e[0;93m" +#define HBLU "\e[0;94m" +#define HMAG "\e[0;95m" +#define HCYN "\e[0;96m" +#define HWHT "\e[0;97m" + +//Bold high intensity text +#define BHBLK "\e[1;90m" +#define BHRED "\e[1;91m" +#define BHGRN "\e[1;92m" +#define BHYEL "\e[1;93m" +#define BHBLU "\e[1;94m" +#define BHMAG "\e[1;95m" +#define BHCYN "\e[1;96m" +#define BHWHT "\e[1;97m" + +//Reset +#define reset "\e[0m" +#define CRESET "\e[0m" +#define COLOR_RESET "\e[0m" + +// Line decorations +#define ERR "[ "RED"ERR"reset" ] " +#define NOR "[ --- ] " +#define OK "[ "GRN"OK!"reset" ] " +#define DBG "[ " YEL "DBG" reset " ] " diff --git a/salty.c b/salty.c new file mode 100644 index 0000000..679afd9 --- /dev/null +++ b/salty.c @@ -0,0 +1,336 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define KEY_SIZE crypto_secretbox_KEYBYTES +#define SALT_SIZE crypto_pwhash_SALTBYTES + + +int encryptMessage(const char* inputFile, const char* outputFile, const char* password) { + // Open files + FILE *inFile = fopen(inputFile,"rb"); + FILE *outFile = fopen(outputFile,"wb"); + if (inFile == NULL || outFile == NULL) { + fprintf(stderr,ERR"Could not open files!\n"); + return 1; + } + // Variables + unsigned char salt[SALT_SIZE]; + unsigned char nonce[crypto_secretbox_NONCEBYTES]; + unsigned char key[KEY_SIZE]; + + // Read input file + + fprintf(stderr,NOR"Reading input filesize...\n"); + fseek(inFile,0,SEEK_END); + size_t inLen = ftell(inFile); + fseek(inFile,0,SEEK_SET); + fprintf(stderr,OK"File is %d bytes.\n",inLen); + unsigned char decrypted[inLen]; + + // Generate salt + randombytes_buf(salt, SALT_SIZE); + fprintf(stderr,NOR"Beginning key generation...\n"); + + // Key generation from password + if (crypto_pwhash( + key,KEY_SIZE, + password,strlen(password), + salt,crypto_pwhash_OPSLIMIT_INTERACTIVE, + crypto_pwhash_MEMLIMIT_INTERACTIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { + fprintf(stderr,ERR"Out of memory! Key could not be generated.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + fprintf(stderr,OK"Key generation successful!\n"); + fprintf(stderr,NOR"Reading file...\n"); + + // Read the input file + if(fread(decrypted,1,inLen,inFile) != inLen) { + fprintf(stderr,ERR"Error reading from file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + fprintf(stderr,OK"File read successfully!\n"); + fprintf(stderr,NOR"Beginning encryption...\n"); + + // Generate a nonce, write headers and encrypted message + randombytes_buf(nonce,sizeof(nonce)); + + if (fwrite("gneurshk",1,strlen("gneurshk"),outFile) != strlen("gneurshk")) { + fprintf(stderr,ERR"Error writing header to file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + if (fwrite(salt,1,sizeof(salt),outFile) != sizeof(salt)) { + fprintf(stderr,ERR"Error writing salt to file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + if (fwrite(nonce,1,sizeof(nonce),outFile) != sizeof(nonce)) { + fprintf(stderr,ERR"Error writing nonce to file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + fprintf(stderr,OK"Headers written!\n"); + fprintf(stderr,NOR"Writing encrypted data...\n"); + + unsigned char encrypted[inLen + crypto_secretbox_MACBYTES]; + + crypto_secretbox_easy(encrypted, decrypted, inLen, nonce, key); + + if(fwrite(encrypted,1,sizeof(encrypted),outFile) != sizeof(encrypted)) { + fprintf(stderr,ERR"Error writing encrypted data to file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + + fclose(inFile); + fclose(outFile); + +fprintf(stderr,"\n"OK"File encrypted!\n"); + + return 0; +} + +int decryptMessage(const char* inputFile, const char* outputFile, const char* password) { + // Open files + FILE *inFile = fopen(inputFile,"rb"); + FILE *outFile = fopen(outputFile,"wb"); + if (inFile == NULL || outFile == NULL) { + fprintf(stderr,ERR"Could not open files.\n"); + return 1; + } + + // Variables + unsigned char salt[SALT_SIZE]; + unsigned char nonce[crypto_secretbox_NONCEBYTES]; + unsigned char key[KEY_SIZE]; + + // Get the size of the file and assume the length of the content + fseek(inFile,0,SEEK_END); + size_t fileLen = ftell(inFile); + fseek(inFile,0,SEEK_SET); + + size_t encLen = fileLen - sizeof(salt) - sizeof(nonce) - 8; + + fprintf(stderr,DBG"Size of encrypted file: %d bytes.\n",fileLen); + fprintf(stderr,DBG"This means the encrypted content is %d bytes.\n",encLen); + + unsigned char encrypted[encLen]; + + // Verify file + unsigned char header[8]; + if (fread(header,1,sizeof(header),inFile) != sizeof(header)) { + fprintf(stderr,ERR"Error reading header from file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + if (memcmp(header,"gneurshk",sizeof(header)) != 0) { + fprintf(stderr,ERR"Invalid header.\n"); + fprintf(stderr,ERR"Make sure the input file was signed by this program!\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + fprintf(stderr,OK"Valid header! Reading the rest...\n"); + + // Read salt and nonce + if(fread(salt,1,sizeof(salt),inFile) != sizeof(salt)) { + fprintf(stderr,ERR"Error reading salt from file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + fprintf(stderr,OK"Salt retrieved.\n"); + + if(fread(nonce,1,sizeof(nonce),inFile) != sizeof(nonce)) { + fprintf(stderr,ERR"Error reading nonce from file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + fprintf(stderr,OK"Nonce retrieved.\n"); + + if(fread(encrypted,1,encLen,inFile) != encLen) { + fprintf(stderr,ERR"Error reading data from file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + fprintf(stderr,OK"Data retrieved.\n"); + fprintf(stderr,OK"Deriving key from password...\n"); + + // Key derivation + if (crypto_pwhash( + key,KEY_SIZE, + password,strlen(password), + salt,crypto_pwhash_OPSLIMIT_INTERACTIVE, + crypto_pwhash_MEMLIMIT_INTERACTIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { + fprintf(stderr,ERR"Out of memory! Key could not be generated.\n"); + return 1; + } + fprintf(stderr,OK"Key derivation successful!\n"); + fprintf(stderr,OK"Proceeding to decrypt file...\n"); + + size_t decLen = encLen - crypto_secretbox_MACBYTES; + unsigned char decrypted[decLen]; + + if (crypto_secretbox_open_easy(decrypted,encrypted,encLen,nonce,key) < 0) { + fprintf(stderr,ERR"Error decrypting file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + if (fwrite(decrypted,1,decLen,outFile) != decLen) { + fprintf(stderr,ERR"Error writing data to file.\n"); + fclose(inFile); + fclose(outFile); + return 1; + } + + fclose(inFile); + fclose(outFile); + + fprintf(stderr,"\n"OK"File decrypted!\n"); + + return 0; + +} + +bool isFile(const char* filename) { + struct stat buffer; + return (stat(filename, &buffer) == 0); +} + +int main(int argc, char *argv[]) { + fprintf(stderr,"\n- NetPaws Salty - File Encryption Program\n"); + fprintf(stderr,"- 2024 Ignacio Rivero\n"); + fprintf(stderr,"- FOR INTERNAL USE ONLY\n\n"); + // Initialize libsodium + if (sodium_init() < 0) { + fprintf(stderr,ERR"libsodium initialization failed! It is not safe to proceed.\n"); + return 1; + } + + // Handle input, output and password arguments + int in = -1, out = -1, pass = -1; + bool decrypt = false; + + int i = 1, exit = 0; + while (i < argc && exit == 0) { + if (strcmp (argv[i],"-in") == 0) { + if (i+1 >= argc) { + fprintf(stderr,ERR"Argument -in requires a file.\n"); + exit = 1; + } else if (!isFile(argv[i+1])) { + fprintf(stderr,ERR"File not found error: %s\n",argv[i+1]); + exit = 1; + } else if (in == -1) { + in = ++i; + } else { + fprintf(stderr,ERR"Too many arguments.\n"); + exit = 1; + } + } else if (strcmp(argv[i],"-out") == 0) { + if (i+1 >= argc) { + fprintf(stderr,ERR"Argument -out requires a file.\n"); + exit = 1; + } else if (strcmp(argv[i+1],"-") == 0) { + out = -2; + i++; + } else if (out == -1) { + out = ++i; + } else { + fprintf(stderr,ERR"Too many arguments.\n"); + exit = 1; + } + } else if (strcmp (argv[i],"-key") == 0) { + if (i+1 >= argc) { + fprintf(stderr,ERR"Argument -key requires a password.\n"); + exit = 1; + } else if (pass == -1) { + if (strlen(argv[i+1]) > 128) { + fprintf(stderr,ERR"Password too long."); + exit = 1; + } else { + pass = ++i; + } + } else { + fprintf(stderr,ERR"Too many arguments.\n"); + exit = 1; + } + } else if (strcmp (argv[i],"-d") == 0) { + decrypt = true; + } else { + fprintf(stderr,ERR"Invalid argument: %s\n",argv[i]); + exit = 1; + } + i++; + } + + if (exit != 0) + return exit; + + // Set input and output filenames, or go to standard I/O if none + char input[FILENAME_MAX]; + char output[FILENAME_MAX]; + char psw[129]; + + if (in == -1) { + fprintf(stderr,ERR"No input file specified.\n"); + return 1; + } else { + snprintf(input,sizeof(input),argv[in]); + } + + if (out == -1) { + fprintf(stderr,NOR"No output file, writing to stdout.\n"); + snprintf(output,sizeof(output),"/dev/stdout"); + } else if (out == -2) { + fprintf(stderr,NOR"Writing to stdout.\n"); + snprintf(output,sizeof(output),"/dev/stdout"); + } else { + snprintf(output,sizeof(output),argv[out]); + } + + char* password; + + // Set password and run! + if (pass == -1) { + password = getpass("Enter your encryption password: "); + printf(DBG"Password : %s\n",password); + } else { + password = argv[pass]; + printf(DBG"Password : %s\n",password); + } + + if (decrypt) { + return decryptMessage(input,output,password); + } else { + return encryptMessage(input,output,password); + } + +}