diff options
| author | srdusr <trevorgray@srdusr.com> | 2024-02-27 15:58:26 +0200 |
|---|---|---|
| committer | srdusr <trevorgray@srdusr.com> | 2024-02-27 15:58:26 +0200 |
| commit | dfd1d9fbdc74430e0b6ec709b4ad9c506b9fd010 (patch) | |
| tree | ad58bd6e2dc27aad771c6aac7b590bd9a10b3076 /main.c | |
| parent | eba14f7765085868785317c23483552b7be95355 (diff) | |
| download | cerberus-dfd1d9fbdc74430e0b6ec709b4ad9c506b9fd010.tar.gz cerberus-dfd1d9fbdc74430e0b6ec709b4ad9c506b9fd010.zip | |
Moved function declarations to main.h
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 349 |
1 files changed, 175 insertions, 174 deletions
@@ -1,197 +1,198 @@ -// TODO: Fix not specifying password length -// TODO: Fix not specifying password options for which characters/digits/lowercase or uppercase letters -// TODO: Fix generated encryption key must not be put in directly by user -// TODO: Use PBKDF2 for generating keys, -// TODO: Secret stored in memory must be encrypted with a key derived from the user password or consider making password manager stateless (no passwords stored locally) +// TODO: Secret stored in memory must be encrypted with a key derived from the +// user password or consider making password manager stateless (no passwords +// stored locally) // TODO: Replace CBC with GCM or CCM to prevent padding attacks // TODO: Have ascii art of a cerberus on start menu/page -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <openssl/evp.h> -#include <openssl/rand.h> -#include <openssl/aes.h> +#include "main.h" -#define MAX_PASSWORD_LENGTH 128 -#define AES_KEY_SIZE 256 / 8 - -struct Password { - char website[128]; - char username[128]; - char password[MAX_PASSWORD_LENGTH]; - char notes[256]; -}; +struct Password passwords[MAX_PASSWORDS]; +int numPasswords = 0; void generate_password(char *password, int length) { - // Generate a random password of the specified length - // using a combination of upper and lowercase letters, digits, and special characters - char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}\\|;:'\",.<>/?"; - int charset_size = strlen(charset); - - for (int i = 0; i < length; i++) { - int index = rand() % charset_size; - password[i] = charset[index]; - } - - password[length] = '\0'; -} - -void encrypt_password(struct Password *password, unsigned char *key) { - AES_KEY aes_key; - unsigned char iv[AES_BLOCK_SIZE]; - unsigned char encrypted_password[MAX_PASSWORD_LENGTH]; - - - // Generate a random initialization vector - RAND_bytes(iv, AES_BLOCK_SIZE); + // Define the character set for the password + char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456" + "789!@#$%^&*-_=+{}[]|;:',.<>/?"; + int charset_size = strlen(charset); - // Initialize the encryption key - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv); + // Seed the random number generator + srand(time(NULL)); - // Encrypt the password using AES-256 encryption - int outlen, tmplen; - EVP_EncryptUpdate(ctx, encrypted_password, &outlen, (unsigned char*)password->password, MAX_PASSWORD_LENGTH); - EVP_EncryptFinal_ex(ctx, encrypted_password + outlen, &tmplen); + for (int i = 0; i < length; i++) { + int index = rand() % charset_size; + password[i] = charset[index]; + } - // Copy the encrypted password and IV back into the password struct - memcpy(password->password, encrypted_password, AES_BLOCK_SIZE); - memcpy(password->notes, iv, AES_BLOCK_SIZE); - - // Clean up - EVP_CIPHER_CTX_free(ctx); + password[length] = '\0'; // Null-terminate the password + printf("Generated Password: %s\n", password); } -void decrypt_password(struct Password *password, unsigned char *key) { - EVP_CIPHER_CTX *ctx; - unsigned char iv[AES_BLOCK_SIZE]; - unsigned char decrypted_password[MAX_PASSWORD_LENGTH]; // change the buffer size to match the size of the password field in the struct - - // Read the initialization vector from the password struct - memcpy(iv, password->notes, AES_BLOCK_SIZE); - - // Initialize the decryption context - ctx = EVP_CIPHER_CTX_new(); - EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv); - - // Decrypt the password using AES-256 decryption - int outlen, tmplen; - EVP_DecryptUpdate(ctx, decrypted_password, &outlen, (unsigned char*)password->password, AES_BLOCK_SIZE); - EVP_DecryptFinal_ex(ctx, decrypted_password + outlen, &tmplen); - - // Copy the decrypted password back into the password struct - memcpy(password->password, decrypted_password, MAX_PASSWORD_LENGTH); - - // Clean up - EVP_CIPHER_CTX_free(ctx); +void save_password(struct Password *password, const char *dir) { + // Save the password information to a file + FILE *fp; + char filename[256]; + snprintf(filename, sizeof(filename), "%s/%s.dat", dir, password->website); + fp = fopen(filename, "wb"); + if (fp == NULL) { + printf("Error: could not open file %s for writing.\n", filename); + return; + } + + // Write the password to the file + fwrite(password, sizeof(struct Password), 1, fp); + + fclose(fp); } -void save_password(struct Password *password, char *filename, unsigned char *key) { - // Save the password information to a file in an encrypted format using AES-256 encryption - FILE *fp = fopen(filename, "wb"); - if (fp == NULL) { - printf("Error: could not open file %s for writing.\n", filename); - return; +void load_passwords(const char *dir) { + printf("Available Passwords:\n"); + DIR *d; + struct dirent *dir_entry; + d = opendir(dir); + if (d) { + int count = 0; + while ((dir_entry = readdir(d)) != NULL) { + if (dir_entry->d_type == DT_REG) { // If it's a regular file + char filename[256]; + snprintf(filename, sizeof(filename), "%s/%s", dir, dir_entry->d_name); + FILE *file = fopen(filename, "rb"); + if (file != NULL) { + struct Password password; + fread(&password, sizeof(struct Password), 1, file); + + // Null-terminate the strings + password.website[MAX_WEBSITE_LENGTH - 1] = '\0'; + password.username[MAX_USERNAME_LENGTH - 1] = '\0'; + password.password[MAX_PASSWORD_LENGTH - 1] = '\0'; + + passwords[count++] = password; + printf("%d. Website: %s, Username: %s\n", count, password.website, + password.username); + fclose(file); + } + } } - - // Encrypt the password information - encrypt_password(password, key); - - // Write the encrypted password information to the file - fwrite(password, sizeof(struct Password), 1, fp); - - fclose(fp); -} - -void load_password(struct Password *password, char *filename, unsigned char *key) { - // Load the password information from a file and decrypt it using AES-256 decryption - // Open the file for reading - FILE *file = fopen(filename, "rb"); - if (file == NULL) { - printf("Error: Could not open file %s\n", filename); - return; + numPasswords = count; + closedir(d); + if (count == 0) { + printf("No passwords found.\n"); } + } +} - // Read the encrypted password information from the file - unsigned char iv[AES_BLOCK_SIZE]; - fread(iv, 1, AES_BLOCK_SIZE, file); - unsigned char encrypted[sizeof(struct Password)]; - fread(encrypted, 1, sizeof(struct Password), file); - - // Decrypt the password information - AES_KEY aes_key; - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv); - int outlen, finallen; - EVP_DecryptUpdate(ctx, (unsigned char*)password, &outlen, encrypted, sizeof(struct Password)); - EVP_DecryptFinal_ex(ctx, ((unsigned char*)password) + outlen, &finallen); - EVP_CIPHER_CTX_free(ctx); - - // Close the file - fclose(file); +void copy_to_clipboard(char *text) { + // Use xclip command to copy text to clipboard + FILE *pipe = popen("xclip -selection clipboard", "w"); + if (pipe != NULL) { + fprintf(pipe, "%s", text); + pclose(pipe); + printf("Copied to clipboard: %s\n", text); + } else { + printf("Error: Could not copy to clipboard.\n"); + } } int main() { - int choice; - char filename[256]; - struct Password password; - unsigned char key[AES_BLOCK_SIZE]; - - // Get the encryption key from the user - printf("Enter the encryption key: "); - char key_str[AES_BLOCK_SIZE]; - printf("Enter the encryption key: "); - fgets(key_str, AES_BLOCK_SIZE, stdin); - for (int i = 0; i < AES_BLOCK_SIZE; i++) { - key[i] = (unsigned char) key_str[i]; + const char *dir = "tmp"; // Directory to store password files + mkdir(dir, 0700); // Create directory if it doesn't exist + + char user_password[MAX_PASSWORD_LENGTH]; + + FILE *key_file = fopen("master.key", "rb"); + if (key_file == NULL) { + printf("Enter your new master password: "); + fgets(user_password, sizeof(user_password), stdin); + user_password[strcspn(user_password, "\n")] = 0; // Remove newline character + + // Save master password to file + key_file = fopen("master.key", "wb"); + if (key_file == NULL) { + printf("Error: Could not create master password file.\n"); + return 1; } - - // Loop until the user chooses to exit the program - do { - // Display the menu of options to the user - printf("\n1. Generate new password\n"); - printf("2. Save password information to file\n"); - printf("3. Load password information from file\n"); - printf("4. Exit program\n\n"); - printf("Enter your choice: "); - scanf("%d", &choice); - - switch (choice) { - case 1: - // Generate a new password and display it to the user - generate_password(password.password, MAX_PASSWORD_LENGTH); - printf("New password: %s\n", password.password); - break; - case 2: - // Get the filename from the user and save the password information to a file - printf("Enter the filename to save to: "); - scanf("%s", filename); - save_password(&password, filename, key); - printf("Password information saved to %s\n", filename); - break; - case 3: - // Get the filename from the user and load the password information from a file - printf("Enter the filename to load from:"); - scanf("%s", filename); - load_password(&password, filename, key); - printf("Password information loaded from %s\n", filename); - // Display the password information to the user - printf("Website: %s\n", password.website); - printf("Username: %s\n", password.username); - printf("Password: %s\n", password.password); - printf("Notes: %s\n", password.notes); - break; - case 4: - // Exit the program - printf("Exiting program...\n"); - break; - default: - // Invalid choice - printf("Invalid choice. Please enter a number between 1 and 4.\n"); - break; + fwrite(user_password, sizeof(user_password), 1, key_file); + fclose(key_file); + } else { + // If master key exists, ask for the password + printf("Enter your master password: "); + fgets(user_password, sizeof(user_password), stdin); + user_password[strcspn(user_password, "\n")] = 0; // Remove newline character + + // Check if the entered password matches the stored master password + char stored_password[MAX_PASSWORD_LENGTH]; + fread(stored_password, sizeof(stored_password), 1, key_file); + fclose(key_file); + if (strcmp(user_password, stored_password) != 0) { + printf("Invalid master password. Exiting...\n"); + return 1; + } + } + + int choice; + while (1) { + printf("\n1. Create New Password\n"); + printf("2. Show Passwords\n"); + printf("3. Exit\n"); + printf("Enter your choice: "); + scanf("%d", &choice); + + switch (choice) { + case 1: { + if (numPasswords >= MAX_PASSWORDS) { + printf("Maximum number of passwords reached.\n"); + break; + } + struct Password password; + int length; + printf("Enter password length: "); + scanf("%d", &length); + generate_password(password.password, length); + printf("Enter website: "); + scanf("%s", password.website); + printf("Enter username: "); + scanf("%s", password.username); + save_password(&password, dir); + printf("Password information saved to %s\n", password.website); + passwords[numPasswords++] = password; + break; + } + case 2: { + load_passwords(dir); + printf("Enter the number of the password to copy (0 to cancel): "); + int selection; + scanf("%d", &selection); + if (selection > 0 && selection <= numPasswords) { + struct Password selected_password = passwords[selection - 1]; + printf("Selected Password:\n"); + printf("- Website: %s\n", selected_password.website); + printf("- Username: %s\n", selected_password.username); + printf("- Password: %s\n", selected_password.password); + printf("Copy to clipboard? (1 for Password, 2 for Username, 0 to " + "cancel): "); + int copy_choice; + scanf("%d", ©_choice); + switch (copy_choice) { + case 1: + copy_to_clipboard(selected_password.password); + break; + case 2: + copy_to_clipboard(selected_password.username); + break; + default: + printf("Canceled.\n"); } - } while (choice != 4); + } else if (selection != 0) { + printf("Invalid selection.\n"); + } + break; + } + case 3: + printf("Exiting program...\n"); + return 0; + default: + printf("Invalid choice. Please enter 1, 2, or 3.\n"); + } + } - return 0; + return 0; } |
