Вычисление ключей
Протокол Записи использует следующий алгоритм для создания ключей, инициализационных векторов и секретов МАС из параметров безопасности, создаваемых протоколом Рукопожатия.
Из мастер-секрета с использованием хэш-функций создается последовательность байтов, которая представляет собой МАС-секреты, ключи и инициализационные вектора: client write MAC secret, server write MAC secret, client write key, server write key, client write IV и server write IV. Если некоторое значение не используется, то оно является пустым.
Для создания ключа вычисляется:
key_block = PRF ( SecurityParameters.master_secret, "key expansion", SecurityParameters.server_random + SecurityParameters.client_random);
Вычисления производятся до тех пор, пока не получится выход заданной длины. Затем key_block разбивается на блоки для получения требуемых ключей следующим образом:
client_write_MAC_secret [ SecurityParameters.hash_size] server_write_MAC_secret [ SecurityParameters.hash_size] client_write_key [ SecurityParameters.key_material_length] server_write_key [ SecurityParameters.key_material_length] client_write_IV [SecurityParameters.IV_size] server_write_IV [SecurityParameters.IV_size]
client_write_IV и server_write_IV создаются только для неэкспортируемых блочных алгоритмов. Для экспортируемых блочных алгоритмов инициализационные вектора создаются другим способом. После выполнения данных вычислений вся информация о мастер-секрете и key_block сбрасывается.
Для экспортируемых алгоритмов шифрования (для которых CipherSpec.is_exportable есть true) требуется дополнительное вычисление ключей записи:
final_client_write_key = PRF (SecurityParameters.client_write_key, "client write key", SecurityParameters.client_random + SecurityParameters.server_random); final_server_write_key = PRF (SecurityParameters.server_write_key, "server write key", SecurityParameters.client_random + SecurityParameters.server_random);
Для экспортируемых алгоритмов шифрования инициализационные вектора вычисляются следующим образом:
iv_block = PRF ("", "IV block", SecurityParameters.client_random + SecurityParameters.server_random);
IV_block разделяется на два инициализационных вектора аналогично key_block:
client_write_IV [SecurityParameters.IV_size] server_write_IV [SecurityParameters.IV_size]
Заметим, что в данном случае PRF используется без секрета: это означает, что секрет имеет нулевую длину и на результат вычисления PRF не влияет.