×

Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

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

Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

  • Рубрики
  • Слайдер статей
  • Тест сайта
  • Подписка
  • Сайдбар
  • Прокрутка вверх
  • Как сделать сайт с нуля своими руками (вводная часть)

    1. Причины создания пошаговой инструкции по разработке самописного сайта
    2. Тема создаваемого сайта
    3. В чем будет заключаться монетизация
    4. Функционал
    5. Этапы создания
    6. Текущее состояние создаваемого сайта

    Здравствуйте уважаемый посетитель!

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

    Причем чтобы такой интернет-ресурс был создан не на каком-нибудь стандартном шаблоне бесплатной СMS (Content management system - система управления контентом) типа WordPress, Drupal, Joomla и т.п., а заточенный под себя, с возможностью обеспечить ему должную безопасность и реализовать все свои индивидуальные потребности.

    Часто такие сайты, созданные под конкретные задачи на основе языка разметки веб-страниц HTML, стилей CSS и других инструментов веб-программирования (PHP, JavaScript и т.п.), называют самописными.

    Этой статьей начинается отдельная рубрика "Как сделать сайт с нуля своими руками", где на реальном примере, с предоставлением исходных материалов (программные коды, файлы и т.п.), будет показано, как действительно можно самостоятельно сделать рабочий сайт.

    По существу, она представляет вводную часть сборника статей по столь интересной и полезной теме. И в общих чертах поясняет некоторые особенности создаваемого сайта.

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

Самописный сайт своими руками!

Текущее состояние создаваемого сайта

Здесь можно посмотреть текущее состояние тестового самописного сайта, который создается в рамках цикла статей Сделай сайт с нуля своими руками.

Где в дополнительных материалах можно бесплатно скачать исходные файлы сайта с таблицами MySQL.

Вы здесь: Главная → Сборник статей → Формы → Хешируем пароли в PHP


Автор: / Дата:

Хешируем пароли в PHP

Здравствуйте уважаемый посетитель!

В предыдущей статье при отправке данных из формы для защиты пароля от взлома мы применили специальное односторонне преобразование (хеширование).

В результате, из сравнительно простого пароля, состоящего из 6-ти цифр и букв латинского алфавита, получили довольно сложную комбинацию из 60 символов. И которую, в конечном итоге, сохранили в базе данных в качестве одного из параметров созданной учетной записи пользователя.

Как ранее было отмечено, хеширование это важнейший элемент защиты такой конфиденциальной информации, как пароль. Поэтому в данной статье будет уделено отдельное внимание этому вопросу.

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

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

Содержание


  • Зачем нужно хешировать пароли
  • Вскрываем пароль при слабо защищенном хеше
  • Защищаемся от 'грубой силы' замедляя хеш-функцию
  • Усложняем хеш добавляя 'соль'
  • Исходные файлы сайта

Зачем нужно хешировать пароли


Наверное нельзя не согласиться с тем, что в наше время никто не застрахован от взлома серверов баз данных. По крайней мере, нам приходится очень часто слышать в новостях, что взломана какая-то очередная база, содержащая данные десятков, сотен тысяч, а то и миллионов пользователей.

И понятно, что в случае утечки таких конфиденциальных данных, как пароли учетных записей, могут возникнуть серьезные проблемы в работе ресурса, с которого они были украдены.

Но кроме этого, для тех пользователей, которые используют не уникальные пароли, а повторяют их при работе с разными интернет-ресурсами, овладение хакерами этой информацией может привести к другим очень серьезным последствиям. Например, в случае использования таких аккаунтов для работы с онлайн банками и другими подобными приложениями, возможно столкнуться с существенными финансовыми потерями.

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

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

Но, как говорится, против лома нет приема. Поэтому определенные индивидуумы нашли и успешно применяют другие методы восстановления пароля. Например, может быт быть использован полный перебор всевозможных вариантов (метод "грубой силы", англ. brute force). Который при хорошей вычислительной мощности оборудования в ряде случаев может оказаться очень эффективным средством.

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

Для эффективности поиска могут применяться и другие массивы данных с заранее вычисленными парами пароль-хэш, так называемыми "радужные" таблицы. В общем, злоумышленники обладают достаточным количеством всевозможных инструментов для совершения своих грязных дел. И к этому нужно быть готовым.

