Глава 8. Безопасный канал общения
ключ все равно следует периодически изменять
1
. При необходимости вы, ко-
нечно, можете использовать 40- или 48-битовые номера сообщений; особого
значения это не имеет.
Почему мы начинаем нумеровать сообщения с единицы, если в языке C
нумерацию принято начинать с нуля? Это небольшая хитрость реализации.
Если сообщениям могут быть присвоены
N
номеров, пользователям А и Б
придется отслеживать
N
+ 1
состояний. Действительно, ведь тогда количе-
ство отосланных сообщений может принимать любое значение из множества
{
0
, . . . , N
}
. Если ограничить количество возможных сообщений до
2
32
−
1
, это
состояние может быть представлено с помощью одного 32-битового числа.
Если бы нумерация сообщений начиналась с нуля, нам бы пришлось ввести
дополнительный флаг, указывающий, что пользователь А еще не отослал ни
одного сообщения или же что пространство номеров сообщений было исчерпа-
но. Наличие таких флагов требует реализации дополнительного и достаточно
сложного кода, который практически никогда не будет использоваться. Если
же этот код практически не используется, то и практически не тестируется,
а значит, может отказать в нужный момент. По сути, введение дополнитель-
ного флага — лишь еще одно потенциальное слабое место, которого так легко
избежать, начиная нумерацию сообщений с единицы.
В следующих разделах главы номер сообщения будет обозначаться как
i
.
8.3.2
Аутентификация
Для аутентификации сообщений мы будем использовать функцию вычис-
ления MAC. Как вы уже, наверное, догадались, это будет функция
HMAC-SHA-256 с полным 256-битовым результатом. Входное значение функ-
ции вычисления MAC будет состоять из сообщения
m
i
и дополнительных
данных аутентификации
x
i
. Как отмечалось в главе 7, “Коды аутентичности
сообщений”, вместе с сообщением зачастую необходимо аутентифицировать
и данные о контексте, в котором оно было отослано. Эти данные применяют-
ся пользователем Б для правильной интерпретации сообщения. Обычно они
включают в себя номер версии протокола, размеры полей и подтверждение
того, что это третье сообщение из последовательности сообщений, отправ-
ленных по каналу. Здесь мы просто определяем безопасный канал общения,
поэтому реальное значение
x
i
должно предоставляться оставшейся частью
приложения. С нашей точки зрения, каждый элемент
x
i
— это строка, зна-
чение которой одинаково для пользователей А и Б.
1
Все ключи следует обновлять через разумные промежутки времени. Интенсивно ис-
пользуемые ключи необходимо обновлять почаще. Ограничение количества сообщений,
которые могут быть зашифрованы или аутентифицированы с помощью одного и того же
ключа, до
2
32
−
1
является вполне приемлемым.
8.3. Структура решения
141
Пусть
`
(
·
)
— это функция, которая возвращает длину строки данных
(в байтах). Значение MAC
a
вычисляется по формуле
a
i
:=
MAC(
i
k
`
(
x
i
)
k
x
i
k
m
i
)
,
где
i
и
`
(
x
i
)
— 32-битовые беззнаковые целые числа, представленные в форма-
те, в котором наименее значимый байт записывается первым. Функция
`
(
x
i
)
гарантирует, что строка
i
k
`
(
x
i
)
k
x
i
k
m
i
уникальным образом разбивается
на нужные части. При отсутствии
`
(
x
i
)
разбивка соответствующей строки
на
i
,
x
i
и
m
i
, а следовательно, и аутентификация были бы неоднозначны-
ми. Разумеется, данные
x
i
должны быть закодированы таким образом, что-
бы их можно было разбить на разные поля без какой-либо дополнительной
контекстной информации, однако гарантировать это на уровне безопасного
канала общения мы не можем. За это должно отвечать приложение, исполь-
зующее наш канал общения.
8.3.3
Шифрование
Для шифрования сообщений мы будем применять блочный шифр AES
в режиме CTR. В роли уникального значения оказии, необходимого для шиф-
рования в режиме CTR, будет выступать номер сообщения.
Размер каждого сообщения имеет ограничение в
16
·
2
32
байт, что ограни-
чивает размер счетчика блоков до 32 бит. Разумеется, мы могли бы исполь-
зовать и 64-битовый счетчик, однако 32-битовые значения легче обрабаты-
вать на многих платформах. Кроме того, большинству приложений вообще
не нужны такие громадные сообщения.
Ключевой поток состоит из байтов
k
0
, k
1
, . . .
. Для сообщения с оказией
i
ключевой поток определяется как
k
0
, . . . , k
2
36
−
1
:=
E
(
K,
0
k
i
k
0)
k
E
(
K,
1
k
i
k
0)
k
. . .
k
E
(
K,
2
32
−
1
k
i
k
0)
,
где каждый блок открытого текста представляет собой конкатенацию 32-би-
тового номера блока, 32-битового номера сообщения и 64 бит нулей. Получен-
ный ключевой поток будет очень длинной строкой. Мы будем использовать
только первые
`
(
m
i
) + 32
байт ключевого потока. (Надеемся, не стоит упо-
минать, что оставшуюся часть ключевого потока подсчитывать не нужно. . . )
Мы выполним конкатенацию значений
m
i
и
a
i
и сложим эти байты с помо-
щью операции XOR с последовательностью байтов
k
0
, . . . , k
l
(
m
i
)+31
.
8.3.4
Формат пакета
Мы не можем просто отослать зашифрованное значение
m
i
k
a
i
, так как
пользователю Б нужно знать номер сообщения. Поэтому перед зашифрован-
ным сообщением
m
i
k
a
i
будет добавлен номер сообщения
i
, представленный
142
Достарыңызбен бөлісу: |