Extra Systems

CYPHERNET

консольная система надежной коммерческой шифросвязи через сеть интернет

процедура согласования сеансовых ключей


После установки связи через центральный сервер с программой output, программа input генерирует случайный сеансовый ключ и шифрует его через RSA открытым ключом абонента, с которым ведутся переговоры. Затем input высылает ему эту шифровку, и сразу вслед за этим высылает хэш сгенерированного ключа. Аналогичные события происходят на другом конце связи в программе output.

Получив от партнера указанную информацию, input расшифровывает сеансовый ключ своим закрытым ключом RSA и проверяет совпадение хэша. Затем оба участника связи (input и output) складывают по модулю два сгенерированные ими случайные последовательности (этим занимается процедура make_common_key) и, ввиду коммутативности этой операции, получают одно и тоже значение, которое и используется далее в качестве сеансового ключа. Все эти действия выполняет процедура get_common_key, которая одинакова и в приемнике, и в передатчике.

Процедура согласования сеансовых ключей get_common_key выполняет свою работу с помощью такого алгоритма:

int get_common_key(int socket)
{
	char local_hash[HASH_SIZE], remote_hash1[HASH_SIZE], remote_hash2[HASH_SIZE];
	char socket_buffer[PACKED_VALUE_LENTH + HASH_SIZE];
	time_t start_time, end_time;
	init_hash();
	printf("Создаем защищенный канал связи...\n");
	make_local_key();
	get_hash(local_key.packed, PACKED_VALUE_LENTH / 2, local_hash);
	time(&start_time);
	printf("Шифруем свою половину ключа...\n");
	encrypt_local_key();
	memcpy(socket_buffer, crypted_local_key, PACKED_VALUE_LENTH);
	memcpy(socket_buffer + PACKED_VALUE_LENTH, local_hash, HASH_SIZE);
	socket_send_buffer(socket, socket_buffer, PACKED_VALUE_LENTH + HASH_SIZE);
	if (socket_read_buffer(socket, socket_buffer, PACKED_VALUE_LENTH + HASH_SIZE) != (PACKED_VALUE_LENTH + HASH_SIZE)) return 0;
	memcpy(crypted_remote_key, socket_buffer, PACKED_VALUE_LENTH);
	memcpy(remote_hash1, socket_buffer + PACKED_VALUE_LENTH, HASH_SIZE);
	printf("Дешифруем чужую половину ключа...\n");
	decrypt_remote_key();
	time(&end_time);
	get_hash(remote_key.packed, PACKED_VALUE_LENTH / 2, remote_hash2);
	if (memcmp(remote_hash1, remote_hash2, HASH_SIZE) != 0) return 0;
	make_common_key();
	printf("Канал связи создан за %ld сек.\n\n", (long int)(end_time - start_time));
	return 1;
}

Процедуры шифрования и расшифрования сеансового ключа encrypt_local_key и decrypt_remote_key описаны здесь.

Характерной особенностью этой процедуры является ее полная готовность использовать ключи RSA любого размера и алгоритмы хэширования любого типа. С этой целью, формируется буфер размером PACKED_VALUE_LENTH + HASH_SIZE, размер которого (переменная socket_buffer_size) пересылается в первую очередь. Это нужно для того, чтобы сервер, прочитав это значение, знал, какого именно размера пересылку между абонентами ему следует осуществить (процедура connect_server).


© Extra Systems, 2024 Extra Web Top