Поскольку темой данной статьи является защита паролей, а не рассмотрение вопросов их взлома, то мы не будем здесь подробно заниматься различными хакерскими методиками. А более плотно займемся рассмотрением способов, которые напротив позволят более надежно защитить наши данные от несанкционированных воздействий.

Надо отметить, что в настоящее время тема кибер безопасности стала довольно избитой. Одни американские выборы чего стоят. И вполне возможно, что у некоторых посетителей может сложиться впечатление, что автор здесь гонит очередные хакерские страшилки.

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

А если все же кто-то сомневается в необходимости серьезного отношения к этому вопросу, с дополнительной информацией по этой теме можно ознакомиться из других источников. Например, хорошие разъяснения по вопросам безопасного применения хеширования паролей, с достаточно кратким и понятным изложением рекомендаций, можно найти в этом разделе онлайн справочника по PHP.

скриншот 37

Вскрываем пароль при слабо защищенном хеше


Для того, чтобы убедиться, что слабо защищенный пароль легко вскрыть, проведем небольшую проверку возможности восстановления исходного пароля из хеша, которую проведем в два этапа:

  • Сначала получим хеш какой-нибудь комбинации символов. Например, возьмем вариант, который мы использовали в предыдущей статье при создании пароля для нового пользователя, в виде Z5nC89. В котором применены как цифры, так и буквы латинского алфавита обоих регистров.
  • А затем, используя специальные инструменты, попробуем из хеша восстановить исходный пароль. При этом средствами взлома могут выступать как специальные программы, так различные, специализирующие на этом, онлайн сервисы.

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

Это касается в основном таких хеширующих алгоритмов как MD5, SHA1 и т.п. Несмотря на то, что многие профессионалы в сфере информационной безопасности достаточно давно уже не рекомендуют их использовать для хеширования паролей, все-равно и сейчас применение таких функций остается достаточно популярным.

Низкая защищенность подобных алгоритмов обусловлена в основном тем, что в свое время такие методы шифрования были спроектированы с очень высокой скоростью вычислений. И сегодня при наличии современных технологий и оборудования, при их выполнении стало довольно просто получать нужный результат методом полного перебора возможных вариантов.

Таким образом, для нашего примера воспользуемся наиболее известным из них, алгоритмом хеширования MD5. Причем при формировании хеш-кода будем использовать только непосредственные возможности соответствующей функции без добавления каких-либо дополнительных мер по усложнению преобразований. Этим мы займемся позднее при рассмотрении способов повышения защищенности данных.

Итак, приступим. В PHP для вычисления MD5-хэша обычно используют встроенную функцию "md5()", обязательным параметром которой является строковая переменная, соответствующая исходной комбинации.

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

  1. <?php

  2. //Получение MD5-хеша с помощью функции md5()

  3. $password = 'Z5nC89';

  4. $hash = md5($password);

  5. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash."\n");

  6. ?>

Рис.1 Получение MD5-хэша с помощью функции md5()

Функция echo nl2br (поз.5) здесь добавлена для контроля полученного результата с помощью вывода значения переменных $password и $hash на страницу сайта.

Следует отметить, что MD5-хэш можно получить и другим способом, использовав для этого универсальную функцию генерирования хеш-кода "hash()", которая позволяет вычислять хеши различными методами. Для этого нужно лишь в качестве первого параметра указать имя используемого алгоритма.

В данном случае такой вариант можно представить следующим кодом, заменив предыдущую функцию md5() на hash().

  1. <?php

  2. //Получение MD5-хэша с помощью функции hash()

  3. $password = 'Z5nC89';

  4. $hash = hash('md5', $password);

  5. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash."\n");

  6. ?>

Рис.2 Получение MD5-хэша с помощью функции hash()

После того, как мы определились с необходимыми для вычисления функциями, временно выведем полученный результат в какое-нибудь место на сайте, например, на главную страницу. Для чего поместим PHP-код одного из приведенных здесь вариантов в конец файла "main.php", находящегося в папке "articles" корневого каталога.

В итоге, после обновления главной страницы, в нижней части ее мы должны увидеть MD5-хеш, соответствующий заданному паролю Z5nC89, как показано на скриншоте.

