admin管理员组

文章数量:1291122

Been trying to create a chat server, where two users can communicate over the localhost, have used OpenSSL for encryption. Basic structure is, prestored, user id and password are given by user input at the time of implementation, server checks if they are correct, and if so allows the socket to connect. Similar to the other user as well, once both are connected the sender sends an encrypted message over the server, server reads it decrypts and sends it to the receiver. The receiver in my program is getting encrypted message. Can't figure out how to get plain text

Client Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <openssl/evp.h>

#define BUFFER_SIZE 1024
#define ENCRYPTED_BUFFER_SIZE (BUFFER_SIZE + 16) // Add extra space for padding
#define KEY_SIZE 16

void *receive_messages(void *arg);
void encrypt_decrypt(const unsigned char *input, unsigned char *output, const unsigned char *key, int encrypt);

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Usage: %s <server_ip> <port>\n", argv[0]);
        return 1;
    }

    char *server_ip = argv[1];
    int port = atoi(argv[2]);
    int sock;
    struct sockaddr_in server_addr;

    // Create socket
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("Socket creation failed");
        return 1;
    }

    // Connect to server
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Connection failed");
        close(sock);
        return 1;
    }

    // Send username
    char username[50];
    printf("Enter your username : ");
    fgets(username, sizeof(username), stdin);
    username[strcspn(username, "\n")] = '\0';
    send(sock, username, strlen(username) + 1, 0); // Include null terminator

    // Send password
    char password[50];
    printf("Enter your password: ");
    fgets(password, sizeof(password), stdin);
    password[strcspn(password, "\n")] = '\0';
    send(sock, password, strlen(password) + 1, 0); // Include null terminator

    // Start thread to receive messages
    pthread_t thread_id;
    int *socket_ptr = malloc(sizeof(int)); // Allocate memory for the socket
    if (socket_ptr == NULL) {
        perror("Failed to allocate memory for socket");
        close(sock);
        return 1;
    }
    *socket_ptr = sock; // Store the socket in the allocated memory
    pthread_create(&thread_id, NULL, receive_messages, (void *)socket_ptr);

    // Encryption key (hardcoded for simplicity)
    unsigned char key[KEY_SIZE] = {0x12, 0xAB, 0x34, 0xCD, 0x56, 0xEF, 0x78, 0x90, 0x12, 0xAB, 0x34, 0xCD, 0x56, 0xEF, 0x78, 0x90};

    // Send messages
    char buffer[BUFFER_SIZE];
    while (1) {
        printf("> ");
        fgets(buffer, sizeof(buffer), stdin);
        buffer[strcspn(buffer, "\n")] = '\0';

        if (strcmp(buffer, "EXIT") == 0) {
            unsigned char encrypted[BUFFER_SIZE];
            encrypt_decrypt((unsigned char *)buffer, encrypted, key, 1); // Encrypt the message
            send(sock, encrypted, strlen((char *)encrypted) + 1, 0); // Include null terminator
            break;
        }

        unsigned char encrypted[BUFFER_SIZE];
        encrypt_decrypt((unsigned char *)buffer, encrypted, key, 1); // Encrypt the message
        send(sock, encrypted, strlen((char *)encrypted) + 1, 0); // Include null terminator
    }

    close(sock);
    return 0;
}

void *receive_messages(void *arg) {
    int sock = *(int *)arg;
    char buffer[BUFFER_SIZE];

    // Encryption key (hardcoded for simplicity)
    unsigned char key[KEY_SIZE] = {0x12, 0xAB, 0x34, 0xCD, 0x56, 0xEF, 0x78, 0x90, 0x12, 0xAB, 0x34, 0xCD, 0x56, 0xEF, 0x78, 0x90};

    while (1) {
        memset(buffer, 0, sizeof(buffer)); // Clear the buffer
        int bytes_read = recv(sock, buffer, sizeof(buffer), 0);
        if (bytes_read <= 0) {
            printf("Disconnected from server.\n");
            break;
        }

        // Debug: Print raw received data
        printf("Raw received data: %s\n", buffer);

        // Decrypt the message
    unsigned char decrypted[BUFFER_SIZE];
    memset(decrypted, 0, sizeof(decrypted)); // Clear the buffer

    encrypt_decrypt((unsigned char *)buffer, decrypted, key, 0); // Decrypt the message
     printf("Received: %s\n", decrypted);



        // Ensure the decrypted message is null-terminated
        decrypted[bytes_read] = '\0';

        // Print the received message
   
    }

    return NULL;
}

