Compare commits

..

No commits in common. "a590d1842da6073a45434b55c6a0e1dd79dd57c6" and "d3e3123373186420881fc4f42846d24489ebebfa" have entirely different histories.

4 changed files with 111 additions and 185 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
/build/

View File

@ -1,22 +1,12 @@
CC = cc salty: salty.o
CFLAGS = -Wall -Wextra -std=c99 -O2 cc ./build/salty.o -o ./build/salty -lsodium -I.
LDFLAGS = -lsodium rm ./build/salty.o
INCLUDES = -I/usr/include -I/usr/local/include -I/usr/pkg/include
LIBS = -L/usr/lib -L/usr/local/lib -L/usr/pkg/lib
BUILD_DIR = build
PREFIX = /usr/local
all: $(BUILD_DIR)/salty salty.o: build
cc -c salty.c -o ./build/salty.o -lsodium -I.
$(BUILD_DIR)/salty: salty.c pawstd.h build:
mkdir -p $(BUILD_DIR) mkdir -p ./build
$(CC) $(CFLAGS) -o $@ salty.c $(INCLUDES) $(LIBS) $(LDFLAGS)
clean:
rm -rf $(BUILD_DIR)
install: install:
install -m 755 $(BUILD_DIR)/salty /usr/local/bin/salty install -m 755 ./build/salty /usr/local/bin/salty
uninstall:
rm $(PREFIX)/bin/salty

View File

@ -84,4 +84,3 @@
#define NOR "[ --- ] " #define NOR "[ --- ] "
#define OK "[ "GRN"OK!"reset" ] " #define OK "[ "GRN"OK!"reset" ] "
#define DBG "[ " YEL "DBG" reset " ] " #define DBG "[ " YEL "DBG" reset " ] "
#define WRN "[ " YEL "WRN" reset " ] "

252
salty.c
View File