Для увеличения / уменьшения размера изображения кликните по картинке
Получение из пароля MD5-хеш

Рис.3 Получение из пароля MD5-хеш

Таким образом мы получили следующее значение хеша: eba7e0c49c4f93cada50dd7803de8f6e.

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

Воспользуемся, к примеру, одним из старейших сервисов для расшифровки хешей CMD5, владеющим одной из самых больших баз данных и предлагающим свои услуги на восстановление разных видов хеш-кодов (SHA1, 32 bit MD5, MD4, mysql и т.д.).

скриншот 35

Для этого скопируем в соответствующее поле ранее полученный хеш и запустим кнопкой "Искать" выполнение необходимого преобразования.

Для увеличения / уменьшения размера изображения кликните по картинке
Восстановление пароля из MD5-хеша

Рис.4 Восстановление пароля из MD5-хеша

Как видно, без каких-либо усилий, мы сразу получили исходную комбинацию символов Z5nC89. Причем для данного варианта сделали это совершенно бесплатно, затратив на это ничтожно малое время в пределах всего одной секунды.

Этот пример наглядно показывает, что использовать для хеширования паролей алгоритм MD5, не применяя при этом никаких дополнительных мер усложнения вычислений, весьма легкомысленно.

Так как делает такие важные конфиденциальные данные просто беззащитными перед злоумышленниками. Которые с удивительной легкостью могут вскрываться даже такими средствами, как онлайн сервисы, не говоря уже о других более серьезных инструментах взлома.

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

Защищаемся от 'грубой силы' замедляя хеш-функцию


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

Если конкретнее, то попробуем подсчитать, сколько времени понадобится для восстановления пароля из хеша, созданного с помощью MD5-функции на обычном пользовательском компьютере.

Возьмем, к примеру, тот же пароль с длиной в шесть символов Z5nC89. Перебрав в таком варианте пароля все возможные символы (0-9, a-z, A-Z, всего 62 символа), получим 56`800`235`584 хешей (62 символа в 6-ой степени).

Таким образом, нетрудно подсчитать, что при переборе всех возможных вариантов такого 6-ти символьного пароля на простом обычном компьютере, скажем, со скоростью обработки в районе одного миллиона хешей в секунду, понадобиться менее одного дня (56`800`235`584 / 1`000`000 ≈ 56`800 сек. ≈ 20 час.).

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

При более сложном пароле, например, при использовании восьми символов, на машине с одним миллиардом операций в секунду можно обработать массив из 218 триллионов хешей (62 символа в 8-ой степени) за время не более 60 часов. Что тоже вполне реально.

Для повышения защиты паролей можно, конечно, с помощью определенных шаблонов заставить пользователей вводить довольно сложные комбинации с большим количеством символов. Но не исключено, что при таком подходе некоторые пользователи не станут заморачиваться и просто не будут регистрироваться, либо вообще уйдут с такого ресурса.

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

Исходя из этого, для защиты от взлома "грубой силы" полученного в предыдущем примере хеш-кода, увеличим время выполнения такого преобразования, скажем в пятьсот тысяч раз. Соответствующий такой операции PHP-код показан в следующей таблице.

  1. <?php

  2. //Вычисление хэша с замедлением MD5-функции

  3. $password = 'Z5nC89';

  4. $start_time = microtime(true);

  5. $hash = md5($password);

  6. for ($i = 0; $i < 500000; $i++) {

  7. $hash = md5($hash);

  8. }

  9. $delta_time = microtime(true) - $start_time;

  10. $cash_time = round($delta_time * 1000000, 0).'мкс.';

  11. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash.', время вычисления - '.$cash_time."\n");

  12. ?>

Рис.5 Вычисление хеша с замедлением MD5-функции

Как видно, здесь к полученному MD5-хешу (поз.5), с помощью конструкции цикла for (поз.6) добавлено выполнение еще 500`000 аналогичных повторных операций (поз.7).

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

Сначала с помощью функции microtime() переменной $start_time присваивается отметка времени начала выполнения преобразования (поз.4). Которое соответствует количеству секунд, прошедших с начала, так называемой, Эпохи Unix (1 января 1970 0:00:00 GMT).

