Я пишу клиента на Java (должен работать как на рабочем столе JRE, так и на Android) для проприетарного протокола (определенного для моей компании), перенесенного через TLS. Я пытаюсь найти лучший способ написать клиент TLS в Java и, в частности, убедиться, что он правильно проверяет имя хоста. ( Изменить:. Под этим я подразумеваю проверку того, что имя хоста соответствует сертификату X.509, чтобы избежать атак типа "человек в середине".)
JSSE - это очевидный API для написания клиента TLS, но я заметил из документа Самый опасный код в мире" (как а также от экспериментов), что JSSE не проверяет имя хоста при использовании SSLSocketFactory API. (Это то, что я должен использовать, поскольку мой протокол не HTTPS.)
Итак, похоже, что при использовании JSSE я должен сам проверять имя хоста. И, вместо того, чтобы писать этот код с нуля (поскольку я почти наверняка ошибаюсь), кажется, что я должен "заимствовать" какой-то существующий код, который работает. Итак, наиболее вероятным кандидатом, который я нашел, является использование библиотеки Apache HttpComponents (иронично, поскольку я фактически не выполняю HTTP) и использую класс org.apache.http.conn.ssl.SSLSocketFactory вместо стандартный класс javax.net.ssl.SSLSocketFactory.
Мой вопрос: это разумный ход действий? Или я полностью неправильно понял, ушел с глубокого конца, и на самом деле гораздо проще получить подтверждение имени хоста в JSSE, не затягивая стороннюю библиотеку, такую как HttpComponents?
Я также посмотрел на BouncyCastle, который имеет API-интерфейс JSSE для TLS, но он, кажется, еще более ограничен, поскольку он даже не проверяет цепочку сертификатов, а тем более проверку имени хоста, поэтому казалось, как не стартер.
Изменить: Этот вопрос ответил на для Java 7, но мне все еще интересно, что такое "лучшая практика" для Java 6 и Android. (В частности, я должен поддерживать Android для своего приложения.)
Отредактировано снова: Чтобы сделать мое предложение "заимствовать у Apache HttpComponents" более конкретным, я создал небольшую библиотеку , который содержит реализации HostnameVerifier (в первую очередь StrictHostnameVerifier и BrowserCompatHostnameVerifier), извлеченные из Apache HttpComponents. (Я понял, что все, что мне нужно, это верификаторы, и мне не нужен Apache SSLSocketFactory, как я изначально думал). Если оставить его на своих устройствах, это решение, которое я буду использовать. Но, во-первых, есть ли какая-то причина, по которой я не должен этого делать? (Предполагая, что моя цель - сделать проверку имени хоста таким же образом, как это делает https. Я понимаю, что сама открыта для обсуждения и обсуждалась в потоке в списке криптографии, но пока я придерживаюсь HTTPS-подобного имени хоста валидация, хотя я не делаю HTTPS.)
Предполагая, что с моим решением ничего не "неправильно", мой вопрос заключается в следующем: есть ли "лучший" способ сделать это, оставаясь при этом переносимым на Java 6, Java 7 и Android? (Где "лучше" означает больше идиоматического, уже широко используемого и/или нуждающегося в меньшем внешнем коде.)