Как правильно использовать Crypto Api для шифрования и дешифрования между клиентом и сервером?

#c #cryptography #rsa #cryptoapi #public-key-encryption

#c #криптография #rsa #cryptoapi #шифрование с открытым ключом

Вопрос:

После многих головных болей и советов людей прекратить, мне наконец удалось заставить мое серверное / клиентское приложение работать с этим API и создать необходимые ключи, то есть сеанс и обмен.

Когда я отправляю открытый ключ клиенту, он успешно импортирует ключ и также зашифрует сообщение с использованием этого ключа, но когда я передаю его обратно серверу; он расшифровывает сообщение с использованием ключа сеанса, но сообщение возвращается как мусор (хм .. нужен закрытый ключ!). Теперь это может быть связано с тем, что я передаю зашифрованное сообщение обратно через rpc, но что-то подсказывает мне, что это что-то другое. В идеале мне нужно четкое объяснение того, что я должен делать со всеми этими ключами, потому что информация, которую я в настоящее время получаю, довольно запутанная.

Должен ли я передавать открытый ключ exchange клиенту, чтобы он мог зашифровать сообщение и вернуться для расшифровки.

Или:

Должен ли я на самом деле шифровать ключ сеанса клиентов открытым ключом сервера, а затем возвращать его? (Для меня это звучит неправильно, но я весь внимание !!!)

Пожалуйста, оставьте комментарии, чтобы перейти к другому API, или скопируйте файлы из MSDN (Я уже прочитал все это). Я работаю с Crypto API и мне просто нужно четкое объяснение того, какие ключи сервер должен передать клиенту, а затем что клиент должен сделать и передать обратно, чтобы я мог, наконец, двигаться дальше…

Комментарии:

1. ВАУ, Перепробовав буквально все, я заставил это работать. Я пришел к выводу, что: Серверу необходимо отправить клиенту свой открытый ключ, который клиент затем использует для шифрования своего сеансового ключа. Я возвращаю зашифрованный ключ сеанса с зашифрованным сообщением, и «Привет, вуаля», сервер расшифровывает сообщения клиента. Пожалуйста, я все еще хотел бы услышать ваши мысли. Правильный ли мой процесс? Что мешает кому-либо перехватить первую передачу, то есть открытый ключ, а затем дождаться ключа сеанса, чтобы разблокировать его и таким образом получить исходное сообщение? (О .. для этого требуется закрытый ключ!)

2. Если вы вернетесь и прочтете это, не могли бы вы опубликовать то, что вы на самом деле сделали, в качестве ответа на вопрос, а не комментария? И принять либо ваш ответ, либо ответ от DXM?

Ответ №1:

Похоже, вы на правильном пути, если вы действительно полны решимости придерживаться этого API 🙂

В криптографии существует два различных семейства алгоритмов шифрования. 1) Те, которые используют симметричные ключи и 2) те, которые используют асимметричные ключи. Алгоритмы симметричного ключа (например, AES, DES …) очень быстры и должны использоваться до тех пор, пока существует безопасный способ убедиться, что и клиент, и сервер имеют один и тот же ключ (т. е. ключ сеанса) и никто другой не может получить доступ к этому ключу. С другой стороны, алгоритмы с асимметричным ключом (например, RSA …), которые также являются известными алгоритмами с закрытым / открытым ключом, намного дороже в вычислительном отношении. У них есть один ключ, который может быть использован только для шифрования данных, и второй ключ, который может быть использован только для расшифровки данных. Эти алгоритмы, как вы выяснили, идеально подходят для первоначального рукопожатия и обмена сеансовыми ключами. Сервер создает пару открытый / закрытый ключ и отправляет клиенту открытый ключ. Любой может перехватить его, но когда клиент кодирует сеансовый ключ и отправляет его обратно, pbulic-ключ бесполезен, если подслушивающий хочет узнать сеансовый ключ. Только сервер может декодировать сообщение, поскольку это единственный объект, который хранит закрытый ключ. Итак, ваша первоначальная проблема заключалась в том, что, когда сообщение возвращалось, вместо использования закрытого ключа из пары, вы использовали синхронный сеансовый ключ и, таким образом, получали мусор.

По сути, вы только что реализовали базовое рукопожатие, которое выполняет SSL (и вы могли бы легко обойтись очень небольшим количеством строк кода, если используете библиотеку OpenSSL).

Как только рукопожатие выполнено, у вас теперь есть защищенный канал между клиентом и сервером. Единственная проблема, с которой вы можете столкнуться, заключается в том, что если кто-то скопирует IP-адрес вашего сервера и начнет притворяться, что он настоящий сервер? Ваш клиент будет думать, что он разговаривает с реальным сервером, он произведет обмен ключами и начнет отправлять защищенную информацию, но вся эта информация может оказаться в руках злоумышленников, если компьютер злоумышленника окажется на другом конце.

Вот здесь и пригодится использование сертификатов SSL. Сертификаты — это еще один пример использования открытых / закрытых ключей. Доверенный центр использует закрытый ключ для подписи хэш-кода сертификатов, и любой может проверить, что сертификат действителен, используя его прикрепленный открытый ключ к идентификационным данным сертификатов. Таким образом, даже если злоумышленник завладеет IP-адресом вашего сервера, он не сможет подделать сертификат вашего сервера.

Комментарии:

1. Большое вам спасибо за этот очень информативный ответ, это именно то, что мне было нужно, т. е. немного уверенности! Основная причина, по которой я хотел использовать этот API, заключалась в том, что у меня уже есть некоторый опыт работы с SSL, и хотя SSL, вероятно, был бы идеальным для этого проекта (т. Е. Передача данных по сети, Интернету и т.д.), он (насколько я знаю) не позволяет вам шифровать, подписывать и хэшировать файлы или другие данные, которые могут потребоваться для хранения на разных носителях. Я чувствую, что понимание обеих технологий пошло бы на пользу моему образованию и, возможно, даже оказалось бы полезным в реальной рабочей ситуации.