<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Заметки Lizard'а</title><generator>teletype.in</generator><description><![CDATA[Криптография, RFID, Sub-GHz и прочее...

TG - https://t.me/li0ard_notes]]></description><image><url>https://img2.teletype.in/files/19/87/1987aab1-7d15-4074-837f-9832d42deb19.png</url><title>Заметки Lizard'а</title><link>https://blog.li0ard.rest/</link></image><link>https://blog.li0ard.rest/?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/li0ard?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/li0ard?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Thu, 23 Apr 2026 08:31:45 GMT</pubDate><lastBuildDate>Thu, 23 Apr 2026 08:31:45 GMT</lastBuildDate><item><guid isPermaLink="true">https://blog.li0ard.rest/blazorpack</guid><link>https://blog.li0ard.rest/blazorpack?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/blazorpack?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Получаем HTML из Blazorpack</title><pubDate>Sat, 25 Oct 2025 09:46:31 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/46/26/46267e9f-f5bf-408d-ace8-9f195a9ff832.png"></media:content><description><![CDATA[<img src="https://img1.teletype.in/files/c0/8f/c08f94dc-2250-453f-bd1e-03dbff72cbe7.png"></img>Одним вечером у меня появилась необходимость написать парсер HTML одного сайта, но при просмотре содержимого страницы вместо нужных мне данных я увидел данный комментарий:]]></description><content:encoded><![CDATA[
  <nav>
    <ul>
      <li class="m_level_1"><a href="#bljn">Как это работает?</a></li>
      <li class="m_level_2"><a href="#UIKA">Установка соединения</a></li>
      <li class="m_level_2"><a href="#1qWH">Обмен данными (BlazorPack)</a></li>
      <li class="m_level_1"><a href="#Vo1f">Получаем HTML</a></li>
      <li class="m_level_2"><a href="#lWZX">Формат DOM</a></li>
      <li class="m_level_2"><a href="#hMRf">Таблица строк</a></li>
      <li class="m_level_2"><a href="#txRS">Процесс восстановления HTML</a></li>
    </ul>
  </nav>
  <p id="kjrt">Одним вечером у меня появилась необходимость написать парсер HTML одного сайта, но при просмотре содержимого страницы вместо нужных мне данных я увидел данный комментарий:</p>
  <figure id="snJc" class="m_original">
    <img src="https://img1.teletype.in/files/c0/8f/c08f94dc-2250-453f-bd1e-03dbff72cbe7.png" width="632" />
  </figure>
  <p id="HY4h">Я подумал: &quot;Ага, значит данные подгружаются динамически, следовательно должен быть запрос на сервер&quot;, однако открыв DevTools я увидел WebSocket, который судя по всему получал HTML от сервера</p>
  <figure id="VEMg" class="m_original">
    <img src="https://img3.teletype.in/files/ac/c0/acc00ff7-88a0-4ee3-a064-006989514529.png" width="532" />
  </figure>
  <h2 id="bljn">Как это работает?</h2>
  <figure id="QgFt" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/27/f9/27f9e8af-d348-4cc4-82ea-0f5c29af3c16.png" width="1838" />
    <figcaption>Полная схема установки соединения и согласования протоколов</figcaption>
  </figure>
  <p id="vCDi">Делать полный разбор протокола я не буду, поэтому кратко пройдёмся по основным этапам:</p>
  <h3 id="UIKA">Установка соединения</h3>
  <p id="yoFt">После того как браузер загрузил страницу происходит POST запрос на <code>/_blazor/negotiate</code>, который возвращает:</p>
  <ul id="Wza4">
    <li id="x26V">список поддерживаемых транспортных протоколов (WebSockets, Server-Sent Events, Long Polling);</li>
    <li id="6Qig">ID соединения (<code>connectionId</code>);</li>
    <li id="Gapb">Токен доступа (<code>connectionToken</code>).</li>
  </ul>
  <p id="HOTV">Браузер перебирает список протоколов, и пытается установить соединение.<br />Если первый вариант не удался, то пробуется следующий и так далее.</p>
  <h3 id="1qWH">Обмен данными (BlazorPack)</h3>
  <p id="WCCk">В качестве протокола обмена сообщениями между сервером и браузером используется протокол <strong>SignalR</strong>, который в свою очередь использует <strong>MessagePack</strong> (бинарный формат сериализации)</p>
  <p id="bOye">Также поверх этого используется ещё 1 слой - <strong>Binary Message Format (BMF)</strong>.<br />К данным добавляются префикс длины, что позволяет передать несколько сообщений за один раз.</p>
  <p id="XsTV">Получается такая &quot;матрёшка&quot; из кодировок:</p>
  <p id="Lpl4" data-align="center"><code>BMF -&gt; SignalR -&gt; MessagePack</code></p>
  <p id="iFxl">Каждый слой решает свою задачу:</p>
  <ul id="BSBV">
    <li id="QWAF"><strong>MessagePack</strong> - компактное представление данных;</li>
    <li id="3nuw"><strong>SignalR</strong> - вызов методов и маршрутизация сообщений (Ядро BlazorPack);</li>
    <li id="QolB"><strong>Binary Message Format (BMF)</strong> - framing сообщений (Передача нескольких сообщений за раз)</li>
  </ul>
  <figure id="62wq" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/f7/d4/f7d474fd-f177-4797-b509-3a4e03cde1d3.png" width="807" />
    <figcaption>Пример сообщения</figcaption>
  </figure>
  <h2 id="Vo1f">Получаем HTML</h2>
  <p id="ub9u">Данный этап можно назвать самым сложным, так как Blazor <u>не отдаёт HTML в &quot;голом&quot; виде</u> , вместо этого <u>он отдаёт представление DOM в бинарном пакете</u> (<code>RenderBatch</code>) разделённым на секции:</p>
  <ul id="5I1K">
    <li id="kbt3"><code>UpdatedComponents</code> (<code>ArrayRange&lt;Diff&gt;</code>);</li>
    <li id="OqOJ"><code>ReferenceFrames</code> (<code>ArrayRange&lt;Frame&gt;</code>);</li>
    <li id="vbap"><code>DisposedComponentIds</code> (<code>ArrayRange&lt;int&gt;</code>);</li>
    <li id="Bqcy"><code>DisposedEventHandlerIds</code> (<code>ArrayRange&lt;long&gt;</code>);</li>
    <li id="Ysgc"><code>StringTable</code> (<code>ArrayRange&lt;string offsets&gt;</code>).</li>
  </ul>
  <p id="i66J">В конце пакета находятся 5 чисел (<code>int32</code>) — это смещения каждой секции в байтах (от начала массива).</p>
  <h3 id="lWZX">Формат DOM</h3>
  <p id="YbF7">Сами узлы DOM хранятся в структуре под названием <code>RenderTreeFrame</code>, одна структура может описывать:</p>
  <ul id="fvVX">
    <li id="Xzar">HTML-тег;</li>
    <li id="vwKA">текстовое значение;</li>
    <li id="wtOv">атрибут;</li>
    <li id="02CK">компонент Blazor;</li>
    <li id="rjgc">&quot;голый&quot; HTML-фрагмент.</li>
  </ul>
  <p id="lXmG">Сам <code>RenderTreeFrame</code> выглядит так:</p>
  <pre id="ZmRh">[Тип фрейма][Параметр 1][Параметр 2][Параметр 3][Параметр 4]</pre>
  <p id="Y8AP">Тип фрейма определяет, что это за узел:</p>
  <ul id="XuGh">
    <li id="AwWs">1 - HTML-тег (<code>Element</code>);</li>
    <li id="eCKh">2 - текст (<code>Text</code>);</li>
    <li id="7s2a">3 - атрибут (<code>Attribute</code>);</li>
    <li id="VqoK">4 - Компонент Blazor (<code>Component</code>);</li>
    <li id="Rc5z">5 - Регион (Служебные данные) (<code>Region</code>);</li>
    <li id="psSN">8 - &quot;Голый&quot; HTML (<code>Markup</code>).</li>
  </ul>
  <h3 id="hMRf">Таблица строк</h3>
  <p id="iyB3">Чтобы не дублировать текст, все строки (имена тегов, атрибуты, значения, текст)<br />хранятся в конце пакета в таблице строк.</p>
  <p id="tqT0">Каждая запись содержит смещение на строку, а сами строки записаны как:</p>
  <pre id="C2yU">[LEB128-длина][UTF-8 байты строки]</pre>
  <h3 id="txRS">Процесс восстановления HTML</h3>
  <ol id="13xH">
    <li id="DcYH">Берём <code>RenderBatch</code> полученный от SignalR</li>
    <li id="tjGq">Читаем 5 чисел в конце файла - получаем смещение секций</li>
    <li id="MufW">Переходим в секцию <code>ReferenceFrames</code> - получаем все узлы дерева (<code>RenderTreeFrame</code>)</li>
    <li id="hY2k">Последовательно читаем фреймы:<br />- если <code>Element</code> - создаём элемент;<br />- если <code>Attribute</code> - добавляем к предыдущему тегу;<br />- если <code>Text</code> - вставляем текстовое содержимое в предыдущий тег;<br />- если <code>Markup</code> - вставляем HTML как есть;<br />- если <code>Region</code> - рекурсивно обрабатываем последующие фреймы;</li>
    <li id="UQD3">Используем свойство subtreeLength, чтобы понять, где заканчивается элемент;</li>
    <li id="HI3g">Склеиваем всё в строку и получаем HTML.</li>
  </ol>
  <p id="i6lS"><strong>P.S Реализация TS библиотеки доступна <a href="https://github.com/li0ard/renderbatch" target="_blank">здесь</a>.</strong></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/rutoken_export_p2</guid><link>https://blog.li0ard.rest/rutoken_export_p2?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/rutoken_export_p2?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Тащим ключи с Рутокен Lite ч.2</title><pubDate>Sat, 09 Aug 2025 16:59:07 GMT</pubDate><category>Криптография</category><description><![CDATA[<img src="https://img2.teletype.in/files/1b/40/1b40aa91-6c20-4034-a705-f1fcf4d68cf9.png"></img>В предыдущей статье, я описал способ экспорта ключей с Рутокен Lite вручную, в этой же статье будет инструкция по экспорту автоматизированным способом.]]></description><content:encoded><![CDATA[
  <p id="AkKu">В <a href="https://teletype.in/@li0ard/rutoken_export" target="_blank">предыдущей статье</a>, я описал способ экспорта ключей из Рутокен Lite вручную, в этой же статье будет инструкция по экспорту автоматизированным способом.</p>
  <p id="O7zM">Нам понадобится:</p>
  <ol id="NQkI">
    <li id="F1Ed"><a href="https://github.com/li0ard/rutoken_export" target="_blank">Моя утилита</a></li>
    <li id="4VqY">Сам Рутокен Lite и PIN-код пользователя</li>
  </ol>
  <section style="background-color:hsl(hsl(0, 0%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="1btQ"><strong>Важно</strong>: Данная статья предполагает, что у вас уже установлен компилятор Go</p>
  </section>
  <ol id="OTJu">
    <li id="CuSn">Клонируем репозиторий и переходим в папку с кодом</li>
    <li id="zsTS">Собираем утилиту с помощью <code>go build</code></li>
    <li id="qjyh">Запускаем утилиту, вводим PIN-код пользователя, и вводим метку (см. ниже) нужного контейнера</li>
  </ol>
  <figure id="qa7l" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/1b/40/1b40aa91-6c20-4034-a705-f1fcf4d68cf9.png" width="593" />
    <figcaption>Пример работы</figcaption>
  </figure>
  <p id="QFf5">В указанной утилитой папке будет лежать экспортированный контейнер</p>
  <figure id="mWmC" class="m_column">
    <img src="https://img1.teletype.in/files/0c/b2/0cb28bae-f772-41ef-98a3-d60c71834c66.png" width="618" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/rutoken_export</guid><link>https://blog.li0ard.rest/rutoken_export?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/rutoken_export?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Тащим ключи с Рутокен Lite</title><pubDate>Sun, 03 Aug 2025 17:23:14 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/98/bc/98bc0167-357c-4188-b336-7b6de337e139.png"></media:content><category>Криптография</category><description><![CDATA[<img src="https://img4.teletype.in/files/b8/8b/b88b54ca-631e-4511-887e-f583e59a7d39.png"></img>Думаю многим знакома ситуация, когда ФНС (или любой другой УЦ) записывает контейнер с ЭЦП на Рутокен, а в процессе использования возникает необходимость использования ЭЦП без самого Рутокена (например из файловой системы) и т.д.]]></description><content:encoded><![CDATA[
  <figure id="AaR9" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/b8/8b/b88b54ca-631e-4511-887e-f583e59a7d39.png" width="1280" />
    <figcaption>Суть такова</figcaption>
  </figure>
  <p id="tEny">Думаю многим знакома ситуация, когда ФНС (или любой другой УЦ) записывает контейнер с ЭЦП на Рутокен, а в процессе использования возникает необходимость использования ЭЦП без самого Рутокена (например из файловой системы) и т.д.</p>
  <p id="yaXO">Однако та же ФНС <strong>&quot;отключает&quot; флаг экспортируемости</strong> контейнера и при попытке экспорта ключа мы получаем ошибку, а в Центре управления Рутокен&#x27;ом есть возможность только экспортировать сертификат.</p>
  <figure id="gDcM" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/79/7c/797c65f7-1f7f-4990-acbd-19014118a520.png" width="1019" />
    <figcaption>Скриншот из Центре управления Рутокен&#x27;ом</figcaption>
  </figure>
  <p id="6SJl">Также следует упомянуть, что существует популярная утилита Tokens.exe от СКБ Контур, однако у неё есть ряд недостатков:</p>
  <ol id="OCrr">
    <li id="jLy2">Утилита работает только на Windows</li>
    <li id="b6BM">Написана на HTML с использованием устаревшего ActiveXObject с связке с DLL</li>
    <li id="N26s">Утилиту благополучно &quot;выпилили&quot; с сайта, поэтому приходится искать по всему интернету</li>
  </ol>
  <h2 id="IlRW">Тащим ключи</h2>
  <h3 id="Byue">1. Ищем контейнер</h3>
  <p id="fFlw">Рутокен Lite - не совсем флешка в привычном понимании, у него максимально облегченная файловая система, поэтому просто открыть его в проводнике не получится</p>
  <p id="cWsB">Однако для этих целей можно воспользоваться утилитами от проекта <a href="https://github.com/OpenSC/OpenSC" target="_blank">OpenSC</a></p>
  <section style="background-color:hsl(hsl(0, 0%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="lOiM"><strong>Важно</strong>: Данная статья предполагает, что у вас уже установлены <code>opensc-tool</code> и <code>opensc-explorer</code></p>
  </section>
  <p id="Z50H">Поэтому подключаем Рутокен, открываем консоль и вводим <code>opensc-tool --list-files</code></p>
  <figure id="2JAE" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/49/41/49411806-5802-4a2c-b4c5-fa5e01e54a8d.png" width="815" />
    <figcaption>Файловая система Рутокена</figcaption>
  </figure>
  <p id="tMMJ">Среди всего списка необходимо найти директорию с 6 файлами, часть из которых доступна для чтения только после авторизации (<code>read[CHV2]</code>). Сделать это легче всего по имени контейнера в КриптоПро, поскольку <code>opensc-tool</code> декодирует ASCII текст:</p>
  <figure id="aGlN" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/21/1d/211de796-f6e7-4ba2-8ae7-ffb7b5ad25c3.png" width="1366" />
    <figcaption>Совпадение имени контейнера с содержимым файла на Рутокене</figcaption>
  </figure>
  <p id="zCiG">Файл на скриншоте это <code>name.key</code>, а директория с контейнером (выделена жёлтым) в нашем случае будет <code>3f00100010030a00</code></p>
  <p id="9R9N"><strong>UPD от 05.08</strong>: Вероятнее всего все контейнеры действительно лежат по пути <code>1000/1003</code>. Соответственно при помощи команды asn1 искать по имени контейнера:</p>
  <figure id="aHQk" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/d2/ee/d2ee69b4-f56d-4cbb-9d23-fe171bf9f709.png" width="809" />
    <figcaption>name.key и header.key второго контейнера на Рутокене</figcaption>
  </figure>
  <h3 id="3San">2. Выгрузка</h3>
  <p id="3k7m">Запускаем <code>opensc-explorer</code> и переходим в директорию контейнера с помощью команды <code>cd &lt;путь&gt;</code></p>
  <section style="background-color:hsl(hsl(0, 0%, var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="Yzxm"><strong>Важно</strong>: Необходимо разделить путь директории на группы по 4 символа и убрать <code>3f00</code>, в нашем случае это будет <code>1000</code>, <code>1003</code>, <code>0a00</code></p>
  </section>
  <figure id="dGCj" class="m_column">
    <img src="https://img4.teletype.in/files/7e/bd/7ebd7d39-532a-4133-af66-95cf2bc5ac2f.png" width="457" />
  </figure>
  <p id="hV8A">В директории файлы лежат в следующем порядке: <code>name.key</code>, <code>header.key</code>, <code>primary.key</code>, <code>masks.key</code>, <code>primary2.key</code>, <code>masks2.key</code></p>
  <figure id="wQ2G" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/a3/72/a3728a84-797b-4b8a-af1d-808bbd4f3bcf.png" width="357" />
    <figcaption>Файлы контейнера</figcaption>
  </figure>
  <p id="PMVf">Теперь самый важный пункт - необходимо авторизоваться по PIN-коду пользователя (в противном случае Рутокен даст выгрузить только <code>name.key</code> и <code>header.key</code>). Сделать это можно с помощью команды <code>verify CHV2 &quot;PIN-код&quot;</code></p>
  <figure id="Inqq" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/24/6c/246c2b0d-8fc6-4df7-8a1c-cece3675eab1.png" width="438" />
    <figcaption>Успешная авторизация</figcaption>
  </figure>
  <p id="dIOi">Теперь же просто копируем файлы контейнера в память компьютера с помощью команды <code>get File_ID путь_назначения</code></p>
  <figure id="8fHq" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/c6/df/c6dfa3e9-8ad7-4ae5-8ef0-b4e351dac4a8.png" width="609" />
  </figure>
  <p id="JpuC">На этом всё, мы успешно скопировали контейнер с Рутокен Lite в память нашего компьютера. Далее желательно &quot;пролечить&quot; контейнер, чтобы &quot;включить&quot; флаг экспортируемости, но на текущий момент решение ещё в разработке (оповещение о релизе будет в Telegram канале). <em>To be continued...</em></p>
  <h2 id="Hybq">Бонус. Экспорт приватного ключа</h2>
  <p id="l7us">Для удобства использования ключа подписи, его можно экспортировать в формат <code>.pem</code> (с которым умеет работать OpenSSL и прочие утилиты) с помощью моей онлайн-утилиты<br />В утилиту загружаем файлы <code>header.key</code>, <code>masks.key</code> и <code>primary.key</code>, поле &quot;Пароль&quot; оставляем пустым (поскольку контейнеры на Рутокенах не имеют пароля т.к происходит авторизация по PIN-коду) и нажимаем &quot;Извлечь&quot;, через несколько секунд скачается <code>.pem</code> файл с приватным ключом.</p>
  <figure id="qvCN" class="m_column">
    <img src="https://img1.teletype.in/files/0c/7c/0c7ce9c1-2f98-4f27-b65c-7bd45e5d62a2.png" width="1344" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/wtfiskeeloq</guid><link>https://blog.li0ard.rest/wtfiskeeloq?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/wtfiskeeloq?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>KeeLoq и с чем его едят</title><pubDate>Tue, 27 May 2025 20:27:42 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/d2/31/d231606d-6bef-4de9-9ebc-c2d8b9f57b54.png"></media:content><category>Криптография</category><description><![CDATA[<img src="https://img3.teletype.in/files/e4/f3/e4f33756-7577-44fd-9681-ecc6ab3684e8.png"></img>KeeLoq - блочный шифр, основанный на NLFSR...]]></description><content:encoded><![CDATA[
  <nav>
    <ul>
      <li class="m_level_1"><a href="#XZoD">Принцип работы</a></li>
      <li class="m_level_1"><a href="#iRjJ">Режимы безопасности</a></li>
      <li class="m_level_1"><a href="#kATQ">Теоретические атаки</a></li>
      <li class="m_level_2"><a href="#LK6k">Слайд-атака</a></li>
      <li class="m_level_2"><a href="#xUzg">Корреляционный подход</a></li>
      <li class="m_level_2"><a href="#UXF8">Линейный шаг</a></li>
      <li class="m_level_1"><a href="#MlSn">Практические атаки</a></li>
      <li class="m_level_2"><a href="#QeWA">Replay-атака</a></li>
      <li class="m_level_2"><a href="#hrtX">Клонирование пульта</a></li>
      <li class="m_level_2"><a href="#EVpD">Future-атака</a></li>
      <li class="m_level_2"><a href="#tacj">Rollback-атака</a></li>
      <li class="m_level_2"><a href="#jCpe">Rolljam-атака</a></li>
      <li class="m_level_2"><a href="#ckqu">Атака на мануфактурные ключи (KGB attack)</a></li>
      <li class="m_level_2"><a href="#tLCW">Enc00-атака</a></li>
      <li class="m_level_2"><a href="#wSBY">Unknown-атака</a></li>
      <li class="m_level_1"><a href="#5cd7">Заключение</a></li>
      <li class="m_level_2"><a href="#34Ux">Использованные материалы</a></li>
    </ul>
  </nav>
  <p id="kioG">Итак, начнём с выдержки из Википедии:</p>
  <blockquote id="zIMz"><strong>KeeLoq</strong> - блочный шифр, основанный на NLFSR (регистр сдвига с нелинейной обратной связью), разработан компанией Nanoteq Pty Ltd. и продан компании Microchip Technology Inc. Шифрование происходит блоками по 32 бита с помощью 64 битного ключа за 528 итераций. Ранее использовался в автомобильных сигнализациях, а ныне используется в автоматических воротах, гаражных дверях и т.п</blockquote>
  <figure id="j3FI" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/e4/f3/e4f33756-7577-44fd-9681-ecc6ab3684e8.png" width="675" />
    <figcaption>Картинка для привлечения внимания </figcaption>
  </figure>
  <h2 id="XZoD">Принцип работы</h2>
  <p id="96Cs">KeeLoq реализует так называемый <em>code hopping</em> (переключение кода), то есть генерирует уникальный пакет данных для каждой передачи.</p>
  <figure id="ZBv5" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/8e/87/8e8716b1-06de-449b-aca1-f2847a954798.png" width="1050" />
    <figcaption>Структура пакета данных</figcaption>
  </figure>
  <p id="Pfu4">Разберём на примере:</p>
  <p id="T1Gp" data-align="center"><code><strong>239B3DEB</strong>F16C47A6</code></p>
  <p id="Gmjp">Первые 4 байта - это фиксированная часть (т.н <code>fix</code>), содержит в себе ID нажатой кнопки на пульте (в нашем случае <code>2</code>) и 28&#x27;ми битный серийный номер пульта (<code><strong>39B3DEB</strong></code>)</p>
  <p id="3RFP">Следующие 4 байта - динамическая часть (т.н <code>hop</code>), зашифрована мануфактурным ключом (ключом производителя). В расшифрованном виде выглядит так:</p>
  <p id="CuTc" data-align="center"><code>21EB000A</code></p>
  <p id="xhAC">Здесь мы видим всё тот же ID нажатой кнопки (<code>2</code>), 12 бит дополнительной информации (зачастую это <code>serial &amp; 0x3FF</code>) и сам 16 битный счётчик нажатий (<code>000A</code>)</p>
  <p id="Sa0P">Логика работы счётчика такая:</p>
  <ul id="O522">
    <li id="nH51">Если переданное значение счётчика соответствует значению в EEPROM приёмника то приёмник подаёт сигнал контроллеру, что всё хорошо (и контроллер например открывает ворота)</li>
  </ul>
  <figure id="lA81" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/07/44/07446e47-580e-4043-a0c0-37b32b7283f7.png" width="796" />
    <figcaption>Штатная работа приёмника</figcaption>
  </figure>
  <ul id="kL84">
    <li id="iVC0">Если переданное значение больше значения в EEPROM то приёмник синхронизируется с переданным значением и соответственно после следующей передачи значения начнёт работать штатно</li>
  </ul>
  <figure id="fd8Y" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/59/66/5966eef6-7b9d-4930-ab26-e9e21b95497c.png" width="784" />
    <figcaption>Процесс сихронизации приёмника</figcaption>
  </figure>
  <ul id="Q5S6">
    <li id="sY2m">Если переданное значение меньше значения в EEPROM то приёмник игнорирует переданную команду, а в некоторых случаях после нескольких отправок &quot;устаревшего&quot; значения и вовсе отвязывает пульт. (Собственно говоря это и есть опасность при экспериментах с KeeLoq)</li>
  </ul>
  <figure id="vsj9" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/6b/9c/6b9c0e69-07be-4a82-a569-4ecb7ecb1dcc.png" width="860" />
    <figcaption>Реакция на устаревшее значение счётчика и отвязка пульта</figcaption>
  </figure>
  <h2 id="iRjJ">Режимы безопасности</h2>
  <p id="S5EC">В стандарте KeeLoq есть 3 режима безопасности (также известны как KDF, learnings):</p>
  <ul id="gAD1">
    <li id="AWTH"><strong>Простой режим (Simple learning)</strong><br />Наименее защищённый режим, при котором мануфактурный ключ никак не преобразуется и используется в шифровании as is.</li>
    <li id="O4Oo"><strong>Классический режим (Normal learning)</strong><br />Улучшенная версия, где мануфактурный ключ изменяется с помощью серийного номера пульта с помощью побитовых операций</li>
  </ul>
  <figure id="kanv" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/e6/56/e656f372-c5a5-4c28-ab78-1bb3a872f9fe.png" width="525" />
    <figcaption>Примерная запись алгоритма</figcaption>
  </figure>
  <ul id="qKp3">
    <li id="C09x"><strong>Безопасный режим (Secure learning)</strong><br />Модифицированная версия классического режима, использующая вместо побитовых операций над серийным номером, дополнительное значение (он же seed), уникальное для каждого пульта и передающееся при первоначальной привязке пульта к приёмнику. На данный момент самый защищённых режим из представленных в стандарте</li>
  </ul>
  <figure id="jZiQ" class="m_column" data-caption-align="center">
    <img src="https://img1.teletype.in/files/4a/55/4a5598d6-fbf5-4438-b411-f3f1b0d80c3f.png" width="496" />
    <figcaption>Примерная запись алгоритма</figcaption>
  </figure>
  <p id="N8p0">Однако некоторые производители отклоняются от стандартных режимов безопасности и реализуют свои собственные, давайте рассмотрим некоторые из них:</p>
  <ul id="nUV6">
    <li id="YvOw"><strong>Magic XOR Type-1 learning</strong><br />Используется производителем Beninca, представляет из себя XOR серийного номера пульта на мануфактурный ключ</li>
  </ul>
  <figure id="0wgO" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/d8/8a/d88a7eb1-9a74-4566-8aa7-0f3984286a8e.png" width="357" />
    <figcaption>Примерная запись алгоритма</figcaption>
  </figure>
  <ul id="gLs7">
    <li id="lKNt"><strong>FAAC SLH (SPA) learning</strong><br />Как понятно из названия, данный алгоритм используется производителем FAAC и по моему мнению является самым продуманным. Представляет из себя серию побитовых операций и шифрования</li>
  </ul>
  <figure id="RRK3" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/eb/26/eb26511a-62ba-4234-9467-15d55ee36454.png" width="360" />
    <figcaption>Примерная запись алгоритма</figcaption>
  </figure>
  <h2 id="kATQ">Теоретические атаки</h2>
  <h3 id="LK6k">Слайд-атака</h3>
  <p id="bolB">Атака применима, преимущественно, к многораундовым кодам, каждый раунд которых представляет собой несложное преобразование исходного блока с использованием лишь одного ключа.</p>
  <p id="H8XD">На первом этапе набрать порядка 2^32 пар открытый-зашифрованный текст<br />Далее <code>(M,C)</code> - одна из таких пар, <code>F</code> - функция преобразования. Суть такова:<br />если <code>(M’,C’)</code> такая, что <code>P’= F(K,M)</code> и <code>C’= F(K,C)</code>, то <code>K</code> и есть искомый ключ.</p>
  <p id="xXtN">В теории данная атака позволяет получить первые 32 бита ключа.</p>
  <h3 id="xUzg">Корреляционный подход</h3>
  <p id="pbUD">Атака базируется на свойстве NLFSR - <code>Cor(F) = 1</code><br />Оказывается, что для равномерно распределенных <code>x2,x3,x4</code> имеет место следующее:</p>
  <ul id="FylO">
    <li id="jusg"><code>{NLFSR(x4, x3, x2, x1, x0) = 0 | x0 ^ x1 = 0} = 5/8</code></li>
    <li id="DHFP"><code>{NLFSR(x4, x3, x2, x1, x0) = 1 | x0 ^ x1 = 1} = 5/8</code></li>
  </ul>
  <p id="50G9">Используя это и аппроксимируя NLFSR вероятности, можно добиться определения очередной части ключа.</p>
  <h3 id="UXF8">Линейный шаг</h3>
  <p id="DRsM">Последние 16 бит ключа определяются, если известны все предыдущие. Основываясь на том, что если мы знаем полностью 48 состояние в цикле,то можем записать:</p>
  <figure id="d9uN" class="m_original">
    <img src="https://img1.teletype.in/files/4b/c1/4bc11943-61af-4270-8db5-855441752ef3.png" width="499" />
  </figure>
  <p id="QhAw">Отсюда находим <code>key^48</code> и аналогично <code>key^49 ... key^63</code></p>
  <hr />
  <p id="GNb7">Общая сложность всех теоретических атак - ≈2^52 (≈4503599627370496)</p>
  <h2 id="MlSn">Практические атаки</h2>
  <p id="N1Bb">Здесь я хочу поблагодарить <a href="https://github.com/jamisonderek" target="_blank">Derek Jamison</a> за прекрасные материалы по практическим атакам на KeeLoq</p>
  <h3 id="QeWA">Replay-атака</h3>
  <figure id="VXZr" class="m_column">
    <img src="https://img4.teletype.in/files/f1/49/f149c351-07ba-4de2-ad91-7b1c8a2f9661.png" width="1236" />
  </figure>
  <p id="SjbV">Очень распространённая атака работающая, преимущественно, для статических кодов, и для уявизмых приёмников, которые не проверяют значение счётчика</p>
  <h3 id="hrtX">Клонирование пульта</h3>
  <figure id="qYAy" class="m_column">
    <img src="https://img2.teletype.in/files/5a/2f/5a2f5185-87fd-4498-b619-680a4da622fc.png" width="1200" />
  </figure>
  <p id="esSo">Если мы знаем мануфактурный ключ пульта то без проблем можем сделать копию, которая будет работать, однако делать так не рекомендуется т.к будет конфликт значения счётчика у оригинального пульта и у копии, и в результате при использования двух пультов (оригинального и копии) приёмник может просто отвязать ваш пульт</p>
  <h3 id="EVpD">Future-атака</h3>
  <figure id="IDuB" class="m_column">
    <img src="https://img3.teletype.in/files/6f/47/6f478059-d942-4e1a-abaf-e7f14b29efd1.png" width="1216" />
  </figure>
  <p id="LebV">Если мы знаем мануфактурный ключ пульта то можно воспользоваться логикой работы счётчика и отправить &quot;будущее&quot; значение счётчика (было <code>0001</code> - стало <code>3E91</code>), приёмник может подумать, что пульт &quot;убежал&quot; далеко вперёд и синхронизироваться с переданным значением и штатно работать со следующими значениями (<code>3E92</code>, <code>3E93</code> и т.п). При данной атаке оригинальный пульт полностью рассинхронизируется и дальнейшее его использования не рекомендуется <a href="#esSo">по описанным выше причинам</a>. </p>
  <h3 id="tacj">Rollback-атака</h3>
  <figure id="aopX" class="m_column">
    <img src="https://img2.teletype.in/files/dc/8a/dc8ada19-3fb1-4e2a-83fc-4364837e1689.png" width="1233" />
  </figure>
  <p id="FJ7C">Данная атака весьма редкая, однако всё же возможна с некоторыми приёмниками. Она похожа на Future-атаку, однако вместо последующих значений, мы откатываем состояние счётчика после нескольких использований и приёмник может заново синхронизироваться с этими значениями.</p>
  <h3 id="jCpe">Rolljam-атака</h3>
  <figure id="66PT" class="m_column">
    <img src="https://img1.teletype.in/files/0e/89/0e89ffba-3d7d-4ee7-9c34-4172190432d0.png" width="1231" />
  </figure>
  <p id="KfTJ">Вся суть атаки в том, что вы записываете сигналы с оригинального пульта и не даёте приёмнику получить их (например создавая помехи рядом с приёмником), после чего вы можете использовать записанные сигналы.</p>
  <p id="Ok8c">Однако следует учесть, что почти во всех странах (<a href="https://www.fcc.gov/general/jammer-enforcement" target="_blank">например в США</a>, странах ЕС, <a href="https://www.consultant.ru/document/cons_doc_LAW_34661/acaefaec257669702f20b2a36e96381e17d50f52/" target="_blank">РФ</a>) глушение сигналов является незаконным.</p>
  <h3 id="ckqu">Атака на мануфактурные ключи (KGB attack)</h3>
  <figure id="pPGX" class="m_column">
    <img src="https://img4.teletype.in/files/ff/f5/fff5633b-1266-47a8-98ac-9a313ce4db9f.png" width="1218" />
  </figure>
  <p id="Q0cY">Идея заключается в том, что, возможно, приёмник умеет работать с несколькими мануфактурными ключами, а не только с одним. Если мы отправим <code>fix</code> от оригинального пульта, но закодируем счётчик с помощью другого мануфактурного ключа, то, возможно, оно откроется (обычно эту атаку комбинируют с Future-атакой, потому что вы не знаете, каким должно быть значение счётчика).</p>
  <h3 id="tLCW">Enc00-атака</h3>
  <figure id="me8y" class="m_column">
    <img src="https://img3.teletype.in/files/a2/d2/a2d2f01c-d90c-437a-abb8-579a9f901322.png" width="1408" />
  </figure>
  <p id="GkM9">Атака представляет собой подмену <code>fix</code> оригинального пульта на <code>fix</code> другого пульта (также привязанного к приёмнику) и использование <code>hop</code> с оригинального пульта. </p>
  <p id="4hTT"><strong>Важно, что после подмены, пульт, <code>fix</code> которого использовали, рассинхронизируется и перестаёт работать</strong></p>
  <h3 id="wSBY">Unknown-атака</h3>
  <figure id="BxwY" class="m_column">
    <img src="https://img2.teletype.in/files/1b/99/1b9931cd-d718-4d16-8d36-ac5238574bfc.png" width="1216" />
  </figure>
  <p id="da9s">Суть в том, что, когда приёмник не может декодировать <code>hop</code>, он использует значение 0. Для универсальных приёмников есть вероятность, что они откроются при значении 0.</p>
  <h2 id="5cd7">Заключение</h2>
  <p id="LRM8">Не смотря на все описанные выше уязвимости, KeeLoq, также как и Mifare Classic (чей шифр Crypto-1 был взломан в далёких 2000x) остаётся популярным выбором для бюджетных систем безопасности (автоматические ворота, гаражные двери и т.п). Возможно в будущем все производители перейдут на более стойкие алгоритмы шифрования (например на AES), как это сделали Beninca и Hormann</p>
  <p id="3kdg">Кстати, имея на руках мануфактурный ключ вы можете &quot;поиграться&quot; с KeeLoq онлайн в <a href="http://li0ard.rest/apps/keeloq" target="_blank">моём мини-приложении</a>.</p>
  <h3 id="34Ux">Использованные материалы</h3>
  <ol id="k2eR">
    <li id="4Jp7"><a href="https://github.com/li0ard/keeloq/" target="_blank">Моя собственная библиотека для работы с KeeLoq</a></li>
    <li id="vDmX"><a href="https://github.com/DarkFlippers/unleashed-firmware/" target="_blank">Исходный код Unleashed Firmware для Flipper Zero</a></li>
    <li id="oj28"><a href="https://github.com/jamisonderek/flipper-zero-tutorials/tree/main/subghz/apps/rolling-flaws" target="_blank">Материалы Derek Jamison по KeeLoq и его приложение &quot;SubGHZ Rolling Flaws&quot;</a></li>
  </ol>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/reviving_t5577</guid><link>https://blog.li0ard.rest/reviving_t5577?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/reviving_t5577?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Чиним T5577 с помощью proxmark3</title><pubDate>Wed, 09 Apr 2025 21:27:32 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/42/99/429977fd-5669-48e4-bde1-b429a5eac76c.png"></media:content><category>proxmark3</category><description><![CDATA[<img src="https://img4.teletype.in/files/77/8c/778c5307-c3eb-4b33-ab76-bef2cb61069c.png"></img>Однажды экспериментировав с конфигурацией метки T5577, я получил в результате метку (даже две), которая нормально не определялась через lf search, либо определялась как Valid Indala ID found!.]]></description><content:encoded><![CDATA[
  <p id="6PXB">Однажды экспериментировав с конфигурацией метки T5577, я получил в результате метку (даже две), которая нормально не определялась через <code>lf search</code>, либо определялась как <code>Valid Indala ID found!</code>.</p>
  <figure id="j9qu" class="m_original" data-caption-align="center">
    <img src="https://img4.teletype.in/files/77/8c/778c5307-c3eb-4b33-ab76-bef2cb61069c.png" width="678" />
    <figcaption>Valid Indala ID found!, а ведь метка была EM-Marine....</figcaption>
  </figure>
  <figure id="bxEK" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/b5/97/b5977b3a-c02b-4835-ad66-11eb4dda1698.png" width="1041" />
    <figcaption>А теперь определяется как ASK и PSK одновременно...</figcaption>
  </figure>
  <h2 id="lNf3">Скорее жив чем мёртв?</h2>
  <p id="4tlB">Учитывая, что метка всё-таки как-то определялась, то необходимость использования команды <code>lf tune</code> отпадала сама собой.</p>
  <p id="UwNK">Поэтому необходимо было определить, может ли proxmark3 считать конфигурацию чипа через <code>lf t55xx [detect / p1detect]</code>. Введя команду, я получил следующий ответ:</p>
  <pre id="lnnA">[!] Could not detect modulation automatically. Try setting it manually with &#x27;lf t55xx config&#x27;</pre>
  <p id="jqyi">Что ж, ещё не всё потеряно...</p>
  <h2 id="zqOZ">Принудительное оживление</h2>
  <p id="9g9H">Следующим шагом была попытка перезаписать нулевой блок метки, отвечающий за конфигурацию. Я делал это следующими командами:</p>
  <pre id="iDxQ">lf t55xx write -b 0 -d 000880E0 -t