void encrypt_decrypt(const unsigned char *input, unsigned char *output, const unsigned char *key, int encrypt) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    int len, ciphertext_len;
    int input_len = strlen((char *)input);

    // Use a fixed IV for testing (ensure the server uses the same IV)
    unsigned char iv[KEY_SIZE] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
                                  0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};

    if (!EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, encrypt)) {
        printf("Error initializing encryption/decryption.\n");
        EVP_CIPHER_CTX_free(ctx);
        return;
    }

    EVP_CIPHER_CTX_set_padding(ctx, 1);

    if (!EVP_CipherUpdate(ctx, output, &len, input, input_len)) {
        printf("Error during encryption/decryption.\n");
        EVP_CIPHER_CTX_free(ctx);
        return;
    }
    ciphertext_len = len;

    if (!EVP_CipherFinal_ex(ctx, output + len, &len)) {
        printf("Error finalizing encryption/decryption.\n");
        EVP_CIPHER_CTX_free(ctx);
        return;
    }
    ciphertext_len += len;

    output[ciphertext_len] = '\0';

    EVP_CIPHER_CTX_free(ctx);
}

Server Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <openssl/evp.h>
#include <openssl/sha.h>

#define MAX_CLIENTS 2
#define BUFFER_SIZE 1024
#define KEY_SIZE 16 // AES-128 key size

typedef struct {
    int socket;
    char username[50];
    unsigned char key[KEY_SIZE];
} Client;

Client clients[MAX_CLIENTS];
int client_count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *handle_client(void *arg);
void broadcast_message(unsigned char *message, int sender_index);
void encrypt_decrypt(const unsigned char *input, unsigned char *output, const unsigned char *key, int encrypt);
unsigned char *derive_file_key(const char *username1, const char *username2, const unsigned char *key1, const unsigned char *key2);

int main(int argc, char *argv[]) {
    if (argc != 2) {
        printf("Usage: %s <port>\n", argv[0]);
        return 1;
    }

    int port = atoi(argv[1]);
    int server_socket, new_socket;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);

    // Create server socket
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0) {
        perror("Socket creation failed");
        return 1;
    }

    // Bind server socket
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        close(server_socket);
        return 1;
    }

    // Listen for incoming connections
    if (listen(server_socket, MAX_CLIENTS) < 0) {
        perror("Listen failed");
        close(server_socket);
        return 1;
    }

    printf("Server started on port %d\n", port);

    while (1) {
        new_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_len);
        if (new_socket < 0) {
            perror("Accept failed");
            continue;
        }

        pthread_mutex_lock(&mutex);
        if (client_count >= MAX_CLIENTS) {
            printf("Maximum clients connected. Rejecting new connection.\n");
            close(new_socket);
            pthread_mutex_unlock(&mutex);
            continue;
        }

        clients[client_count].socket = new_socket;
        clients[client_count].username[0] = '\0';
        pthread_t thread_id;
        pthread_create(&thread_id, NULL, handle_client, (void *)&clients[client_count]);
        client_count++;
        pthread_mutex_unlock(&mutex);
    }

    close(server_socket);
    return 0;
}

