Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java ME (J2ME) > Еще раз о https...


Автор: satellite 16.11.2007, 13:02
Привет всем. Прочитал несколько тем на форуме, но конкретного решения так и не нашел.
Пишу такую программку:
Код

import java.io.IOException;
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpsConnection;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 *
 * @author  Vladimir
 * @version
 */
public class Midlet extends MIDlet
{
    private InputStream IS;
    private HttpsConnection HC;
    public void startApp() 
    {
        try {
            HC = (HttpsConnection) Connector.open("https://eurasiasat.satgate.ru/index.php");
            System.out.println("OK 1");
        } catch (IOException ex) {
            System.out.println(ex);
        }
        try {
            IS = HC.openInputStream();
            System.out.println("OK 2");
        } catch (IOException ex) {
            System.out.println(ex);
        }
    }
    
    public void pauseApp() 
    {
    }
    
    public void destroyApp(boolean unconditional) 
    {
    }

    
}



При выполнении генерируется исключение - javax.microedition.pki.CertificateException: Certificate was issued by an unrecognized entity

Как я понимаю, сертификат, полученный с сайта является незнакомым. 
Если я запускаю мидлет на своей NOKIA N72, то в момент соелинения появляется вопрос - Сертификат незнакомый, принять?, - я жму принять и соединение идет дальше. На других телефонах вопросов не появляется, а программа просто виснет.
Если я открываю страницу на компе интернет-эксплорером, то могу скачать сертификат. Возможно ли импортировать его в мидлет (дать понять мидлету, что сертификат надежный), чтобы исключение не формировалось? Или есть другое решение?
Заранее спасибо.


Автор: W0LF 16.11.2007, 14:53
Ну, скачиваешь ты не сертификат, а ключ, которым подписываешь, и если у тебя есть такой сертификат в телефоне, то будет все ок, а если нет - то плохо. 
Поэтому можно сгенерить свой сертификат, и подписать им, но я не знаю, как в телефон его потом залить :(

Автор: satellite 25.11.2007, 13:08
Проверку сертификата с сервера можно реализовать через интерфейс Certificate (или класс certificate). Там есть такие возможности. Вот только как применить этото класс я пока не понял. Класс абстрактный, нужно переопределить методы.

Автор: satellite 3.12.2007, 13:01
Цитата(W0LF @ 16.11.2007,  14:53)
Ну, скачиваешь ты не сертификат, а ключ, которым подписываешь, и если у тебя есть такой сертификат в телефоне, то будет все ок, а если нет - то плохо. 
Поэтому можно сгенерить свой сертификат, и подписать им, но я не знаю, как в телефон его потом залить :(

Мне удалось импортировать сертификат с сервера в телефон, в списке сертификатов телефона он прописан и ему все разрешено. Но ничего не изменилось. Я уже и приложение подписывал определенным сертификатом, который был также и в телефоне, но результата никакого. Похоже проблема нерешаема )))

Автор: VOS 4.12.2007, 10:30
Уточните пару моментов:

1) Какой сертификат у Вас установлен на сервере? Самоподписанный или подписанный Verisign/Thawte?
2) Каким сертификатом Вы подписали мидлет (сертификат разработчика)? Опять же или Вы сгенерили его и потом отправили на подпись в УЦ, или загнали в телефон как корневой сертификат?

Полагаю, все должно работать, если:

Ваш мидлет подписан сертификатом разработчика, удостоверенным тем УЦ (удостоверяющим центром) Verisign/Thawte корневой  сертификат которого есть в Вашем телефоне.
На сервере используется сертификат, опять же подписанный УЦ.

В этом случае приложение  должно работать на любом MIDP 2.0 телефоне.
В противном случае Вам действительно придется всякими спец. сердствами загонять свои сертификаты в телефон, что для большинства пользователей является неразрешимой проблемой.
Если по каким-то причинам Вам не хочется использовать подобную схему (например Вы не хотите, чтобы Ваш клиент ежегодно платил за сертификат для своего сервера), то Вы в принципе можете реализовать самостоятельный защищенный протокол, используя, например, библиотеку Bouncy Castle. Но в этом случае Вам необходимо учитывать действующее законодательство. 

Автор: satellite 5.12.2007, 00:16
VOS спасибо за ответ

Цитата

Какой сертификат у Вас установлен на сервере? Самоподписанный или подписанный Verisign/Thawte?


Сертификат подписан Equifax Secure Global eBusiness CA-1. Сервер, на который заходит мой мидлет принадлежит определенной компании и я не могу управлять ее сертификатами. Т.е. он есть и под него нужно мне подстроиться.

Цитата

Каким сертификатом Вы подписали мидлет (сертификат разработчика)?


Я пытался генерить свой сертификат, кидать его в телефон и подписывать им мидлет. Также пытался подписывать сертификатом, по моему Халмера или что-то в этом роде. В любом случае я думаю, что если мидлет подписан сертификатом, который есть в телефоне то по идее все должно работать. Пока что ничего не работало - но возможно я где-то что-то неправильно делаю.

Автор: VOS 6.12.2007, 11:43
В моем телефоне нет корневого сертификата Equifax Secure Global eBusiness CA-1,
соответственно на моем телефоне вряд ли (не гарантируется) работа с этим сервером. Думаю у Вас аналогично.
Вам надо загрузить в свой телефон корневой сертифика Equifax Secure Global eBusiness CA-1.
По большому счету это открытый ключ этой компании. Им будет проверена подпись под сертификатом Вашего сервера.
Соответсвенно получается цепочка:
Вы доверяете Equifax Secure Global eBusiness CA-1 (т.к. у Вас есть их открытый ключ и считается что Вы его получили от доверенного источника)
Equifax Secure Global eBusiness CA-1 проверил сертификат Вашего сервера, значит теперь Вы можете доверять и ему.

Это если кратко и грубо ;)

Автор: satellite 10.12.2007, 19:43
to VOS:
И все-таки....что нужно , чтобы все работало по HTTPS?
В телефоне должен быть установлен сертификат(ключ) сервера, с которым будет общаться мидлет - и этого достаточно? Или мидлет тоже должен быть подписан каким-то сертификатом?

Автор: VOS 11.12.2007, 10:23
Мидлет тоже должен быть подписан. 
Аналогично как в обычном броузере на PC. Когда вы устанавливаете какой-нибудь апплет или ActiveX он говорит, эта прога сделана тем-то и тем-то, что  подтверждается тем то. Установить?

В мобиле по умолчанию  повыше безопасность, поэтому не доверяют всяким левым прогам. 

Например, я хакер и выяснил, что есть клевый мидлет, позволяющий играть в сетевую игру, но за $ или это какой-нибудь online trading и т.д. 
Если этот мидлет не подписан, то я делаю мидлет с тем же именем. Размещу его где-нибудь, накидаю в форумах на него ссылок, типа рулез и т.д. Притом ссылок, как Вы думаю знаете, можно набросать неочевидных, но это уже хакерские методы, другой топик.
Подмену сервера не так легко сделать, как иногда можно об этом услышать, но тоже возможно, если это не https протокол с
_нормальным_ сертификатом.
Дальше юзер качает его, вводит свой логин/пароль и мидлет  отправляет их на мой сервер/почту и т.д, а потом
говорит, типа вам надо обновить версию и отправляет Вас на скачку уже реального. А пароль/логин хакер уже получил.

Таких атак навскидку можно несколько  десятков придумать. Поэтому:
 - если Вы работаете с важными данными - мидлет должен быть подписан и юзер должен знать, что устанавливать надо только такой милет.
ну и т.д. 

Соответственно считается, если Вы юзаете https, то Вы работаете с важными данными, а значит см. выше.

P.S. Все немного сумбурно, времени нет подробнее написать.

Автор: satellite 12.12.2007, 09:47
to VOS