lf t55xx write -b 0 -d 000880E0 --r0 -t
lf t55xx write -b 0 -d 000880E0 --r1 -t
lf t55xx write -b 0 -d 000880E0 --r2 -t
lf t55xx write -b 0 -d 000880E0 --r3 -t</pre>
  <p id="3L7P">После чего я проверил метку командой <code>lf t55xx detect</code> и... видимо, одна из команд сработала:</p>
  <figure id="XJp7" class="m_column" data-caption-align="center">
    <img src="https://img3.teletype.in/files/a9/f4/a9f49b9a-bbc3-4a61-8a0e-be40e6e6155b.png" width="402" />
    <figcaption>Метку удалось вернуть к работе на конфигурации по умолчанию</figcaption>
  </figure>
  <p id="VPXN">После чего я попробовал записать на метку какой нибудь рандомный EM-Marine ID и считать его, это сработало!</p>
  <figure id="V1GQ" class="m_original" data-caption-align="center">
    <img src="https://img4.teletype.in/files/3a/fb/3afb5452-b162-49c7-b6c7-71f2952fec5b.png" width="635" />
    <figcaption>Метка заработала в стандарте EM-Marine</figcaption>
  </figure>
  <h2 id="QRWu">Заключение</h2>
  <p id="9a3T">Получилась весьма короткая статья, но я думаю, она кому-нибудь да пригодится.</p>
  <p id="8uxe">Вообще, восстановление работоспособности T5577 - это довольно-таки индивидуальная тема. То, что работает в одних случаях, может не работать в других.</p>
  <figure id="MIwg" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/78/62/78621bca-cc25-443c-a549-36d4ce69c489.png" width="764" />
    <figcaption>Многообразие решений на форуме Dangerous Things :)</figcaption>
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/blindedid</guid><link>https://blog.li0ard.rest/blindedid?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/blindedid?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Blinded ID в Session и что с ними не так</title><pubDate>Tue, 20 Aug 2024 10:30:28 GMT</pubDate><category>Криптография</category><description><![CDATA[Blinded ID (aka &quot;слепые&quot; айди и т.п) - алгоритм деривации публичного ключа (ID) пользователя для открытых групп в Session, для того чтобы скрыть настоящий ID пользователя, тем самым обеспечить некую приватность.]]></description><content:encoded><![CDATA[
  <p id="fqfi">Blinded ID (aka &quot;слепые&quot; айди и т.п) - алгоритм деривации ID пользователя, который является публичным ключом Curve25519, для открытых групп в <a href="http://getsession.org" target="_blank">Session</a>, для того чтобы скрыть настоящий ID пользователя.</p>
  <p id="8uQF">Всего существует две версии данного алгоритма:</p>
  <ol id="6jQf">
    <li id="ugY5">Legacy версия (ID начинается с префикса 15)</li>
    <li id="PKVB">Новая версия (ID начинается с префикса 25)</li>
  </ol>
  <p id="dMlP">На данный момент полностью реализованной является legacy версия, а поддержка новой версии есть только в <a href="https://github.com/oxen-io/libsession-util/blob/dev/src/blinding.cpp" target="_blank">libsession</a> и вроде как планируется в <a href="https://github.com/oxen-io/session-pysogs/pull/220" target="_blank">pysogs</a>.</p>
  <section style="background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);">
    <p id="jNcZ"><strong>Важно</strong>: Все математические операции выполняются в поле <em>F</em>p кривой ed25519, манипуляции со скалярами (редуцирование, инвертирование) выполняются в поле <em>F</em>n (order field)</p>
  </section>
  <h2 id="EQRZ">Один ключ -&gt; два ключа. Legacy версия.</h2>
  <h3 id="4Id9">Алгоритм</h3>
  <p id="751h">Для работы алгоритма нам понадобится:</p>
  <ul id="JwS8">
    <li id="FDkU">ID пользователя</li>
    <li id="m5M4">Публичный ключ сервера</li>
  </ul>
  <p id="mV2l">Сам алгоритм:</p>
  <ol id="f5SJ">
    <li id="BCUN">Генерируем т.н &quot;blinding factor&quot;: хэшируем с помощью Blake2B публичный ключ сервера и редуцируем результат.<br />Обозначим, как <code>k</code>.</li>
    <li id="Njow">Из ID пользователя убираем префикс 05 и переводим его в ed25519.<br />Обозначим, как <code>A</code>.</li>
    <li id="8RHt">Умножаем <code>k</code> на <code>A</code> и получаем ключ ed25519, который является одним из возможных &quot;слепых&quot; id.<br />Обозначим, как <code>kA</code>.</li>
  </ol>
  <figure id="1mos" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/78/69/78693505-fa28-4cc3-852c-418b9b00d683.png" width="661" />
    <figcaption>Примерная запись алгоритма</figcaption>
  </figure>
  <h3 id="uY6p">Сломанное условие</h3>
  <p id="eCpq">Как следует из заголовка, legacy версия генерирует 2 возможных &quot;слепых&quot; ID.</p>
  <p id="Bgil">Второй возможный ID (<code>kA2</code>) генерируется на основе <code>kA</code>, только с <a href="https://github.com/theinfinityway/session_id/blob/main/src/index.ts#L98" target="_blank">изменённым</a> (XOR на 128) sign битом.</p>
  <p id="T5D0">И для того чтобы выяснить какой из двух ключей следует использовать, pysogs <a href="https://github.com/oxen-io/session-pysogs/blob/dev/sogs/crypto.py#L101-L117" target="_blank">предлагает</a> следующий код:</p>
  <pre id="sU4t" data-lang="python">if kA[31] &amp; 0x80:
    return kA[0:31] + bytes([kA[31] &amp; 0x80])</pre>
  <p id="O6vu">Однако это условие <a href="https://github.com/oxen-io/session-pysogs/issues/221" target="_blank">совершенно не работает</a>, поэтому в реализации клиентов пошли другим путём - <a href="https://github.com/oxen-io/session-desktop/blob/eb463a49baa79ffcb6a54362d34860f7fc358e11/ts/session/apis/open_group_api/sogsv3/sogsBlinding.ts#L161-L190" target="_blank">получение</a> &quot;слепого&quot; id из приватного ключа, вместо того чтобы получать его из публичного ключа. Таким образом сервер не знает наверняка, какой ключ из двух следует использовать, и надеется на клиент в результате чего в теории может произойти раздвоение пользователя.</p>
  <figure id="Q2Qv" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/91/04/91042e9b-b7d9-4a6b-a68a-734b943df30a.png" width="683" />
    <figcaption>Примерная запись условия</figcaption>
  </figure>
  <h3 id="nIr1">Обратимая необратимость</h3>
  <p id="hhGD">Так же немало важным является то, что legacy версия (а фактически единственная версия на момент написания статьи) является обратимой вопреки всем заявлениям.</p>
  <p id="C1xo">Для этого достаточно инвертировать полученный ранее &quot;blinding factor&quot;, умножить его на слепой id, полученный ключ перевести в Curve25519 и в результате мы имеем ID пользователя.</p>
  <figure id="4HQ6" class="m_original" data-caption-align="center">
    <img src="https://img3.teletype.in/files/20/fd/20fd6a13-f4fb-4996-bd6a-677ab853c674.png" width="670" />
    <figcaption>Примерная запись алгоритма</figcaption>
  </figure>
  <h2 id="4XKD">Один ключ -&gt; один ключ. Новая версия</h2>
  <p id="Rc2T">На момент написания статьи эта версия реализована только в libsession, и поэтому может поменяться.</p>
  <p id="gYKy">Самое главное отличие этой версии от legacy в том, что в процессе генерации &quot;blinding factor&quot; принимает участие ID пользователя вместе с публичным ключом сервера, что, в свою очередь, исключает возможность обратимости, как это было с legacy версией.</p>
  <p id="E64O">Т.е алгоритм следующий:</p>
  <ol id="pZRm">
    <li id="4AOy">Генерируем &quot;blinding factor&quot;: хэшируем с помощью Blake2B ID пользователя (вместе с префиксом) и публичный ключ сервера и редуцируем результат.<br />Обозначим, как <code>k</code>.</li>
    <li id="uYJ3">Переводим ID пользователя из Curve25519 в ed25519.<br />Обозначим, как <code>A</code>.</li>
    <li id="3yYP">Умножаем скаляр <code>k</code> на <code>A</code> </li>
  </ol>
  <p id="DnGh">На выходе получаем единственный Blinded ID для конкретного пользователя на конкретном сервере.</p>
  <figure id="e2eb" class="m_column" data-caption-align="center">
    <img src="https://img4.teletype.in/files/b2/12/b212990b-309b-41a2-b944-bc9c45a51a9e.png" width="677" />
    <figcaption>Примерная запись алгоритма</figcaption>
  </figure>
  <h2 id="1g9d">Ссылки</h2>
  <p id="MsGC"><a href="https://github.com/theinfinityway/session_id" target="_blank">Моя библиотека &quot;Session ID&quot;</a></p>
  <p id="MZUq"><a href="https://github.com/sessionjs" target="_blank">Проект Session.js</a></p>
  <p id="DAGm"><a href="https://github.com/VityaSchel/bunsogs" target="_blank">Проект bunsogs</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/findkey</guid><link>https://blog.li0ard.rest/findkey?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/findkey?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Расчёт параметров МСК</title><pubDate>Fri, 26 Jul 2024 06:31:02 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/c7/f3/c7f349bb-bfdf-4d23-871f-a079a0eca839.png"></media:content><description><![CDATA[<img src="https://img3.teletype.in/files/a6/98/a698fc32-0b84-4d31-bed8-f5976aebc4ee.png"></img>Под МСК (Местная система координат) подразумевается система координат построенная независимо от государственной системы координат (чаще всего на основе СК-42 или СК-63) и для конкретного субъекта Российской Федерации.]]></description><content:encoded><![CDATA[
  <p id="Aw6b">Под МСК (Местная система координат) подразумевается система координат построенная независимо от государственной системы координат (чаще всего на основе СК-42 или СК-63) и для конкретного субъекта Российской Федерации.</p>
  <blockquote id="MwJ3">Многие программы ГИС позволяют реализовать работу в МСК непосредственно. Так, в QGIS и в MapInfo Pro любая проекция может быть дополнена аффинным преобразованием, а в Global Mapper конформные проекции дополняются разворотом.</blockquote>
  <h2 id="lR1F">Постановка задачи</h2>
  <p id="yafh">Имеется 6-7 пунктов, для которых известны координат X и Y в ГСК и в МСК. Необходимо подобрать параметры проекции представляющую МСК в ГИС.</p>
  <blockquote id="dQzV">При подборе параметров предполагается использовать один из пунктов в качестве центральной точки преобразования.</blockquote>
  <h2 id="oAb7">Подготовка данных</h2>
  <p id="0W1q">Имеем 2 каталога координат. Один содержит координаты пунктов в государственной системе, а именно в СК-42, 4 зона (EPSG:28404) в формате <code>Y X</code>:</p>
  <pre id="f8wC">4645997.49 5768521.60
