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
版权声明:本文标题:sockets - Error in creating Encrypted Chat server, OpenSSL (C) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741510252a2382564.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论