А затем, с помощью получения разности значений меток времени до и после преобразований в виде $delta_time (поз.9) и округления этого значения с помощью функции round(), умноженного на 1`000`000, получается реальное время получения хеша в микросекундах (поз.10).

После вышеуказанных дополнений снова обновим главную страницу и посмотрим на результат.

Для увеличения / уменьшения размера изображения кликните по картинке
Результат замедления MD5-функции

Рис.6 Результат замедления MD5-функции

Как видно, в этом случае время получения одного хеша на используемом в этом примере оборудования составило 270`437 мкс (примерно одна треть секунды). Что означает, что в одну секунду при таких параметрах может быть выполнено не более 3 вычислений.

Очевидно, что при данной скорости обработки, невозможно в реальности на таком железе перебрать все комбинации. Ведь для этого потребуются сотни лет (56`800`235`584 / 3 / 60 / 60 / 24 / 365 ≈ 600 лет).

А на более производительном оборудовании, скажем в тысячу, для этого случая понадобится до полугода непрерывной работы. И понятно, что здравомыслящий человек этим тоже заниматься не будет.

Для сравнения, нетрудно подсчитать, что время разового выполнения MD5-функции для данного примера составляет менее одной микросекунды (270`437 / 500`000 = 0.54 мкс).

Поэтому, если бы мы не уменьшили скорость обработки, то на таком же оборудовании можно было бы перебрать все варианты всего за несколько часов (56`800`235`584 / 2`000`000 / 60 / 60 / 24 / 365 ≈ 9 часов), что вполне реально. Как говорится, результат налицо.

Стоит отметить, что величина времени выполнения хеш-функции выбирается с учетом разумной достаточности. Очевидно, что задав время в пределах 100÷300 миллисекунд, пользователь при отправке формы даже это и не заметит. Но зато как это плодотворно скажется на защите от атак "грубой силы" злоумышленников.

Усложняем хеш добавляя 'соль'


В предыдущем разделе мы рассмотрели способ защиты от "грубой силы". Теперь же попробуем защититься от методов вскрытия паролей, основанных на поиске по заготовленным массивам пар пароль-хэш, с использованием упомянутых ранее "радужных" таблиц.

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

Суть в том, что при таком дополнении используя готовые таблицы будет невозможно найти исходный пароль по таким модифицированным хешам. Ведь готовых таблиц для таких данных в природе просто не существует. И атакующему придётся создать огромное количество отдельных "радужных таблиц", что, практически трудно выполнимо.

Весь процесс этих преобразований можно представить в несколько действий.

При сохранении пароля:

  • формируем соль из случайной последовательности, полученной с помощью криптографического генератора псевдослучайных чисел;
  • смешиваем соль с паролем и вычисляем хеш с помощью хеш-функции;
  • присоединяем соль к полученному хешу и сохраняем результирующий хеш-код вместе с "солью" в базе данных пользователей.

При проверке пароля:

  • Извлекаем по отдельности соль и хеш из сохраненного ранее в базе данных результирующего хеш-кода;
  • смешиваем соль с вновь введенным паролем и вычисляем хеш-код с помощью хеш-функции с учетом заданного количества интераций (повторное многократное применение обработки данных), которые были применены для замедления функции на этапе сохранения пароля;
  • сравниваем хеш введенного пароля с хешем, полученным из базы данных. При совпадении - пароль введен правильно. При не совпадении - пароль не верен.

И для того, чтобы посмотреть, как это выглядит на практике, приведем наш ранее сформированный PHP-код получения MD5-хеша к следующему виду.

  1. <?php

  2. //Добавление соли в MD5-хэш

  3. $password = 'Z5nC89';

  4. $start_time = microtime(true);

  5. $salt = substr(sha1(mt_rand()),6,16);

  6. $mod_pass = $salt.$password;

  7. $hash = md5($mod_pass);

  8. for ($i = 0; $i < 500000; $i++) {

  9. $hash = md5($hash);

  10. }

  11. $hash = $salt.$hash;

  12. $delta_time = microtime(true) - $start_time;

  13. $cash_time = round($delta_time * 1000000, 0).'мкс.';

  14. echo nl2br('MD5: пароль - '.$password.', соль - '.$salt.', хеш - '.$hash.', время вычисления - '.$cash_time."\n");

  15. ?>

Рис.7 Добавление соли в MD5-хэш

Здесь для получения соли используется вариант, при котором сначала с помощью функции mt_rand() генерируется случайное число с дальнейшем получением из него sha1-хэша виде 40-символьного шестнадцатеричного числа. А затем после извлечения функцией substr() строки, начинающейся с шестой позиции sha1-хэша и длиной в 16 символов, образуется 16-символьная соль в виде переменной $salt (поз.5). Чуть позже будет понятно, почему для этого случая мы выбрали такую длину соли.

А далее, полученная соль смешивается с паролем, образуя значение переменной $mod_pass (поз.6), которое в дальнейшем будет использовано для вычисления хеша (поз.7).

Для замедления MD5-функции здесь также с помощью цикла for (поз.8) применяется цикличные повторные вычисления, образующие хеш $hash (поз.9) с заданным замедлением, соответствующим 500`000 циклов.

Окончательное формирование результирующего хеш-кода происходит путем сложения соли с хешем, полученным на выходе цикла (поз.11).

Таким образом после выполнения всех этих преобразований должен получиться хеш, состоящий не из 32-ух, а уже из 48-ми символов. Причем первая его часть из 16 символов будет представлять соль, а вторая - хеш, полученный из пароля, смешанного с солью и с прогонкой через MD5-функцию 500`000 раз.

После внесенных дополнений снова обновим станицу и посмотрим, так ли это.

Для увеличения / уменьшения размера изображения кликните по картинке
Получение хеша с добавленной солью

Рис.8 Получение хеша с добавленной "солью"

Как видно, результат подтвердил ранее сказанное. На выходе мы получили 48-символьный результирующий хеш-код. Который образован с использованием 16-ти символьной соли. Но к этому нужно добавить еще очень важный момент.

Дело в том, что мы получили хеш-код с замедленной MD5-функцией и с добавлением соли, используя для этого специально созданный PHP-скрипт. Поэтому, для того, чтобы иметь хоть какие-то шансы на взлом таких хешей, необходимо не только получить их из базы данных, но и взломать непосредственно файлы сайта и разобраться с заданным в них алгоритмом преобразований.

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

Например, в приведенном примере сознательно была использована соль с длиной в 16 символов. И в итоге мы получили результирующий хеш-код в 48 символов в виде 4fe8eb4f4bad316c79d58384eb80d3d2a2a445f2e13c3246, который по количеству и типу символов полностью повторяет хеш, образованный в результате выполнения другой криптографической хеш-функции типа Тiger/192. Ниже показаны вариант кода и результат вычисления такого хеша.

  1. <?php

  2. //Получение MD5-хэша с помощью функции hash()

  3. $password = 'Z5nC89';

  4. $hash = hash('tiger192,3', $password);

  5. echo nl2br('MD5: пароль - '.$password.', хеш - '.$hash."\n");

  6. ?>

Рис.9 PHP-код получения хэша по алгоритму Тiger/192

Для увеличения / уменьшения размера изображения кликните по картинке
Результат получения хеша с помощью функции tiger/192

Рис.10 Результат получения хеша с помощью функции tiger/192

Как видно, хеш 188a297729de491f3a03978cf8cb1a743029bd7e23165860, сформированный с применением алгоритма Tiger/192 по виду ничем не отличается от ране полученного нами MD5-хеша с добавленной солью.

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

Таким образом на примере обычной MD5-функции мы рассмотрели возможные механизмы, применение которых позволяет существенно повысить защиту паролей от несанкционированного восстановления. Где получили хеш, для взлома которого прийдется очень и очень потрудиться.

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

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

Исходные файлы сайта


Знак папкиИсходные файлы сайта с обновлениями, которые были сделаны в данной статье, можно скачать из прилагаемых дополнительных материалов:

  • Файлы каталога www
  • Таблицы базы данных MySQL

При этом, временно сформированные в данной статье PHP-скрипты, размещенные в файле "main.php" папки "articles" корневого каталога, закомментированы. Для проверки рассмотренных здесь примеров, следует раскомментировать соответствующие фрагменты кода.

Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.

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

Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.

С уважением, Николай Гришин

Комментарии


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

Буду Вам за это очень признателен!

comments powered by HyperComments