@ -1,16 +1,16 @@
#define _POSIX_C_SOURCE 200809L
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sodium.h> #include <sodium.h>
#include <termios.h> #include <pawstd.h>
#include "pawstd.h"
#define KEY_SIZE crypto_secretbox_KEYBYTES #define KEY_SIZE crypto_secretbox_KEYBYTES
#define SALT_SIZE crypto_pwhash_SALTBYTES #define SALT_SIZE crypto_pwhash_SALTBYTES
#define BUF_SIZE 1024 #define BUF_SIZE 1024
#define VER "1.00"
bool stdinput = false; bool stdinput = false;
@ -36,7 +36,7 @@ bool keyGen(const unsigned char* salt, const char* password, unsigned char* key)
return true; return true;
} }
int encryptFile(const char* inputFile, const char* outputFile, const char* password) { int encryptMessage(const char* inputFile, const char* outputFile, const char* password) {
// Generate salt // Generate salt
unsigned char salt[SALT_SIZE]; unsigned char salt[SALT_SIZE];
@ -57,47 +57,58 @@ int encryptFile(const char* inputFile, const char* outputFile, const char* passw
} }
unsigned char* decrypted; unsigned char* decrypted;
size_t decLen = 0; size_t decLen;
// Check if input is stdin, and read the input // Check if input is stdin, and read the input
if (stdinput) { if (stdinput) {
// Begin reading into buffer // Begin reading into buffer
unsigned char buffer[BUF_SIZE]; unsigned char buffer[BUF_SIZE];
size_t inputSize = 0;
unsigned char c;
unsigned char* input = malloc(BUF_SIZE); unsigned char* input = malloc(BUF_SIZE);
if (input == NULL) { if (input == NULL) {
fprintf(stderr,ERR"Memory allocation error.\n"); fprintf(stderr,ERR"Memory allocation error.");
fclose(outFile); fclose(outFile);
return 1; return 1;
} }
while(true) { int i = 0;
size_t readBytes = fread(buffer,1,BUF_SIZE,stdin); c = fgetc(stdin);
decLen += readBytes; while (feof(stdin) == 0) {
// Prevents reallocating to zero bytes. inputSize++;
if (decLen > 0) { if (i < BUF_SIZE) {
unsigned char* old = input; buffer[i] = c;
input = realloc(input, decLen); i++;
} else {
char *old = input;
input = realloc(input, inputSize);
if (input == NULL) { if (input == NULL) {
fprintf(stderr, ERR"Memory allocation error.\n"); fprintf(stderr,ERR"Memory allocation error.");
fclose(outFile); fclose(outFile);
free(old); free(old);
return 1; return 1;
} }
memcpy(input + inputSize - BUF_SIZE,buffer,BUF_SIZE);
i = 0;
} }
memcpy(input + decLen - readBytes,buffer,readBytes); c = fgetc(stdin);
if (readBytes == 0 && !ferror(stdin)) }
break; if (i > 0) {
else if (readBytes == 0 && ferror(stdin)) { char *old = input;
fprintf(stderr,ERR"Error reading from stdin.\n"); input = realloc(input, inputSize);
if (input == NULL) {
fprintf(stderr,ERR"Memory allocation error.");
fclose(outFile); fclose(outFile);
free(input); free(old);
return 1; return 1;
} }
memcpy(input + inputSize - i,buffer,i);
} }
decrypted = input; decrypted = input;
decLen = inputSize;
} else { } else {
// Open input file // Open input file
FILE *inFile = fopen(inputFile,"rb"); FILE *inFile = fopen(inputFile,"rb");
if (inFile == NULL) { if (inFile == NULL || outFile == NULL) {
fprintf(stderr,ERR"Could not open input file!\n"); fprintf(stderr,ERR"Could not open input file!\n");
return 1; return 1;
} }
@ -117,15 +128,9 @@ int encryptFile(const char* inputFile, const char* outputFile, const char* passw
fclose(inFile); fclose(inFile);
} }
if (decLen == 0) {
fprintf(stderr,ERR"No bytes read from file.\n");
fclose(outFile);
return 1;
}
size_t encLen = decLen + crypto_secretbox_MACBYTES; size_t encLen = decLen + crypto_secretbox_MACBYTES;
fprintf(stderr,OK"Input file is %zu bytes.\n",decLen); fprintf(stderr,OK"File is %d bytes.\n",decLen);
fprintf(stderr,OK"Encrypting file to %zu bytes.\n", encLen); fprintf(stderr,OK"Encoding file to %d bytes.\n", encLen);
fprintf(stderr,NOR"Beginning encryption...\n"); fprintf(stderr,NOR"Beginning encryption...\n");
// Generate a nonce, write headers and encrypted message // Generate a nonce, write headers and encrypted message
@ -133,13 +138,7 @@ int encryptFile(const char* inputFile, const char* outputFile, const char* passw
randombytes_buf(nonce,sizeof(nonce)); randombytes_buf(nonce,sizeof(nonce));
// Encrypt the data // Encrypt the data
unsigned char* encrypted = malloc(encLen); unsigned char encrypted[encLen];
if (encrypted == NULL) {
fprintf(stderr,ERR"Memory allocation error: File too large.\n");
free(decrypted);
fclose(outFile);
return 1;
}
crypto_secretbox_easy(encrypted, decrypted, decLen, nonce, key); crypto_secretbox_easy(encrypted, decrypted, decLen, nonce, key);
// Patchy but correct-ish attempt to solve annoying stdout issue // Patchy but correct-ish attempt to solve annoying stdout issue
@ -161,7 +160,7 @@ int encryptFile(const char* inputFile, const char* outputFile, const char* passw
memcpy(outputBuffer + offset, nonce, sizeof(nonce)); memcpy(outputBuffer + offset, nonce, sizeof(nonce));
offset += sizeof(nonce); offset += sizeof(nonce);
memcpy(outputBuffer + offset, encrypted, encLen); memcpy(outputBuffer + offset, encrypted, sizeof(encrypted));
fprintf(stderr,NOR"Writing encrypted data...\n"); fprintf(stderr,NOR"Writing encrypted data...\n");
@ -180,7 +179,7 @@ int encryptFile(const char* inputFile, const char* outputFile, const char* passw
return 0; return 0;
} }
int decryptFile(const char* inputFile, const char* outputFile, const char* password) { int decryptMessage(const char* inputFile, const char* outputFile, const char* password) {
// Open output file // Open output file
FILE *outFile = fopen(outputFile,"wb"); FILE *outFile = fopen(outputFile,"wb");
if (outFile == NULL) { if (outFile == NULL) {
@ -191,58 +190,65 @@ int decryptFile(const char* inputFile, const char* outputFile, const char* passw
// Variables // Variables
unsigned char salt[SALT_SIZE]; unsigned char salt[SALT_SIZE];
unsigned char nonce[crypto_secretbox_NONCEBYTES]; unsigned char nonce[crypto_secretbox_NONCEBYTES];
unsigned char* fullInput; unsigned char* fullInput;
size_t inLen = 0; size_t inLen;
// Check if input is stdin, and read the input // Check if input is stdin, and read the input
if (stdinput) { if (stdinput) {
// Begin reading into buffer // Begin reading into buffer
unsigned char buffer[BUF_SIZE]; unsigned char buffer[BUF_SIZE];
size_t inputSize = 0;
unsigned char c;
unsigned char* input = malloc(BUF_SIZE); unsigned char* input = malloc(BUF_SIZE);
if (input == NULL) { if (input == NULL) {
fprintf(stderr,ERR"Memory allocation error."); fprintf(stderr,ERR"Memory allocation error.");
fclose(outFile); fclose(outFile);
return 1; return 1;
} }
while(true) { int i = 0;
size_t readBytes = fread(buffer,1,BUF_SIZE,stdin); c = fgetc(stdin);
inLen += readBytes; while (feof(stdin) == 0) {
// Prevents reallocating to zero bytes. inputSize++;
if (inLen > 0) { if (i < BUF_SIZE) {
unsigned char* old = input; buffer[i] = c;
input = realloc(input, inLen); i++;
} else {
char *old = input;
input = realloc(input, inputSize);
if (input == NULL) { if (input == NULL) {
fprintf(stderr,ERR"Memory allocation error.\n"); fprintf(stderr,ERR"Memory allocation error.");
fclose(outFile); fclose(outFile);
free(old); free(old);
return 1; return 1;
} }
memcpy(input + inputSize - BUF_SIZE,buffer,BUF_SIZE);
i = 0;
} }
memcpy(input + inLen - readBytes,buffer,readBytes); c = fgetc(stdin);
if (readBytes == 0 && !ferror(stdin)) }
break; if (i > 0) {
else if (readBytes == 0 && ferror(stdin)) { char *old = input;
fprintf(stderr,ERR"Error reading from stdin.\n"); input = realloc(input, inputSize);
if (input == NULL) {
fprintf(stderr,ERR"Memory allocation error.");
fclose(outFile); fclose(outFile);
free(input); free(old);
return 1; return 1;
} }
memcpy(input + inputSize - i,buffer,i);
} }
fullInput = input; fullInput = input;
inLen = inputSize;
} else { } else {
FILE *inFile = fopen(inputFile,"rb"); FILE *inFile = fopen(inputFile,"rb");
// Get the size of the file and read it // Get the size of the file and read it
inLen = fileSize(inFile); size_t inputSize = fileSize(inFile);
unsigned char* input = malloc(inLen); unsigned char* input = malloc(inputSize);
if (input == NULL) {
fprintf(stderr, ERR"Memory allocation error: File too large.\n");
fclose(inFile);
fclose(outFile);
return 1;
}
if (fread(input,1,inLen,inFile) != inLen) { if (fread(input,1,inputSize,inFile) != inputSize) {
fprintf(stderr,ERR"Error reading from input file.\n"); fprintf(stderr,ERR"Error reading from input file.\n");
fclose(inFile); fclose(inFile);
fclose(outFile); fclose(outFile);
@ -251,26 +257,21 @@ int decryptFile(const char* inputFile, const char* outputFile, const char* passw
fclose(inFile); fclose(inFile);
fullInput = input; fullInput = input;
inLen = inputSize;
} }
size_t encLen = inLen - sizeof(salt) - sizeof(nonce) - 8; size_t encLen = inLen - sizeof(salt) - sizeof(nonce) - 8;
if (inLen == 0) { if (inLen == 0) {
fprintf(stderr,ERR"No bytes read from file.\n"); fprintf(stderr,ERR"File size is 0. No data.");
fclose(outFile); fclose(outFile);
return 1; return 1;
} }
fprintf(stderr,OK"Size of input file: %zu bytes.\n",inLen); fprintf(stderr,DBG"Size of encrypted file: %d bytes.\n",inLen);
fprintf(stderr,OK"Encrypted content is %zu bytes.\n",encLen); fprintf(stderr,DBG"This means the encrypted content is %d bytes.\n",encLen);
unsigned char* encrypted = malloc(encLen); unsigned char encrypted[encLen];
if (encrypted == NULL) {
fprintf(stderr,ERR"Memory allocation error.");
free(fullInput);
fclose(outFile);
return 1;
}
// Verify file // Verify file
size_t offset = 0; size_t offset = 0;
@ -291,17 +292,15 @@ int decryptFile(const char* inputFile, const char* outputFile, const char* passw
memcpy(nonce, fullInput + offset, sizeof(nonce)); memcpy(nonce, fullInput + offset, sizeof(nonce));
offset += sizeof(nonce); offset += sizeof(nonce);
memcpy(encrypted, fullInput + offset, encLen); memcpy(encrypted, fullInput + offset, sizeof(encrypted));
fprintf(stderr,OK"Data retrieved.\n"); fprintf(stderr,OK"Data retrieved.\n");
free(fullInput);
// Key // Key
unsigned char key[KEY_SIZE]; unsigned char key[KEY_SIZE];
if (!keyGen(salt,password,key)) { if (!keyGen(salt,password,key)) {
free(encrypted); free(fullInput);
fclose(outFile); fclose(outFile);
return 1; return 1;
} }
@ -309,25 +308,24 @@ int decryptFile(const char* inputFile, const char* outputFile, const char* passw
fprintf(stderr,OK"Proceeding to decrypt file...\n"); fprintf(stderr,OK"Proceeding to decrypt file...\n");
size_t decLen = encLen - crypto_secretbox_MACBYTES; size_t decLen = encLen - crypto_secretbox_MACBYTES;
unsigned char* decrypted = malloc(decLen); unsigned char decrypted[decLen];
if (crypto_secretbox_open_easy(decrypted,encrypted,encLen,nonce,key) < 0) { if (crypto_secretbox_open_easy(decrypted,encrypted,encLen,nonce,key) < 0) {
fprintf(stderr,ERR"Error decrypting file.\n"); fprintf(stderr,ERR"Error decrypting file.\n");
free(encrypted); free(fullInput);
fclose(outFile); fclose(outFile);
return 1; return 1;
} }
if (fwrite(decrypted,1,decLen,outFile) != decLen) { if (fwrite(decrypted,1,decLen,outFile) != decLen) {
fprintf(stderr,ERR"Error writing data to file.\n"); fprintf(stderr,ERR"Error writing data to file.\n");
free(encrypted); free(fullInput);
fclose(outFile); fclose(outFile);
return 1; return 1;
} }
fclose(outFile); fclose(outFile);
free(encrypted); free(fullInput);
free(decrypted);
fprintf(stderr,"\n"OK"File decrypted!\n"); fprintf(stderr,"\n"OK"File decrypted!\n");
@ -339,65 +337,22 @@ bool isFile(const char* filename) {
return (stat(filename, &buffer) == 0); return (stat(filename, &buffer) == 0);
} }
bool getPassword(char *pw, int size) {
struct termios term;
tcgetattr(fileno(stdin), &term);
int i = 0;
char c;
pw[0] = '\0';
// Hide input
term.c_lflag &= ~ECHO;
tcsetattr(fileno(stdin), 0, &term);
// Get password from stdin
while (true) {
c = fgetc(stdin);
if (c == '\r' || c == '\n' || feof(stdin)) {
break;
}
// Return false on excess characters
if (i < size - 1) {
pw[i] = c;
pw[i + 1] = '\0';
} else
return false;
i++;
}
// Show input
term.c_lflag |= ECHO;
tcsetattr(fileno(stdin), 0, &term);
return true;
}
void printUsage() {
fprintf(stderr,"\nUsage: salty [-d] -in [INPUT] -out [OUTPUT] [OPTIONS]\n");
fprintf(stderr,"Encrypts or decrypts a file with a password. When INPUT or OUTPUT are not set,\n");
fprintf(stderr,"or set to -, standard input or output is used respectively.\n\n");
fprintf(stderr,"Options:\n");
fprintf(stderr," -in\t\tTakes an input file\n");
fprintf(stderr," -out\tTakes an output file\n");
fprintf(stderr," -d\t\tEnable decryption mode\n");
fprintf(stderr," -key\tTakes a password, needed if reading from stdin\n");
fprintf(stderr," \t\tOtherwise this password is read from stdin itself\n");
fprintf(stderr," -v\t\tDisplays version information and exits\n");
fprintf(stderr," -h\t\tDisplays this help and exits\n");
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
setvbuf(stdout, NULL, _IONBF, 0); fprintf(stderr,"\n- NetPaws Salty - File Encryption Program\n");
fprintf(stderr,NOR"NetPaws Salty - File Encryption Program\n"); fprintf(stderr,"- 2024 Ignacio Rivero\n");
fprintf(stderr,NOR"2024 Ignacio Rivero\n"); fprintf(stderr,"- FOR INTERNAL USE ONLY\n\n");
// Initialize libsodium // Initialize libsodium
if (sodium_init() < 0) { if (sodium_init() < 0) {
fprintf(stderr,ERR"libsodium initialization failed! It is not safe to proceed.\n"); fprintf(stderr,ERR"libsodium initialization failed! It is not safe to proceed.\n");
return 1; return 1;
} }
// Handle input, output, password, and other arguments // Handle input, output and password arguments
int in = -1, out = -1, pass = -1; int in = -1, out = -1, pass = -1;
bool decrypt = false; bool decrypt = false;
int i = 1, exit = -1; int i = 1, exit = 0;
while (i < argc && exit == -1) { while (i < argc && exit == 0) {
if (strcmp (argv[i],"-in") == 0) { if (strcmp (argv[i],"-in") == 0) {
if (i+1 >= argc) { if (i+1 >= argc) {
fprintf(stderr,ERR"Argument -in requires a file.\n"); fprintf(stderr,ERR"Argument -in requires a file.\n");
@ -433,7 +388,7 @@ int main(int argc, char *argv[]) {
exit = 1; exit = 1;
} else if (pass == -1) { } else if (pass == -1) {
if (strlen(argv[i+1]) > 128) { if (strlen(argv[i+1]) > 128) {
fprintf(stderr,ERR"Password is too long."); fprintf(stderr,ERR"Password too long.");
exit = 1; exit = 1;
} else { } else {
pass = ++i; pass = ++i;
@ -444,13 +399,6 @@ int main(int argc, char *argv[]) {
} }
} else if (strcmp (argv[i],"-d") == 0) { } else if (strcmp (argv[i],"-d") == 0) {
decrypt = true; decrypt = true;
} else if (strcmp (argv[i],"-v") == 0) {
fprintf(stderr,NOR"Version %s\n",VER);
exit = 0;
} else if (strcmp (argv[i],"-h") == 0) {
fprintf(stderr,NOR"Version %s\n",VER);
printUsage();
exit = 0;
} else { } else {
fprintf(stderr,ERR"Invalid argument: %s\n",argv[i]); fprintf(stderr,ERR"Invalid argument: %s\n",argv[i]);
exit = 1; exit = 1;
@ -458,17 +406,13 @@ int main(int argc, char *argv[]) {
i++; i++;
} }
if (exit == 1) { if (exit != 0)
printUsage();
return exit; return exit;
} else if (exit != -1)
return exit;
fprintf(stderr,"\n");
// Set input and output filenames, or go to standard I/O if none // Set input and output filenames, or go to standard I/O if none
char input[FILENAME_MAX]; char input[FILENAME_MAX];
char output[FILENAME_MAX]; char output[FILENAME_MAX];
char psw[129];
if (in == -1) { if (in == -1) {
fprintf(stderr,NOR"No input file, reading from stdin.\n"); fprintf(stderr,NOR"No input file, reading from stdin.\n");
@ -477,7 +421,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr,NOR"Reading from stdin.\n"); fprintf(stderr,NOR"Reading from stdin.\n");
stdinput = true; stdinput = true;
} else { } else {
snprintf(input,sizeof(input),"%s", argv[in]); snprintf(input,sizeof(input),argv[in]);
} }
if (out == -1) { if (out == -1) {
@ -487,7 +431,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr,NOR"Writing to stdout.\n"); fprintf(stderr,NOR"Writing to stdout.\n");
snprintf(output,sizeof(output),"/dev/stdout"); snprintf(output,sizeof(output),"/dev/stdout");
} else { } else {
snprintf(output,sizeof(output),"%s", argv[out]); snprintf(output,sizeof(output),argv[out]);
} }
char* password; char* password;
@ -496,21 +440,15 @@ int main(int argc, char *argv[]) {
if (pass > 0) { if (pass > 0) {
password = argv[pass]; password = argv[pass];
} else if (in < 0) { } else if (in < 0) {
fprintf(stderr, ERR"Cannot read from stdin without a password.\n"); fprintf(stderr,ERR"Cannot read from stdin without a password.\n");
return 1; return 1;
} else { } else {
password = malloc(129); password = getpass("Enter your encryption password: ");
printf(NOR"Enter your encryption password: ");
if (!getPassword(password,130)) {
fprintf(stderr,"\n"ERR"Password is too long.");
return 1;
}
printf("\n");
} }
if (decrypt) { if (decrypt) {
return decryptFile(input, output, password); return decryptMessage(input,output,password);
} else { } else {
return encryptFile(input, output, password); return encryptMessage(input,output,password);
} }
} }