4661392.15 5770068.91
4650059.09 5783332.41
4634241.37 5778952.22
4631481.69 5764570.61
4642125.18 5754643.12
4655952.19 5757337.28</pre>
  <p id="bBPW">А второй координаты в местной системе:</p>
  <pre id="bv3g">67266.64 30088.40
82697.29 31184.27
71759.40 44771.50
55822.67 40857.06
52643.65 26564.42
62990.64 16331.35
76888.20 18619.57</pre>
  <p id="i43U">Каждая строка в обоих файлах соответствует одному и тому же пункту. В первой строке центральный пункт системы.</p>
  <blockquote id="xBbz">Очень важно помнить, что с точки зрения математической картографии МСК остаётся проекцией Гаусса-Крюгера и наследует её искажения. Поэтому важно знать, на какой именно ГСК основана МСК. Зачастую это заранее неизвестно, и приходится проводить предварительное исследование для выяснения этого вопроса.</blockquote>
  <p id="yjkL">В нашем примере мы предполагаем, что это либо СК-42, 4 зона, либо СК-63, район C. Создадим также каталог в СК-63:</p>
  <figure id="yAdU" class="m_column">
    <img src="https://img3.teletype.in/files/a6/98/a698fc32-0b84-4d31-bed8-f5976aebc4ee.png" width="1191" />
    <figcaption>cs2cs online by MyGeodata Cloud</figcaption>
  </figure>
  <pre id="nka5">330797.453706 5755981.4752