void *handle_client(void *arg) {
    Client *client = (Client *)arg;
    char buffer[BUFFER_SIZE];
    int bytes_read;

    // Receive username
    bytes_read = recv(client->socket, buffer, sizeof(buffer), 0);
    if (bytes_read <= 0) {
        perror("Username receive failed");
        close(client->socket);
        return NULL;
    }
    buffer[bytes_read] = '\0';
    strcpy(client->username, buffer);
    printf("Client connected: %s\n", client->username);

    // Authenticate user
    FILE *db = fopen("user_db.txt", "r");
    if (!db) {
        perror("Failed to open user database");
        close(client->socket);
        return NULL;
    }

    char db_username[50], db_password[100], db_key[KEY_SIZE * 2 + 1];
    int authenticated = 0;
    while (fscanf(db, "%[^:]:%[^:]:%s\n", db_username, db_password, db_key) != EOF) {
        if (strcmp(client->username, db_username) == 0) {
            authenticated = 1;
            break;
        }
    }
    fclose(db);

    if (!authenticated) {
        printf("Invalid username: %s\n", client->username);
        close(client->socket);
        return NULL;
    }

    // Receive password
    bytes_read = recv(client->socket, buffer, sizeof(buffer), 0);
    if (bytes_read <= 0) {
        perror("Password receive failed");
        close(client->socket);
        return NULL;
    }
    buffer[bytes_read] = '\0';

    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256((unsigned char *)buffer, strlen(buffer), hash);
    char hash_str[SHA256_DIGEST_LENGTH * 2 + 1];
    for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
        sprintf(hash_str + (i * 2), "%02x", hash[i]);
    }

    if (strcmp(hash_str, db_password) != 0) {
        printf("Invalid password for user: %s\n", client->username);
        close(client->socket);
        return NULL;
    }

    // Set encryption key
    for (int i = 0; i < KEY_SIZE * 2; i += 2) {
        sscanf(db_key + i, "%2hhx", &client->key[i / 2]);
    }

    printf("User %s authenticated successfully.\n", client->username);

    while (1) {
        memset(buffer, 0, sizeof(buffer));
        bytes_read = recv(client->socket, buffer, sizeof(buffer), 0);
        if (bytes_read <= 0) {
            printf("Client %s disconnected.\n", client->username);
            break;
        }

        unsigned char decrypted[BUFFER_SIZE];
        encrypt_decrypt((unsigned char *)buffer, decrypted, client->key, 0); // Decrypt message
        decrypted[bytes_read] = '\0'; // Null-terminate the decrypted message
        printf("Received from %s: %s\n", client->username, decrypted);

        if (strncmp((char *)decrypted, "EXIT", 4) == 0) {
            break;
        }

        // Save message to file
        unsigned char *file_key = derive_file_key(clients[0].username, clients[1].username, clients[0].key, clients[1].key);
        unsigned char encrypted_file_data[BUFFER_SIZE];
        encrypt_decrypt(decrypted, encrypted_file_data, file_key, 1); // Encrypt for storage

        FILE *file = fopen("clientid1_clientid2.txt", "ab");
        if (file) {
            fwrite(encrypted_file_data, 1, strlen((char *)encrypted_file_data), file);
            fclose(file);
        }

        // Broadcast message to the other client
        broadcast_message(decrypted, client - clients);
    }

    close(client->socket);
    pthread_mutex_lock(&mutex);
    client_count--;
    pthread_mutex_unlock(&mutex);
    return NULL;
}

void broadcast_message(unsigned char *message, int sender_index) {
    pthread_mutex_lock(&mutex);
    for (int i = 0; i < MAX_CLIENTS; i++) {
        if (i != sender_index && clients[i].socket > 0) {
            unsigned char encrypted[BUFFER_SIZE];
            encrypt_decrypt(message, encrypted, clients[i].key, 1); // Encrypt for recipient
            send(clients[i].socket, encrypted, strlen((char *)encrypted) + 1, 0); // Include null terminator
            printf("MESSAGE SENT TO %s\n", clients[i].username);
        }
    }
    pthread_mutex_unlock(&mutex);
}

void encrypt_decrypt(const unsigned char *input, unsigned char *output, const unsigned char *key, int encrypt) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    int len, ciphertext_len;

    EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, key, encrypt);
    EVP_CIPHER_CTX_set_padding(ctx, 1); // Enable padding
    EVP_CipherUpdate(ctx, output, &len, input, strlen((char *)input));
    ciphertext_len = len;
    EVP_CipherFinal_ex(ctx, output + len, &len);
    ciphertext_len += len;
    output[ciphertext_len] = '\0'; // Null-terminate the output

    EVP_CIPHER_CTX_free(ctx);
}

unsigned char *derive_file_key(const char *username1, const char *username2, const unsigned char *key1, const unsigned char *key2) {
    static unsigned char file_key[KEY_SIZE]; // Static ensures the memory persists after the function returns

    if (strcmp(username1, username2) < 0) {
        memcpy(file_key, key1, KEY_SIZE / 2);
        memcpy(file_key + KEY_SIZE / 2, key2, KEY_SIZE / 2);
    } else {
        memcpy(file_key, key2, KEY_SIZE / 2);
        memcpy(file_key + KEY_SIZE / 2, key1, KEY_SIZE / 2);
    }

    return file_key; // Return the derived key
}

The following is the output that I get

User1 Received Message

Any help would be highly appreciated!!

本文标签: socketsError in creating Encrypted Chat serverOpenSSL (C)Stack Overflow