Рецензирование для обмена криптографическим ключом - PullRequest
2 голосов
/ 14 марта 2011

Я играл с Bouncy Castle (java) в течение последних нескольких дней, и я достиг того момента, когда, как мне кажется, я могу безопасно обмениваться секретными ключами с обменом Диффи-Хеллмана.

Прочитав много постов, подчеркивающих сложность правильного осуществления криптографического обмена, я хотел бы получить ваше честное мнение о моей работе. Все основные операции шифрования основаны на Bouncy Castle и поэтому могут считаться надежными.

    String message = "Hello World";

    AESCipher aes_client = new AESCipher(256);
    RSACipher rsa_server = new RSACipher(2048);

    // (Public key sent over the wire)
    RSACipher rsa_client = new RSACipher(rsa_server.getPublicKey().getModulus(),
                                         rsa_server.getPublicKey().getExponent());

    // The client encodes his AES key with the RSA public key:
    byte[] aes_key = rsa_client.encode(aes_client.getKeyBytes());
    byte[] aes_iv = rsa_client.encode(aes_client.getInitializationVector());

    // (Data sent back over the wire)
    byte[] decoded_aes_key = rsa_server.decode(aes_key);
    byte[] decoded_aes_iv = rsa_server.decode(aes_iv);

    // The server creates an AES server which uses the client key:
    AESCipher aes_server = new AESCipher(decoded_aes_key, decoded_aes_iv);

    byte[] encoded_message = aes_client.encode(message.getBytes());
    byte[] decoded_message = aes_server.decode(encoded_message);

    System.out.println(new String(decoded_message));

Можно ли считать этот обмен безопасным? Должен ли я придерживаться сокетов SSL, даже если бы мне было больно мучиться? Заранее спасибо за ваш вклад!

(Кстати, моя библиотека Bouncy-Castle-Wrapping-Library полностью открыта, поэтому просто дайте мне знать, если вам нужен URL хранилища.)

Ответы [ 2 ]

2 голосов
/ 15 марта 2011

(В вашем протоколе нет Диффи-Хеллмана, только RSA и симметричное шифрование.)

Первое основное замечание - ваш протокол уязвим для активных атак. «Человек посередине» - это классика (злоумышленник перехватывает открытый ключ, заменяя его своим собственным). Кроме того, у вас есть только симметричное шифрование, но нет MAC. Давайте предположим, что ваша модель атаки касается только пассивных атакующих; в большинстве случаев это, по меньшей мере, очень смелое предположение. На самом деле, мне трудно представить себе ситуацию, когда это применимо: подслушивающий, который может просматривать переданные байты, но не может отправлять свои собственные сообщения. Если вы не запускаете все это в аутентифицированном туннеле с проверками целостности (в SSL есть режим для этого, но это своего рода победа).

Вы шифруете IV, который не нужен (IV не является ключом, иначе он будет называться «ключом», а не IV). Что вам нужно от IV - это генерировать случайным образом для каждого зашифрованного сообщения. Предполагая, что вы используете режим CBC, допустимо, чтобы последний зашифрованный блок из сообщения использовался как IV для следующего сообщения. Однако было бы смертельно опасно повторно использовать IV для двух разных сообщений с одним и тем же симметричным ключом шифрования. Поскольку Bouncy Castle не имеет класса с именем AESCipher, ваш пример кода не сообщает нам, используете ли вы AES с правильным режимом цепочки и правильным управлением IV. Также обратите внимание, что повторное использование последнего зашифрованного блока из предыдущего сообщения работает только до тех пор, пока сообщения отправляются последовательно, а сообщения не теряются. Более надежное решение:

  1. выбрать новый случайный IV (через криптографически сильный ГСЧ, например, java.security.SecureRandom) для каждого сообщения;
  2. отправляет объединение IV и зашифрованные данные в виде закодированного сообщения.

Это позволяет получателю восстановить IV (как первый блок сообщения), а затем обработать сообщение независимо от того, были ли отправлены и получены предыдущие сообщения. И в этом случае активный злоумышленник может нанести ущерб этой схеме, хотя бы только с помощью простых «атак воспроизведения» (злоумышленник отправляет копию ранее отправленного сообщения).

В качестве примечания, String.getBytes() и new String(byte[]) используют кодировку платформы по умолчанию, которая может различаться для клиента и сервера. Вам было бы лучше использовать явную кодировку, например UTF-8: message.getBytes("UTF-8") и new String(decoded_message, "UTF-8").

Вообще говоря, безопасность и гордыня плохо сочетаются. Будьте готовы отказаться от вашего кода. Основная причина, по которой вы действительно должны использовать стандартные протоколы, такие как SSL / TLS, заключается в том, что безопасность не может быть доказана. Что бы вы сказали кому-то (например, вашему начальнику), спросив вас, что заставляет вас думать, что протокол безопасен? «Какой-то парень в Stack Overflow сказал мне об этом»?

0 голосов
/ 14 марта 2011

Я бы просто отметил, что IV обычно не шифруется.Думаю, в этом нет ничего страшного, но в этом нет необходимости.

...