Задать вопрос

Как сделать SSL socket клиент серверное приложение?

Здравствуйте! Пишу клиент серверное приложение, необходимо чтобы они "общались" по защищенному протоколу.
Сервер будет стоять на машине под управлением CentOS 6.5
Клиент крутиться будет на Android устройствах и не только.
У меня не хватает знаний в плане SSL. Что мне для этого нужно?
Нужны ли настройки машины, сертификат?
Находил в нете много статей, к примеру эту
но я так понимаю там не используется сертификат, а есть ли примеры с использованием сертификата?
Заранее большое спасибо!
  • Вопрос задан
  • 4792 просмотра
Подписаться 4 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 2
StFaustoff
@StFaustoff
jDev
Работа с сертификатами бывает разная. Это может быть как просто использование сертификата на стороне сервера и дальнейшая проверка через центры сертификации, так и использование самоподписанных сертификатов, когда и клиент и сервер имеют один сертификат и обмениваются ими при подключении. Первый вариант проще, второй бесплатный.
После этого нужно настроить веб контейнер. Вот тут есть хороший пример настройки TomCat'a. Собственно я использую двухфазную самоподписанную сертификацию.
После этого начнется "жара" =) Так как я пользуюсь самоподписанным сертификатом, то задача немного усложняется. Дело в том, что на стороне мобильного клиента необходима предварительная настройка контекста интернет соединения для работы с сертификатом. Соответственно идут клиент обращается серверам сертификации, чтобы проверить надежность ресурса. Но так как все самопальное, то приходиться настройки безопасности переводить в режим - доверять всему.
После этой настройки, контекст передается для создаваемого коннекта и регистрируется.
Приведу пример кода, выстраданного многими часами кропотливой работы
try{// Работа с SSL пробрасывает исключения, порой очень неприятные и непонятно как устранимые
   KeyStore keyStore = KeyStore.getInstance("Your_Type_Of_Certificate");//делаем хранилище ключей, аналогичное типу Вашего сертификата
   InputStream in = ...// крепим к потоку сам файл сертификата
   try{
      keyStore.load(in, "Your_Password".toCharArray());//грузим в хранилище сертификат, дополняя его паролем от сертификата
   }catch (Exception ex){
      Log.wtf("OMG",ex.getLocalizedMessage());//либо файла нет, либо пароль не тот
   }finally {
      in.close();
   }
   // Один из "столпов" клиентского SSL, отвечает за хранение всех сертификатов. Имеются разные варианты его настройки(разные алгоритмы)
   KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
   kmf.init(keyStore, "Your_Password".toCharArray());
   KeyManager[] keyManagers = kmf.getKeyManagers();

   //Второй элемент, который "должен" проверять, валидны ли наши сертификаты
   TrustManager[] wrappedTrustManagers = new TrustManager[]{
       new X509TrustManager() {
           public java.security.cert.X509Certificate[] getAcceptedIssuers() {
              return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
        }
   };
   SSLContext sslContext = SSLContext.getInstance("TLSv1");//Создаем контекст SSL по типу протокола
   sslContext.init(keyManagers, wrappedTrustManagers,  new java.security.SecureRandom());//инициализируем его
       return sslContext;// Радуемся =)
   }catch (Exception ex){
        Log.wtf("OMG", ex.getLocalizedMessage());// Печалимся ='(
        return null;
   }


После этого контекст можно использовать при создании соединений
//Устанавливаем контекст
   HttpsURLConnection.setDefaultSSLSocketFactory(методНаписанныйВыше().getSocketFactory());
    //Та самая "защита" которая говорит "мне плевать на всех, коннекчусь куда хочу". Виной этому самоподписанный сертификат.
   HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
   
   SchemeRegistry registry = new SchemeRegistry();

    SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
    socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
    registry.register(new Scheme("Type_Of_Connection", socketFactory, 443));

    SingleClientConnManager mgr = new SingleClientConnManager(yourConnection.getParams(), registry);
    //Я работаю по https, по этому пример для него
    DefaultHttpClient httpClient = new DefaultHttpClient(mgr, yourConnection.getParams());

    HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);


За такой код я бы и сам себя убил, но увы, любые попытки его поправить к успеху не привели, я рукожоп)
Стоит заметить, что я использую библиотеки org.apache.http и другие deprecate вещи. Вам же я желаю сделать все по уму и красоте. Надеюсь помог)
Если будут вопросы, обращайтесь.
Ответ написан
@relgames
Java Developer
Я бы рекомендовал не писать с нуля socket-server, а использовать Netty
maxrohde.com/2013/09/07/setting-up-ssl-with-netty
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы