Перейти к содержимому


Фотография

TLS сокеты

OC TLS cryptography internet socket

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 9

#1 Оффлайн   Fingercomp

Fingercomp

    Видимый невидимый

  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 863 сообщений

Награды

                                               

Отправлено 04 Август 2016 - 08:34

Не так давно LeshaInc выкладывал свою программку, фтп клиент-то, и кто-то сказал про ssh. Это, конечно, задача интересная, но речь не об этом. Уже тогда на протяжении дней трёх я изучал вот этот документец. И с тех пор, добавив более 4 тысяч, удалив более двух тысяч строк кода, перечитав этот RFC вдоль и поперёк, исписав 22 страницы моего настольно-напольного блокнота, погуглив 183 запроса про тлс (надо же, гугловская статистика иногда бывает полезна для себя), чуть не потратив 2500 рублей на 12 страниц, описывающих формат десятичных чисел ( :facepalm: ) и даже найдя один баг в Computronics, который мне не давал покоя часов двенадцать, а то и больше, в общем случае... Я наварил TLS сокеты в OpenComputers.

 

Что такое TLS? В нашей ирке спрашивавшим я отвечал так: это такая штука, из-за которой появляется замочек в адресной строке браузера. Фактически, это корректно, и им этого достаточно, но позволю немного поглубже объяснить.

В девяностых годах компания Netscape разработала концепцию и реализацию безопасной передачи данных через недоверенное соединение. Назвалось это чудо SSL, что означает Secure Sockets Layer — слой безопасных сокетов, и выпущено было две версии: 2.0 и 3.0. Версия 1.0 была настолько дырявой, что даже не была никогда выпущена в публичный доступ. Но и, как это неудивительно, ни 2.0, ни 3.0 сейчас мало того, что не считаются безопасными, их поддержку уже исключают из всяких популярных подуктов типа Firefox или Chrome.

Netscape, впрочем, недолго держала это изобретение. Ребята из Internet Engineering Task Force (IETF) в 1999 году выпустили свою, 3.1 версию SSL, которая хоть и имела некоторую совместимость с прошлой версией, но имела много нового и исправляла некоторые проблемы безопасности в прошлом протоколе. Версия SSL от IETF с тех пор называется TLS.

Все версии, для справки:

  • ?: SSL 1.0

  • 1992: SSL 2.0

  • 1995: SSL 3.0

  • 1999: SSL 3.1 // TLS 1.0

  • 2006: SSL 3.2 // TLS 1.1

  • 2008: SSL 3.3 // TLS 1.1

И хоть сейчас SSL и TLS используются взаимозаменяемо, правильнее, всё же, говорить TLS.

 

И всё же, что это за штука такая?

TLS и его предшественник, SSL, — это протокол-прослойка между слоем данных приложений и слоем TCP. Как-то так:

  • Слой данных приложений [Application Data].

  • Слой безопасности [Transport Layer Security, TLS].

  • Слой протокола контроля передачи данных [TCP].

Таким образом, переход на TLS не требует огромных изменений в код, достаточно заменить обычную имплементацию сокетов на защищённую и сгенерировать ключи.

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

 

Как работает TLS.

Перед тем, как передавать данные, неплохо было бы договориться с другим концом соединения, какой набор шифрования использовать, передать некоторые дополнительные данные, подтвердить подлинность сервера (для защиты от встраивания в соединение) и, конечно, обменяться ключами, которыми будет шифроваться информация. Для этого предназначена процедура рукопожатия — Handshake. Клиентом генерируется рандомная информация, шифруется асимметричным шифратором (ECDH-RSA или RSA) и передаётся серверу. Перед этим сервер предоставляет цепочку сертификатов, каждый последующий сертификат которого подтверждает предыдущий. В конце цепочки получается самоподписанный сертификат, которому надо доверять (есть целые списки таких корневых сертификатов). После того, как рандомные байты переданы, сервер и клиент из них генерируют ключи: два ключа проверки валидности информации (на сервер и клиент отдельно для защиты от атаки), два ключа симметричного шифрования данных и, если того требует шифратор, два инициализирующих вектора.

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

 

Каждое шифрованное сообщение имеет специальный код авторизации (MAC), который включает хэш пересылаемых данных и номер последовательности, который имеется отдельно для приёма и отдачи, начинается с 0 и увеличивается на 1 с каждым отосланным сообщением. Таким образом, если сообщение было перехвачено и позже отослано, или трафик был перепутан, то и сервер, и клиент после проверки кода авторизации закрывают соединение.

 

 

Как видно, протокол этот отнюдь не простой, а потому я ещё больше ценю свою программку. Она не полностью соответствует стандартам, в ней нет проверки сертификата, да и сиферы пока только с RSA, но уже позволяет создать соединение с GitHub, Google, да и другими HTTPS-сайтами.

 

d7K3vqv.png

 

Оно работает для меня как-то нестойко, шатко, долго, в общем, неустойчиво. Но ведь работает! На скрине выше успешно была получена информация длиной в 27763 байта.

 

 

 

Библиотека предоставляет таблицу с одной функцией: tlsSocket(host: string[, port: number]). Возвращает она обёрнутый сокет: таблицу с функциями:

  • socket.write(data: string) — посылает данные на сервер.

  • socket.read(): string or nil, string — читает данные с сокета.

  • socket.close() — закрывает сокет (делает это правильным способом, оповещая сервер).

  • socket.id(): string — возвращает ID сокета.

  • socket.isClosed(): boolean — говорит, закрыт ли сокет.

  • socket.setTimeout(to: number) — устанавливает предельное время ожидания данных с сокета, в общем, таймаут соединения.

Все функции вызываются с ., не с :!

 

Зависимости:

  • Компоненты
    • Карта данных второго уровня. Она предоставляет получение рандомных данных и HMAC.

    • Улучшенный шифратор (Advanced Cipher Block) из Computronics. RSA шифрование.

    • Интернет-карта, чтобы, очевидно, посылать запросы.


  • Библиотеки
    • libder-decoder — моя собственная библиотека, которая парсит сертификаты.

    • libbigint — либа БОЛЬШИХ чисел (сначала была библиотека от Zer0Galaxy, но работала она жутчайше медленно: более минуты против пары секунд).

    • lua-lockbox — либа с криптофункциями. К сожалению, не все они работают на Lua 5.3, но есть рабочий AES-128 шифратор.


  • Lua 5.3. На прошлой версии работать не будет!

  • OpenOS 1.6.

  • OpenComputers 1.6.

Установка из OPPM: oppm install libtls. Исходный код.


Сообщение отредактировал Fingercomp: 05 Август 2016 - 07:24


#2 Оффлайн   1Ridav

1Ridav

    Орден К.А.

  • Администраторы
  • 256 сообщений

Награды

         2         

Отправлено 04 Август 2016 - 08:57

Прекрасное начало! Какие планы по добавлению функционала? Приложений на основе этой библы?



#3 Оффлайн   Fingercomp

Fingercomp

    Видимый невидимый

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 863 сообщений

Награды

                                               

Отправлено 04 Август 2016 - 10:13

Ну, надо прикрутить обёртку уже имеющегося сокета, добавить передачу ключа через ECDH-RSA (в карте данных вроде-то что-то было с эллиптическими кривыми и диффихеллманом, не уверен), и, может быть, если очень захочется мне вдруг, проверку валидности сертификатов. Кроме того, хочется как-нибудь ускорить библиотеку — к гитхабу подключался я 10 секунд, а считывал 27 килобайт минуту. Пока что не смотрел, что там так долго пыхтит.

Какие делать программки, я пока не знаю. Может быть, сделать библиотеку HTTPS, но пока что не особо хочется с ней возиться.

 

Тыкаю LeshaInc, чтобы в свой фтп-клиент прикрутил сфтп.


  • NEO это нравится

#4 Оффлайн   Alex

Alex

    Орден К.А.

  • Администраторы
  • 3 265 сообщений

Отправлено 04 Август 2016 - 10:47

Тыкаю LeshaInc, чтобы в свой фтп-клиент прикрутил сфтп.

было бы неплохо лучше для начала туда прикрутить удобное отображение списка файлов вместо эпического прогресбарчика и считалки аптайма времени загрузки однокилобайтного файлика. Ведь там же были мысли о удобном закачивании "большого" количества файлов . Но его пока там же, по идее, нет, судя по скринам. Если в папке больше чем 25(или сколько там) файликов, то все же улетит при листинге на мониторе 2 тира. И как узнать, что там? Нужно или как-то постранично дать возможность выводить или скролл. Или как-то еще.

И есть ли там возможность скачать сразу папку со всем содержимым рекурсивно? Там сам клиентский функционал еще есть куда пилить и пилить.

TLS там может и обождать :)



#5 Оффлайн   Totoro

Totoro

    Свой человек

  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 442 сообщений

Награды

                                      

Отправлено 04 Август 2016 - 11:27

Крутая библиотека, и титанический труд!

Поздравляю с успешным завершением.

 

P.S. Через точку, а не через двоеточие - то есть, одновременно может быть открыт только один такой сокет?



#6 Оффлайн   Fingercomp

Fingercomp

    Видимый невидимый

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 863 сообщений

Награды

                                               

Отправлено 04 Август 2016 - 11:38

Крутая библиотека, и титанический труд!

Поздравляю с успешным завершением.

 

P.S. Через точку, а не через двоеточие - то есть, одновременно может быть открыт только один такой сокет?

Нет. Просто сам сокет хранится в локальной переменной функции, которая возвращает обёртку. Таблица функций создаётся в функции, и получается, что имеет доступ к сокету в переменной.

Дело в том, что в OC обычные сокеты тоже работают через точку, и чтобы не ломать ничего, я сделал так же.



#7 Оффлайн   Saintmare

Saintmare

    Свой человек

  • Пользователи
  • PipPipPipPipPipPipPip
  • 365 сообщений

Отправлено 04 Август 2016 - 14:56

и им этого достаточно
 

А сейчас обидно стало.



#8 Оффлайн   Fingercomp

Fingercomp

    Видимый невидимый

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 863 сообщений

Награды

                                               

Отправлено 04 Август 2016 - 17:53

Обёртка сокетов. Piece of cake, а не задача. Уже доступно. Вот затравочная картинка с ГУГОЛЕМ:

 

Z2deGcM.png

D:

 

Спойлер

  • Totoro и Saintmare это нравится

#9 Оффлайн   Fingercomp

Fingercomp

    Видимый невидимый

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 863 сообщений

Награды

                                               

Отправлено 05 Август 2016 - 09:49

Увеличил скорость чтения в 1⅓, а соединения — в 2.5 раза. Подключил возможность задавать собственные расширения, ибо без этого, например, не работает HTTPS. В общем, пользоваться либой уже можно. :yahoo:


Сообщение отредактировал Fingercomp: 05 Август 2016 - 09:49

  • Saintmare это нравится

#10 Оффлайн   Fingercomp

Fingercomp

    Видимый невидимый

  • Автор темы
  • Пользователи
  • PipPipPipPipPipPipPip
  • 1 863 сообщений

Награды

                                               

Отправлено 05 Август 2016 - 19:05

Неожиданно для себя! Напилил HTTP/HTTPS 1.1 (во второй версии разбираться лень) либу. Работает она абсолютно идентично функции component.request(), вот только поддерживает HTTPS и принимает четвёртый параметр: метод запроса (GET по умолчанию, если не посылается тело запроса, и POST в противном случае). Кроме того, она превращает все хедеры в формат Train-Case, так что можно спокойно получать данные хедеров в своих программах. Однако всё это делается за счёт меньшей производительности, так что лучше использовать стандартные функции, если ничего из вышеперечисленного не требуется.

Библиотека возвращает функцию отправки запроса:

  • http(url: string[, body: string[, headers: table[, method: string]]]): table — посылает запрос на сервер.

  • http(url: string, kwargs: table): table — делает то же самое, но принимает таблицу с аргументами, чтобы не путаться.

В таблице аргументов все параметры опциональны. Вот пример полной таблички:

{
  body = "Hello here\n",
  headers = {
    connection = "close"
  },
  method = "PUT"
}

Возвращают обе функцию таблицу с теми же функциями, что у компонента (и да, тут не надо ставить двоеточие, как и в OC'шном реквесте):

  • response.read([n: number]): string or nil — прочесть некоторое количество данных. Вообще, вся информация читается сразу же, но можно ограничить вывод аргументом. Можно отдать math.huge (или вообще не указывать аргумент), и тогда возвратится все данные полученные.

  • response.close() — закрыть соединение.

  • response.finishConnect(): boolean — возвращает, открыто ли соединение (в стандартном OC немного по-другому работает, там не буля, а nil с причиной, ну и ладно).

  • response.response(): number, string, table — возвращает код статуса (204 или 404, например), текстовое описание статуса ("No Content", "Not Found") и хедеры таблицей таблиц (ибо хедеров одинаковых может быть несколько).

Вот так может выглядеть выхлоп response.response():

200     "OK"    {["Content-Length"]={"12"},
 ["Content-Type"]={"application/octet-stream"},
 Date={"Fri, 05 Aug 2016 15:35:34 GMT"},
 ["Last-Modified"]={"Fri, 05 Aug 2016 14:56:08 GMT"}
 Server={"SimpleHTTP/0.6 Python/2.7.12"}}

Установка из OPPM: oppm install libhttp. Ну и исходный код.


Сообщение отредактировал Fingercomp: 15 Август 2016 - 22:21

  • Totoro, eu_tomat, Quant и еще 1 это нравится





Темы с аналогичным тегами OC, TLS, cryptography, internet, socket

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных


Яндекс.Метрика