В конечном итоге мне всего лишь нужно парсить страницу с HTTPS сервера, т.е. считать ее и разобрать. Настоящая Opera подписана сертификатом, а вот ее русский мод не подписан вообще. Однако он открывает HTTPS страницы, значит есть какой-то метод считать страницу HTTPS ? Пусть это будет уже не защищенное соединение, задача - просто считать данные.
Использовать HttpConnection вместо HttpsConnection я пробывал, не помогает...

Автор: VOS 12.12.2007, 10:34
Конечно есть. Можно самостоятельно реализовать SSL протокол. 
В принципе там ничего особо сложного нет, более того реализацию практически всех необходимых для этого модулей можно 
найти, например, в библиотеке Bouncy Castle (а может там и готовая реализация есть, давно ее не юзал).
Т.е. соединение делать не через HttpConnection/HttpsConnection а через сокеты. Поверх них реализовать SSL протокол.
Тогда никаких проблем не возникнет.
Возможно они пошли по этому пути.
В принципе сделать подобный модуль и мне было бы интересно, пригодился бы, думаю. Но, блин, конец года, сами понимаете, времени нет.
Так бы с удовольствием поучаствовал в создании такой библиотечки. Попробуйте погуглить, может есть уже готовый или заготовки какие.
Если найдете, не забудьте поделиться smile

Автор: satellite1977 12.12.2007, 18:38
 smile 

Автор: satellite 13.12.2007, 02:23
Ну вот я и применил сокет:

Код

public class Midlet extends MIDlet
{
    SocketConnection SC = null;
    InputStream IS = null;
    OutputStream OS = null;
    public void startApp() 
    {
        try {
       
             SC = (SocketConnection) Connector.open("socket://eurasiasat.satgate.ru:443");
             System.out.println("OK");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        
        try {
            OS = SC.openOutputStream();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        try {
           
            OS.write("GET https://eurasiasat.satgate.ru/index.php HTTP/1.0\r\n\r\n".getBytes());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        try {
            IS = SC.openInputStream();
            System.out.println("InputStream Opened");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        StringBuffer SB = new StringBuffer();
        for (int i = 0; i < 15000; i++)
        {
            try {
                SB.append((char)IS.read());
            } catch (IOException ex) {
                System.out.println(ex + "Cant read");
            }
        }
        System.out.println(SB.toString());
        
    }


На этапе IS.read вылетает java.io.IOException: error 10054 during TCP read. Как я понял, это происходит именно из-за того, что сервер Https. Вот теперь и нужно реализовать SSL )))

Автор: eugine_s 13.12.2007, 14:38
satellite,  не очень хороший код у тебя получился.

1. В startApp() не стоит перезагружать "тяжелым" кодом.
2. В startApp() нельзя запускать процессы которые могут привести к deadlock-ам (тупиковым ситуациям), да и вообще работу с сокетом нужно делать в отдельном потоке.


Автор: satellite1977 13.12.2007, 14:59
 smile 

Автор: satellite 13.12.2007, 15:01
Цитата(eugine_s @ 13.12.2007,  14:38)
satellite,  не очень хороший код у тебя получился.

1. В startApp() не стоит перезагружать "тяжелым" кодом.
2. В startApp() нельзя запускать процессы которые могут привести к дедблокам (тупиковым ситуациям), да и вообще работу с сокетом нужно делать в отдельном потоке.


Целью этого кода было просто соединение к серверу используя сокет и ничего более, конечно, он не выглядел бы так в конечном варианте.
А за советы спасибо )))

Автор: engineer.dev 7.1.2008, 18:42
Как вариант получилась бодяга...
Берем с bouncycastle.org либу lcrypto-j2me-138.zip


 
Код

            .
            import org.bouncycastle.crypto.tls.*;
            .
            .
            .
            CertificateVerifyer cert = new AlwaysValidVerifyer();
            SocketConnection hc = (SocketConnection) Connector.open(url, Connector.READ_WRITE, true);
            TlsProtocolHandler tp = new TlsProtocolHandler(hc.openInputStream(), hc.openOutputStream());
            tp.connect(cert);
            InputStream ti = tp.getInputStream();
            OutputStream to = tp.getOutputStream();
            .
            .
           