346208.044264 5757327.09534
335051.738244 5770735.14419
319180.795365 5766563.18288
316233.724465 5752221.19702
326744.900981 5742157.23182
340603.316544 5744670.19105</pre>
  <h2 id="Q4vH">Получение параметров</h2>
  <p id="I2Jt">Для вычислений воспользуемся моей <a href="https://geo.li0ard.rest/keys" target="_blank">утилитой</a>.</p>
  <p id="RKDq">Для начала необходимо определить базовую ГСК, сделаем это с помощью координатных невязок.</p>
  <p id="I64Q">Загружаем каталог в СК-42 и в МСК в утилиту, и получаем значение невязок:</p>
  <figure id="UaNY" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/5d/6c/5d6cb960-ef51-47d1-acf3-9663cabbcacd.png" width="553" />
    <figcaption>Невязки для СК-42</figcaption>
  </figure>
  <p id="6wRz">Теперь вычислим невязки аналогичным способом для СК-63:</p>
  <figure id="31Tt" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/9f/a1/9fa1830a-5eef-4dcb-b3ba-68fcbd7d8a4e.png" width="562" />
    <figcaption>Невязки для СК-63</figcaption>
  </figure>
  <p id="aYAm">Сравнив невязки мы понимаем, что базовая ГСК - СК-63</p>
  <p id="Ho4F">Получаем параметры 2D преобразования Гельмерта:</p>
  <figure id="wkIL" class="m_original">
    <img src="https://img4.teletype.in/files/7b/8e/7b8e85ad-b303-4c69-9679-979e5bd22b97.png" width="564" />
  </figure>
  <p id="RfmG">А также параметры Аффинного параметрического преобразования:</p>
  <figure id="BeQr" class="m_original">
    <img src="https://img1.teletype.in/files/87/c3/87c3aab6-23ac-4af7-9f55-127a0215b17d.png" width="550" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/anticryptopro_p3</guid><link>https://blog.li0ard.rest/anticryptopro_p3?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/anticryptopro_p3?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Побег из КриптоПро (ч.3)</title><pubDate>Sun, 23 Jun 2024 12:06:45 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/56/b9/56b95756-5be1-44d6-be7a-8b423726351e.png"></media:content><category>Криптография</category><description><![CDATA[<img src="https://img2.teletype.in/files/9d/d5/9dd5b7e8-5018-4f4b-bfdc-c2b32875e02b.png"></img>В прошлых частях я разбирался с транспортным ключевым контейнером от КриптоПро (он же PFX, PKCS12, P12). В этой статье пойдёт речь о собственном формате ключевого контейнера КриптоПро (те самые 6 файлов .key)]]></description><content:encoded><![CDATA[
  <p id="7ST7">В прошлых частях (<a href="/anticryptopro">клик</a>, <a href="/anticryptopro_p2">клик</a>) я разбирался с транспортным ключевым контейнером от КриптоПро (он же PFX, PKCS12, P12). В этой статье пойдёт речь о собственном формате ключевого контейнера КриптоПро (те самые 6 файлов .key)</p>
  <figure id="GY2O" class="m_original" data-caption-align="center">
    <img src="https://img2.teletype.in/files/9d/d5/9dd5b7e8-5018-4f4b-bfdc-c2b32875e02b.png" width="598" />
    <figcaption>Проприетарный контейнер КриптоПро</figcaption>
  </figure>
  <p id="cZkW">Вообще тема данной статьи не нова, ещё в далёком 2016 года Михаил Куликов (он же shukan) написал <a href="https://habr.com/ru/articles/275039/" target="_blank">статью</a> на Хабре в которой он предоставил программу на C, которая вытаскивала ключ для ГОСТ 34.10-2001. Чуть позже благодаря сообществу появилась версия и для ГОСТ 34.10-2012. Однако пробуя запустить все эти утилиты для контейнера ГОСТ 34.10-2012 512 бит сгенерированного в КриптоПро CSP 5.0, утилиты выдавали ошибку. Собственно это и стало мотивацией разобраться как там всё устроено и написать свою программу.</p>
  <h2 id="bApX">Как там всё устроено</h2>
  <h3 id="naQk">Файл masks.key</h3>
  <figure id="GQHb" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/58/86/58863e2a-852e-432a-a347-ccb0a4fdd410.png" width="812" />
    <figcaption>Содержимое masks.key</figcaption>
  </figure>
  <p id="MkTb">Содержит в себе три Octet String, которые в свою очередь являются маской ключа (32 байта для 256 бит, 64 для 512), солью для деривации пароля и контрольной суммы маски соответственно.</p>
  <h3 id="vjGc">Файл primary.key</h3>
  <figure id="qmTL" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/19/b7/19b7ab2d-7ea5-42dc-9f32-49447d9dfef1.png" width="822" />
    <figcaption>Содержимое primary.key</figcaption>
  </figure>
  <p id="MEyb">Содержит зашифрованный приватный ключ (32 байта для 256 бит, 64 для 512), который после расшифровки надо разделить по модулю на поле Q эллиптической кривой ключа.</p>
  <h3 id="auGh">Файл header.key</h3>
  <figure id="3mQn" class="m_column" data-caption-align="center">
    <img src="https://img2.teletype.in/files/91/6a/916ad450-13e0-4c25-8b99-72ad41482b51.png" width="848" />
    <figcaption>Содержимое header.key</figcaption>
  </figure>
  <p id="7Y70">Содержит всю информацию о контейнере: Сертификат, свойства ключа, параметры эллиптической кривой и алгоритма хэширования, первые 8 байт публичного ключа, а также контрольные суммы.</p>
  <h2 id="XLcJ">Получаем приватный ключ</h2>
  <p id="Mvlh">Для получения приватного ключа необходимо выполнить следующие шаги:</p>
  <ol id="FOPy">
    <li id="yeOC">Получение так ключа хранения с помощью CPKDF (CryptoPro Key Derivation Function) в которую передаётся пароль и соль из файла masks.key.</li>
    <li id="PJTR">Расшифровка основного ключа с помощью ГОСТ 28147-89 (Магма) в ECB режиме с параметрами набора Z от ТК-26</li>
    <li id="bZZo">Деление по модулю расшифрованного ключа на маску</li>
    <li id="9u5A">Подстановка результата в ASN.1 конструкцию приватного ключа</li>
  </ol>
  <p id="csSv">Подводя итоги могу сказать, что это была достаточно сложная работа, отнявшая у меня годовой запас кофе и не только :) Однако я полностью доволен результатом.</p>
  <p id="UHAM">Также хочу выразить благодарность Савелию Красовскому за его утилиту go-decrypto-pro, которая стала основной для моей программы, и VovkaTM за консультации и прочую помощь.</p>
  <h2 id="0Kh6">Ссылки</h2>
  <p id="uTre">Программа - <a href="https://github.com/li0ard/ckey" target="_blank">https://github.com/li0ard/ckey</a></p>
  <p id="8yLV">Утилита go-decrypto-pro - <a href="https://github.com/savely-krasovsky/go-decrypto-pro" target="_blank">https://github.com/savely-krasovsky/go-decrypto-pro</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/dump_l3_cdm</guid><link>https://blog.li0ard.rest/dump_l3_cdm?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/dump_l3_cdm?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Дампим L3 CDM из AVD</title><pubDate>Thu, 28 Dec 2023 18:22:08 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/e8/19/e819e595-bef4-4a3c-a4be-d0464621a394.png"></media:content><category>Криптография</category><description><![CDATA[<img src="https://img4.teletype.in/files/75/21/7521468a-4237-40c3-9826-c65d9a3e506b.png"></img>Автор статьи не несёт ответственности за всё ниже сказанное. Вся информация ниже опубликована в учебно-ознакомительных целях. Все действия выполняйте на свой страх и риск.]]></description><content:encoded><![CDATA[
  <blockquote id="I4bS">Автор статьи не несёт ответственности за всё ниже сказанное. Вся информация ниже опубликована в учебно-ознакомительных целях. Все действия выполняйте на свой страх и риск.</blockquote>
  <p id="Vz0r">Если вы решили получить 2 магических файла для расшифровки DRM контента и у вас нету Android устройства с root, как в моём случае, то можно использовать эмулятор, который встроен в обычную Android Studio.</p>
  <p id="B4Rw">Для начала нам необходимо создать конфигурацию нашего устройства, для это заходим в Device manager и нажимаем Create Device</p>
  <p id="1aZM"></p>
  <figure id="p6Pq" class="m_column">
    <img src="https://img4.teletype.in/files/75/21/7521468a-4237-40c3-9826-c65d9a3e506b.png" width="1365" />
    <figcaption>Изображения взято с forum.videohelp.com</figcaption>
  </figure>
  <p id="TjNo">Далее выбираем марку нашего устройства (например я выбирал Pixel 6)</p>
  <figure id="MmWO" class="m_column">
    <img src="https://img4.teletype.in/files/7c/24/7c246c84-09fe-4693-b70e-17c85176469e.png" width="1365" />
  </figure>
  <p id="15Bx">Сейчас нам необходимо сделать первый важный шаг: выбрать версию Android с Google APIs и без Google Play (иначе у вас не будет рута в adb). Лично я выбрал Android 9.0 Pie</p>
  <figure id="7IQ9" class="m_column">
    <img src="https://img2.teletype.in/files/93/7d/937dca24-d99b-454e-9f89-cc0b91ab33e4.png" width="1365" />
  </figure>
  <p id="tWGu">Далее идут настройки, которые можно оставить без изменений. Запускаем наше устройство.</p>
  <figure id="KDNN" class="m_column">
    <img src="https://img3.teletype.in/files/2c/1c/2c1c2bd3-4b3b-44a3-9d5a-d75b48653b25.png" width="1365" />
  </figure>
  <h3 id="Wgen">Установка Frida</h3>
  <p id="RHMC">Открывыем терминал и пишем:</p>
  <pre id="sv2s">pip install frida frida-tools</pre>
  <figure id="PDb6" class="m_column">
    <img src="https://img4.teletype.in/files/37/4f/374f137b-4055-411c-8c4f-683bcd18d466.png" width="1349" />
  </figure>
  <p id="BveF">Далее <a href="https://github.com/frida/frida/releases" target="_blank">заходим на официальную страницу проекта</a> и скачиваем frida-server для вашей версии клиента на компьютере</p>
  <p id="3I90">В терминале пишем:</p>
  <pre id="3ZHt">adb devices</pre>
  <p id="bXmS">Если у вас всё хорошо то отобразится примерно следующая картина:</p>
  <figure id="utCZ" class="m_column">
    <img src="https://img4.teletype.in/files/bd/92/bd92d226-dee7-4643-ac94-9f7fc0573754.png" width="1365" />
  </figure>
  <p id="GxAe">Теперь настала очередь загрузить frida-server на наше устройство через терминал:</p>
  <pre id="iPW0">adb push frida-server /sdcard
