Приемник (input) служит для приема информации от абонента, с которым ведутся переговоры, и вывода полученной информации на экран консоли. В начале сеанса приемник запрашивает у пользователя его идентификатор, а также идентификатор абонента, от которого будет приниматься текстовая информация. Приемник должен иметь закрытый ключ абонента, который им пользуется и открытый ключ абонента, с которым будут вестись переговоры. В наличии также должен быть соответствующий fingerprint.
Отсылка соответствующего fingerprint на сервер (этим сервер опознает клиента и определяет, с каким именно абонентом его нужно связать) производится процедурой send_finger_print.
После установки связи через центральный сервер с программой output, программа input генерирует случайный сеансовый ключ и шифрует его через RSA открытым ключом абонента, с которым ведутся переговоры. Затем input высылает ему эту шифровку, и сразу вслед за этим высылает хэш сгенерированного ключа. Аналогичные события происходят на другом конце связи в программе output.
Получив от партнера указанную информацию, input расшифровывает сеансовый ключ своим закрытым ключом RSA и проверяет совпадение хэша. Затем оба участника связи (input и output) складывают по модулю два сгенерированные ими случайные последовательности и, ввиду коммутативности этой операции, получают одно и тоже значение, которое и используется далее в качестве сеансового ключа. Все эти действия выполняет процедура get_common_key, которая одинакова и в приемнике, и в передатчике.
После того, как сеансовый ключ таким образом сформирован, в дело вступает модуль потокового шифрования. Он экспортирует универсальные (инкапсулирующие необходимые операции независимым от выбранного алгоритма потокового шифрования способом) функции make_crypt_key_table (создание таблицы ключей), encrypt_buffer (шифрует буфер в программе input) и decrypt_buffer (дешифрует буфер в программе output).
Программа input выполняет свою работу с помощью такого алгоритма:
#include "common.h" #define STR_BUF_SIZE 4096 #define CLIENT_MODE CLIENT_MODE_INPUT int main(void) { int my_id, his_id, my_socket, buf_size, client_mode = CLIENT_MODE; char str_buf[STR_BUF_SIZE]; char public_name[64], private_name[64]; set_console_code_page(); printf ("\nКлиент консольной шифросвязи (приемник)\n(C) Extra Systems, 2024\n\n"); printf ("Укажите свой идентификатор: "); scanf("%d", &my_id); printf ("Укажите идентификатор партнера: "); scanf("%d", &his_id); printf ("\n"); sprintf(private_name, "private_%d", my_id); sprintf(public_name, "public_%d", his_id); if (!load_rsa_keys(public_name, private_name)) { printf("На диске отсутствуют нужные ключи...\n\n"); return 1; } print_crypt_params(); sockets_startup(); my_socket = create_client_socket(main_server_name, main_server_port); if (!send_finger_print(my_socket, my_id, his_id, CLIENT_MODE)) { printf("На диске отсутствует нужный fingerprint...\n\n"); return 1; } if (!get_common_key(my_socket)) { printf("Канал связи установить не удалось...\n"); return 1; } make_crypt_key_table(); while (buf_size = socket_read_buffer(my_socket, str_buf, STR_BUF_SIZE)) { str_buf[buf_size] = 0; decrypt_buffer(str_buf, buf_size); printf( "%s", str_buf); } close_socket(my_socket); sockets_cleanup(); return 0; }
© Extra Systems, 2024 |