Вроде обрабатывает нормально но заметил пару глюков...
В частности при приеме ответа в UTF-8 почему-то из потока пропадают указаные адреса в теле странички например должно выводится https://78.220.195.230/index.php вместо этого принимаем https:///index.php...


Автор: VOS 8.1.2008, 14:10
engineer.dev,  спасибо за информацию по Bouncy Castle/TLS. Хотел на этот предмет после праздников ее посмотреть.
Скажите, после обсфукатора насколько размер jar увеличивается, если юзать их реализацию https, а не встроенную?

Автор: engineer.dev 11.1.2008, 21:20
Цитата(VOS @ 8.1.2008,  12:10)
engineer.dev,  спасибо за информацию по Bouncy Castle/TLS. Хотел на этот предмет после праздников ее посмотреть.
Скажите, после обсфукатора насколько размер jar увеличивается, если юзать их реализацию https, а не встроенную?

в общем гдет от 800 кило до чуть больше метра (может такой здоровый размер из-за моих кривых рук, т.к. я не заморачивался а засунул всю либу ;), кстати если будете пользоваться либами бонсикастэл там есть несльколько подводных камней, так там есть классы java.* которые конфликруют и надо их переименовывать.... ну короче как руки дайдут дайте знать у меня самого ща несколько актуальна тема https ;)

Автор: VOS 11.1.2008, 23:46
Спасибо. Про траблы с java.* при использовании этой библиотеки я знаю, в 2-х проектах использовал ее.
Цитата

в общем гдет от 800 кило до чуть больше метра 

Многовато что-то, может это  без прогонки через обсфукатор? У меня примерно такой jar получался, когда юзал их реализацию 
RSA (генерация ключей, подпись, верификация)  без обсфукатора.  После него jar где-то 32 кБ получался. 










Автор: engineer.dev 14.1.2008, 21:30
Кстати напоролся на такой подводный камень... даже нет не камень булыжник блин...
в JSR-118 озвучили 

Цитата

15.4.2 Network Access Requirements
Unidentified third party applications MUST use the normal HttpConnection and HttpsConnection APIs to
access web and secure web services. There are no restrictions on web server port numbers through these
interfaces. The implementations augment the protocol so that web servers can identify unidentified third party
applications. The Product-Token “UNTRUSTED” refers to the Unidentified Third Party Protection Domain
and is retained to maintain backward compatibility with JTWI. The following MUST be implemented:
• The implementation of HttpConnection and HttpsConnection MUST include in the User-Agent header
with the Product-Token “UNTRUSTED/1.0”. User-Agent headers supplied by the application MUST
NOT be deleted.
• The implementation of SocketConnection using TCP sockets MUST throw java.lang.SecurityException
when a MIDlet suite belonging to the Unidentified Third Party Protection Domain attempts to connect on
ports 80 and 8080 (http) and 443 (https).
• The implementation of SecureConnection using TCP sockets MUST throw java.lang.SecurityException
when a MIDlet suite belonging to the Unidentified Third Party Protection Domain attempts to connect
on port 443 (https).
• The implementation of the method DatagramConnection.send MUST throw java.lang.SecurityException
when a MIDlet suite belonging to the Unidentified Third Party Protection Domain attempts to send
datagrams to any of the ports 9200-9203 (WAP Gateway).
• The above requirements SHOULD be applied regardless of the API used to access the network. For
example, the javax.microedition.io.Connector.open and javax.microedition.media.Manager.createPlayer
methods SHOULD throw java.lang.SecurityException if access is attempted to these port numbers
through a means other than the normal HttpConnection and HttpsConnection APIs.


короче это значит что если ваше мидлет не подписан то хрен вы сможете воспользоваться сокет соединением через определенные порты такие как 80, 8080, 443 и т.д.
я долго мучался не понимая почему на эмуле все пучком а на мобиле не идет...

Автор: VOS 14.1.2008, 21:55
Попробуйте на сервере SSL повесить на другой  порт, например 4443

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)