Added the program
This commit is contained in:
parent
7e72eb7557
commit
7022bfdf12
274
password_manager.c
Normal file
274
password_manager.c
Normal file
@ -0,0 +1,274 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/err.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SALT_SIZE 16
|
||||
#define IV_SIZE 16
|
||||
#define BLOCK_SIZE 16
|
||||
#define KEY_SIZE 32
|
||||
#define MAX_CIPHERTEXT_LENGTH 256
|
||||
|
||||
const char *defaultCharSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()-_=+[]{};:,.<>?/\\|";
|
||||
const char *noSymbolsCharSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
int passwordLength = 16;
|
||||
int useSymbols = 1;
|
||||
char masterPassword[256]; // Master password for encryption
|
||||
|
||||
void getMasterPassword(char *password) {
|
||||
struct termios oldt, newt;
|
||||
printf("Enter master password: ");
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
fgets(password, sizeof(masterPassword), stdin);
|
||||
password[strcspn(password, "\n")] = '\0';
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void printHelp() {
|
||||
printf("Password Manager Usage:\n");
|
||||
printf(" --add SERVICE --username USERNAME [--password PASSWORD] Add a new service with optional password (randomly generated if not provided)\n");
|
||||
printf(" --get SERVICE Retrieve the username and password for a given service\n");
|
||||
printf(" --list List all services stored in the vault\n");
|
||||
printf(" --length LENGTH Specify the length of generated passwords (default: 16)\n");
|
||||
printf(" --no-symbols Generate passwords without symbols\n");
|
||||
printf(" --help Display this help message\n");
|
||||
}
|
||||
|
||||
void parseArgs(int argc, char **argv, char **operation, char **service, char **username, char **password) {
|
||||
int c;
|
||||
while (1) {
|
||||
static struct option long_options[] = {
|
||||
{"length", required_argument, 0, 'l'},
|
||||
{"no-symbols", no_argument, 0, 'n'},
|
||||
{"add", required_argument, 0, 'a'},
|
||||
{"get", required_argument, 0, 'g'},
|
||||
{"list", no_argument, 0, 'L'},
|
||||
{"username", required_argument, 0, 'u'},
|
||||
{"password", required_argument, 0, 'p'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "l:na:g:L:u:p:h", long_options, NULL);
|
||||
if (c == -1) break;
|
||||
|
||||
switch (c) {
|
||||
case 'l':
|
||||
passwordLength = atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
useSymbols = 0;
|
||||
break;
|
||||
case 'a':
|
||||
*operation = "add";
|
||||
*service = optarg;
|
||||
break;
|
||||
case 'g':
|
||||
*operation = "get";
|
||||
*service = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
*operation = "list";
|
||||
break;
|
||||
case 'u':
|
||||
*username = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
*password = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
printHelp();
|
||||
exit(0);
|
||||
default:
|
||||
printf("Invalid option %c\n", c);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generatePassword(char *password) {
|
||||
const char *charSet = useSymbols ? defaultCharSet : noSymbolsCharSet;
|
||||
for (int i = 0; i < passwordLength; ++i) {
|
||||
unsigned char randomByte;
|
||||
RAND_bytes(&randomByte, sizeof(randomByte));
|
||||
int randomIndex = randomByte % (int)strlen(charSet);
|
||||
password[i] = charSet[randomIndex];
|
||||
}
|
||||
password[passwordLength] = '\0';
|
||||
}
|
||||
|
||||
void handleErrors() {
|
||||
ERR_print_errors_fp(stderr);
|
||||
abort();
|
||||
}
|
||||
|
||||
void deriveKey(unsigned char *key, unsigned char *salt) {
|
||||
if (!PKCS5_PBKDF2_HMAC(masterPassword, strlen(masterPassword), salt, SALT_SIZE, 10000, EVP_sha256(), KEY_SIZE, key)) {
|
||||
handleErrors();
|
||||
}
|
||||
}
|
||||
|
||||
void encryptPassword(const char *plaintext, unsigned char *ciphertext, unsigned char *salt, int *ciphertext_len) {
|
||||
unsigned char key[KEY_SIZE], iv[IV_SIZE];
|
||||
deriveKey(key, salt);
|
||||
|
||||
// Generate random IV
|
||||
RAND_bytes(iv, sizeof(iv));
|
||||
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
int len;
|
||||
|
||||
// Prepend salt and IV to the ciphertext
|
||||
memcpy(ciphertext, salt, SALT_SIZE);
|
||||
memcpy(ciphertext + SALT_SIZE, iv, IV_SIZE);
|
||||
|
||||
if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors();
|
||||
|
||||
if (!EVP_EncryptUpdate(ctx, ciphertext + SALT_SIZE + IV_SIZE, &len, (unsigned char *)plaintext, strlen(plaintext))) handleErrors();
|
||||
*ciphertext_len = len;
|
||||
|
||||
if (!EVP_EncryptFinal_ex(ctx, ciphertext + SALT_SIZE + IV_SIZE + len, &len)) handleErrors();
|
||||
*ciphertext_len += len;
|
||||
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
}
|
||||
|
||||
void decryptPassword(const unsigned char *ciphertext, char *plaintext, int ciphertext_len) {
|
||||
unsigned char key[KEY_SIZE], iv[IV_SIZE], salt[SALT_SIZE];
|
||||
memcpy(salt, ciphertext, SALT_SIZE);
|
||||
memcpy(iv, ciphertext + SALT_SIZE, IV_SIZE);
|
||||
|
||||
deriveKey(key, salt);
|
||||
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
int len, plaintext_len;
|
||||
|
||||
if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) handleErrors();
|
||||
|
||||
if (!EVP_DecryptUpdate(ctx, (unsigned char *)plaintext, &len, ciphertext + SALT_SIZE + IV_SIZE, ciphertext_len - SALT_SIZE - IV_SIZE)) handleErrors();
|
||||
plaintext_len = len;
|
||||
|
||||
if (!EVP_DecryptFinal_ex(ctx, (unsigned char *)plaintext + len, &len)) handleErrors();
|
||||
plaintext_len += len;
|
||||
plaintext[plaintext_len] = '\0';
|
||||
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
}
|
||||
|
||||
void savePassword(const char *service, const char *username, const char *password) {
|
||||
FILE *vault = fopen("vault.csv", "a");
|
||||
if (!vault) {
|
||||
printf("Error opening vault file.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char ciphertext[MAX_CIPHERTEXT_LENGTH];
|
||||
int ciphertext_len;
|
||||
unsigned char salt[SALT_SIZE];
|
||||
RAND_bytes(salt, sizeof(salt));
|
||||
|
||||
encryptPassword(password, ciphertext, salt, &ciphertext_len);
|
||||
|
||||
// Convert to hex string for storage
|
||||
char hexCiphertext[MAX_CIPHERTEXT_LENGTH * 2 + 1]; // Enough space for hex representation
|
||||
for (int i = 0; i < ciphertext_len + SALT_SIZE + IV_SIZE; i++) {
|
||||
sprintf(hexCiphertext + i * 2, "%02x", ciphertext[i]);
|
||||
}
|
||||
|
||||
fprintf(vault, "%s,%s,%s\n", service, username, hexCiphertext);
|
||||
fclose(vault);
|
||||
}
|
||||
|
||||
void getPassword(const char *service) {
|
||||
FILE *vault = fopen("vault.csv", "r");
|
||||
if (!vault) {
|
||||
printf("Error opening vault file.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char line[512];
|
||||
while (fgets(line, sizeof(line), vault)) {
|
||||
char *storedService = strtok(line, ",");
|
||||
char *storedUsername = strtok(NULL, ",");
|
||||
char *encryptedPassword = strtok(NULL, "\n");
|
||||
|
||||
if (strcmp(service, storedService) == 0) {
|
||||
unsigned char ciphertext[MAX_CIPHERTEXT_LENGTH];
|
||||
int ciphertext_len = strlen(encryptedPassword) / 2; // Each byte is represented by 2 hex characters
|
||||
for (int i = 0; i < ciphertext_len; i++) {
|
||||
sscanf(encryptedPassword + 2 * i, "%2hhx", &ciphertext[i]);
|
||||
}
|
||||
|
||||
char decryptedPassword[MAX_CIPHERTEXT_LENGTH];
|
||||
decryptPassword(ciphertext, decryptedPassword, ciphertext_len);
|
||||
printf("Service: %s\nUsername: %s\nPassword: %s\n", storedService, storedUsername, decryptedPassword);
|
||||
fclose(vault);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Service not found.\n");
|
||||
fclose(vault);
|
||||
}
|
||||
|
||||
void listServices() {
|
||||
FILE *vault = fopen("vault.csv", "r");
|
||||
if (!vault) {
|
||||
printf("Error opening vault file.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Services in the vault:\n");
|
||||
char line[512];
|
||||
while (fgets(line, sizeof(line), vault)) {
|
||||
char *storedService = strtok(line, ",");
|
||||
// Check if storedService exists
|
||||
if (storedService != NULL) {
|
||||
printf("%s\n", storedService);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(vault);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char *operation = NULL;
|
||||
char *service = NULL;
|
||||
char *username = NULL;
|
||||
char *password = NULL;
|
||||
|
||||
parseArgs(argc, argv, &operation, &service, &username, &password);
|
||||
getMasterPassword(masterPassword); // Get the master password
|
||||
|
||||
if (operation != NULL) {
|
||||
if (strcmp(operation, "add") == 0) {
|
||||
char generatedPassword[256];
|
||||
if (password == NULL) {
|
||||
generatePassword(generatedPassword);
|
||||
savePassword(service, username, generatedPassword);
|
||||
} else {
|
||||
savePassword(service, username, password);
|
||||
}
|
||||
} else if (strcmp(operation, "get") == 0) {
|
||||
getPassword(service);
|
||||
} else if (strcmp(operation, "list") == 0) {
|
||||
listServices();
|
||||
}
|
||||
} else {
|
||||
printf("No valid operation specified.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user