Я реализую обмен асимметричными ключами для создания симметричного ключа.
Мой вопрос скорее философский/юридический с точки зрения ответственности за обмен ключами и что происходит, когда, скажем, используется общеизвестный ключ.
Я хотел бы установить эти базовые переменные:
- У клиента есть открытый ключ сервера, жестко закодированный в памяти.
- Сервер имеет свой закрытый ключ, жестко запрограммированный в памяти.
- Существует жестко запрограммированный
nonce_size
- Существует жестко запрограммированный
public_key_size
- Существует жестко запрограммированный
mac_size
Этапы связи для обмена следующие:
- После успешного TCP-соединения клиент генерирует новый открытый ключ.
client_pubkey
, шифрует своим открытым ключом client_pubkey
использование нового одноразового номера temp_nonce_1
и жестко запрограммированный server_pubkey
, и отправляет сообщение, в котором первые байты представляют собой одноразовый номер, а остальные — закодированные client_pubkey
(включая его Mac). Он имеет известный размер nonce_size + public_key_size + mac_size
.
- Сервер получает сообщение, проверяя его размер точно на
nonce_size + public_key_size + mac_size
. Если это так, предполагается, что это обмен ключами. Он расшифровывает public_key. Затем сервер генерирует новый симметричный_ключ
, и отправляет обратно сообщение, содержащее новый одноразовый номер tmp_nonce2
, а симметричный ключ + mac зашифрован с использованием полученного client_pubkey
.
- Клиент получает это сообщение, точно знает, какого размера оно должно быть, иначе отклоняет. Теперь у клиента есть симметричный ключ для использования.
- Сервер и клиент взаимодействуют через симметричные ключи.
Итак, вот моя попытка понять, почему это безопасно:
- В случае случайных байтов мусора, отправляемых на сервер, сервер генерирует ключ, шифрует ключ с помощью мусора, создавая еще больше мусора, а затем отправляет его. Таким образом, на самом деле мы отправили больше мусора, а затем просто никогда не получили действительного сообщения и, в конечном итоге, тайм-аут, закрывающий соединение. Единственный вред здесь — потраченное впустую процессорное время на несколько секунд.
- Клиент специально отправляет public_key только из нулей (или какого-то другого очевидного набора битов, например, все 1) и допустимый (или также нулевой) одноразовый номер. В этом случае сервер обрабатывает нули как открытый ключ и отправляет симметричный ключ, зашифрованный с помощью нулей открытого ключа. Тем не менее, это все еще должно быть безопасным, потому что наличие открытого ключа из нулей предполагает, что вы знаете закрытый ключ, из которого получен указанный нулевой открытый_ключ, что потенциально может занять миллиарды лет для обратного проектирования, поэтому он все еще безопасен.
- Предполагая, что клиент и сервер могут перезапускать этот процесс бесконечно (и на сервере нет ограничения на количество попыток), при условии, что каким-то образом по чистой случайной удаче и отправке случайных байтов происходит обмен ключами и действительное сообщение о любых данных, которые были отправлены сервером. Ожидание отправлено и проанализировано сервером, мы поднимаем руки вверх, так как это почти невозможно и в основном
дерьмо случается
.
- В этом случае мы не можем сказать, что кто-то несет ответственность, не так ли? Сервер ничего не может сделать, зная, что это вредоносный пакет.
- Даже если бы у нас было ограничение x-retry в 2 попытки, теоретически это могло бы произойти даже при самом первом подключении с IP-адреса, и опять же мы ничего не можем с этим поделать.
Таким образом, в основном все безопасно, потому что ожидается, что основа самого первого сообщения будет зашифрована открытым_ключом, и только сервер должен знать соответствующий закрытый_ключ, верно? И что в том простом случае, когда что-то каким-то образом удается пройти, результат остается неопределенным?
Извините, если это действительно кратко, я просто пытаюсь проверить свое понимание теории и убедиться, что в реализации такого протокола нет ошибок.