adb shell
su
mv /sdcard/frida-server /data/local/tmp
chmod +x /data/local/tmp/frida-server
/data/local/tmp/frida-server</pre>
  <figure id="Y30u" class="m_column">
    <img src="https://img3.teletype.in/files/af/e6/afe6aac8-6a0e-4419-96be-e4afe6735a4f.png" width="1352" />
  </figure>
  <p id="w7Ra">Теперь не закрывайте этот терминал и можете приступать к следующему шагу.</p>
  <h3 id="lvvo">Установка дампера и получение ключей</h3>
  <p id="lCqu">Переходим по <a href="https://github.com/lollolong/dumper" target="_blank">ссылке</a>, скачиваем ZIP архив и разархивируем его.</p>
  <figure id="nVk7" class="m_column">
    <img src="https://img4.teletype.in/files/b6/31/b631c2f1-cebb-4500-a15d-dc27e89a5e03.jpeg" width="452" />
  </figure>
  <p id="Bkjd">После в терминале пишем:</p>
  <pre id="NMf8">python dump_keys.py</pre>
  <p id="k3jI">Должно написать &quot;Hooks completed&quot; и после этого необходимо начать просмотр, какого нибудь защищенного через Widevine контента (например <a href="https://bitmovin.com/demos/drm" target="_blank">демо страница BitMovin</a>). Во время просмотра будут сообщения в консоли и в результате появится директория key_dumps в которой будут 2 файла с приватным ключом и идентификатором устройства.</p>
  <figure id="ifH9" class="m_column">
    <img src="https://img3.teletype.in/files/65/0d/650d4fb1-a3da-457e-b8e8-62b430b8e76d.png" width="1365" />
  </figure>
  <h3 id="brpQ">Ссылки</h3>
  <p id="NhFJ">Оригинальная статья - https://forum.videohelp.com/threads/408031-Dumping-Your-own-L3-CDM-with-Android-Studio</p>
  <p id="tT8H">Мой телеграм канал - https://t.me/li0ard_notes (полумёртвое создание однако)</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://blog.li0ard.rest/gia9_pseudosecurity</guid><link>https://blog.li0ard.rest/gia9_pseudosecurity?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard</link><comments>https://blog.li0ard.rest/gia9_pseudosecurity?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=li0ard#comments</comments><dc:creator>li0ard</dc:creator><title>Безопасность устного собеседования (ГИА-9)</title><pubDate>Mon, 03 Apr 2023 14:53:40 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/0d/92/0d92ce57-388b-4ebe-9ab0-503a3b1d865f.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/d8/4f/d84ff49c-af86-4f57-b0f8-f43af82ca6b2.png"></img>Все ниже сказанное является мнением автора и ни к чему не призывает даже если вам так показалось. Вас предупредили :)]]></description><content:encoded><![CDATA[
  <blockquote id="EVVc">Все ниже сказанное является мнением автора и ни к чему не призывает даже если вам так показалось. Вас предупредили :)</blockquote>
  <hr />
  <p id="G1et">В этой статье пойдет речь о том, как устроен один из экзаменов ГИА-9, об устном собеседовании по русскому языку, а именно про так называемую безопасность, ведь в описании программы сказано, что подменить аудиозапись экзамена невозможно.</p>
  <h3 id="mDIQ">Программное обеспечение</h3>
  <p id="O6hL">В моем регионе используется программа Russo, которую я добыл с сайта одного образовательного учреждения</p>
  <figure id="gIcC" class="m_column">
    <img src="https://img2.teletype.in/files/d8/4f/d84ff49c-af86-4f57-b0f8-f43af82ca6b2.png" width="1280" />
    <figcaption>Главный экран с тестовыми данными</figcaption>
  </figure>
  <figure id="i3ZM" class="m_column">
    <img src="https://img2.teletype.in/files/5a/94/5a94c292-074d-49ef-978c-d7c917f914ce.png" width="1280" />
    <figcaption>Экран самого собеседования</figcaption>
  </figure>
  <p id="20oQ">После нажатия на кнопку программа создает папку и ZIP архив с идентичным названием и содержимым. Структура названия папки/архива: <code>01-ДДММГГГГ-000000-код школы-номер аудитории</code>.</p>
  <figure id="bdYt" class="m_original">
    <img src="https://img3.teletype.in/files/aa/3a/aa3afc53-0859-47d3-b611-4fed52c65143.png" width="552" />
    <figcaption>Содержимое архива</figcaption>
  </figure>
  <p id="7cy4">В архиве мы можем видеть заголовочный файл и аудиозаписи участников по их порядковым номерам.</p>
  <h3 id="Wiv9">Псевдобезопасность</h3>
  <p id="sTW7">Файлы mp3 мы рассматривать не будем, т.к это самые обычные mp3&#x27;шки. Меня интересует заголовочный csv&#x27;шный файл. Открыв его, мы можем увидеть следующие данные:</p>
  <figure id="sAv7" class="m_original">
    <img src="https://img1.teletype.in/files/8c/03/8c03159b-d0b5-44eb-b6be-1f51746aa07e.png" width="358" />
    <figcaption>Содержимое 01-03042023-000000-111111-001.csv</figcaption>
  </figure>
  <p id="pGTn">Первая строка тут что то вроде magic заголовка, потом на следующей строке идет дата проведения, город, код учреждения, название учреждение, номер аудитории. Потом идет перечисление файлов участников и кол-во участников, я бы хотел остановиться на перечислении файлов. Как мы можем видеть тут записано название файла, дата и время (с точностью до секунд) создания, длина файла и CRC-32 сумма и всё. Лично я считаю, что это не спасает от подмены файлов, ведь можно оставить имя и отметку о создании файла, подменить файл и вписать новую длину и контрольную сумму, которая рассчитывается очень легко.</p>
  <figure id="j8my" class="m_column">
    <img src="https://img1.teletype.in/files/8a/e2/8ae2b934-319d-4c01-99ee-46f4d9d93384.png" width="712" />
    <figcaption>Сайт из первой ссылки в гугле</figcaption>
  </figure>
  <h3 id="IRR9">Что же делать?</h3>
  <p id="F9a0">Я считаю, что необходимо переработать данную систему и сделать например так, чтобы программа подписывала detached подписью (например тем же ГОСТ&#x27;овским сертификатом <a href="https://open-dpo.obrnadzor.gov.ru/data/manual/ceritficate_install_man.pdf" target="_blank">подписанным УЦ ФРДО</a>) файл аудиозаписи, а в заголовочный файл можно было бы вносить значение этой самой подписи. Позже при проверке программа бы проверяла подпись на то кем она сделана и сравнивала бы её значение с заголовочным файлом.</p>

]]></content:encoded></item></channel></rss>