Ключи Code, вопросы по использованию

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

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

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

Заранее спасибо!

Re: Ключи Code, вопросы по использованию

На вопросы данного топика ранее были даны ответы по почте.
Подводя краткий итог, выкладываю их тут:

Neekeetos пишет:

Подскажите пожалуйста где найти описание возможностей загружаемого кода

Вся имеющаяся документация по нашим ключам (включая модели Code и их возможности) доступна для скачивания с нашего сайта, а также находится в папке «\Doc» (по умолчанию: «%Program Files%\Guardant\Guardant 6\%Public Code%\Doc\») установленного комплекта разработчика.

Neekeetos пишет:

- Могу ли я создать ячейки в ключе, которые доступны для записи/чтения из загружаемого в ключ кода, но недоступны при вызовах внешнего апи ключа из приложения?

Да. Например, прошив в ключ защищенную ячейку с активированными сервисами – «Чтение данных. Чтение по паролю» и «Обновление данных» и храня пароли на чтение и обновление в загружаемом коде. Таким образом, можно используя соответствующие пароли прочитать или записать некоторые данные в защищенную ячейку из загружаемого кода (при помощи функций - GcaPI_Read и GcaPI_Update).

Neekeetos пишет:

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

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

1)      Сгенерировать сеансовые данные (далее СД) при помощи функции GccaGetRandom;
2)      Зашифровать СД при помощи аппаратного алгоритма AES128;
3)      Передать зашифрованные СД (далее З-СД) из загружаемого кода непосредственно в приложение и хранить их там;
4)      В нужный момент из кода приложения передать З-СД обратно в загружаемый код для дешифрации;
5)      Использовать СД по назначению.

Neekeetos пишет:

- каков ресурс перезаписи отдельных защищаемых ячеек в ключе? могу я их перезаписать, скажем, 100 000 раз?, влияют ли записи в них на ресурс соседних ячеек? Если да, то как?

Данный вопрос был подробно рассмотрен тут.

Re: Ключи Code, вопросы по использованию

Антон Тихиенко пишет:

Данный вопрос был подробно рассмотрен тут.

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

Re: Ключи Code, вопросы по использованию

Neekeetos пишет:

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

Как я и указал в своем предыдущем посте:

Антон Тихиенко пишет:

На вопросы данного топика ранее были даны ответы по почте.

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


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

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

Для того чтобы в общем случае предложенная схема была именно сеансовой – нужно после генерации случайности с помощью GccaGetRandom просто сохранять ее внутри ключа в переменную объявленную как NO_INIT. Такие переменные сохраняются в области RAM, которая не перезатирается между вызовами и сохраняет свое состояние от подключения до отключения ключа. И код внутри ключа получает возможность контролировать тот ли это сеанс.

(2012-04-09 20:18:14 отредактировано Denis)

Re: Ключи Code, вопросы по использованию

Можно выделить три основных способа хранения данных в ключе:

1. Постоянные ячейки памяти ключа (доступны с помощью GcaPI_Read и GcaPI_Update).

  + Сохраняют значение между инициализациями ключа (например при потере питания).
  + Не анализируются из вне.

  - Не предназначены для очень частого изменения.
  - Работают медленнее, чем оперативная память ключа, из-за перезаписи flash-памяти.

2. Оперативная память ключа (“NO_INIT”-переменные).

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

  - (!) «Обнуление» содержимого даже при кратковременной потере питания ключа (например, при плохом контакте USB или намеренном передёргивании ключа во время работы ПО).

3. Внешний зашифрованный контекст.
Т.е. данные хранятся в памяти самой программы в зашифрованном состоянии. Расшифровываться и использоваться они будут ТОЛЬКО внутри ключа. Обновлённые данные снова будут возвращаться в программу в зашифрованном виде.

  + Данные не «обнуляются» при потере питания ключа.
  + Можно хранить больший объём данных.
  + Нет лимита на кол-во изменений данных.

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

Если считать, что хранимые третьим способом данные актуальны только во время выполнения программы (сеансовые данные), то для борьбы с анализом контекста (и частично с его сохранением и подменой) можно:
1. Шифровать контекст на ключе обновляемом при каждом запуске программы, противодействуя накоплению таблицы "вопрос-ответ".
2. Подмешивать в контекст случайные данные, добавив дополнительное поле в описывающию его структуру, делая одинаковые контексты различными для внешнего наблюдателя.

Сеансовый ключ можно хранить в постоянной ячейке памяти и при каждом старте программы вызывать функцию, обновляющую его на основе предыдущего значения этого ключа.
Самая простая схема (но не самая устойчивая к поиску постоянного ключа, поэтому требует доработки):
    x = A(x, k), где
    x - неизвлекаемый обновляемый ключ,
    A - криптоалгоритм,
    k - неизвлекаемый постоянный ключ.

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

Пейте сладкий чай!

Re: Ключи Code, вопросы по использованию

Антон Тихиенко пишет:

Для того чтобы в общем случае предложенная схема была именно сеансовой – нужно после генерации случайности с помощью GccaGetRandom просто сохранять ее внутри ключа в переменную объявленную как NO_INIT. Такие переменные сохраняются в области RAM, которая не перезатирается между вызовами и сохраняет свое состояние от подключения до отключения ключа. И код внутри ключа получает возможность контролировать тот ли это сеанс.

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

Пейте сладкий чай!

Re: Ключи Code, вопросы по использованию

Neekeetos пишет:

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

    Neekeetos, заранее приношу извинения, если я неверно вас понял, но судя по сообщения на форуме, вы пытаетесь реализовать защиту на Code больше подходящую для старых моделей ключей.
    Подход, в котором надо защищать обмен между ключом и программой противоречит основной идеи ключей Code, которая подразумевала, что в ключе должен быть не искусственно введённый алгоритм защиты, с конечным набором входных и выходных данных, а неотъемлемая часть логики программы. Тогда не будет смысла записывать все возможные варианты входных/выходных данных переданных в функцию внутри ключа, т.к. они будут слишком разнообразны и специфичны для каждого пользователя программы. А иначе получится всего лишь защита в стиле «Stealth II», но с блэкджеком и самодельным алгоритмом для схемы «вопрос-ответ». Взломщик должен столкнуться с анализом «чёрного ящика», в результате которого ему надо не взломать секретный ключ, а переписать самому часть алгоритмов программы. А это требует от него на много более кропотливой работы, да и результат может не совпасть с оригиналом.

Пейте сладкий чай!

Re: Ключи Code, вопросы по использованию

Denis пишет:

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

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

Denis пишет:

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

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

Я же хочу создать еще один туннель между ключом и программой, таким образом чтобы данные проходящие через гвардант апи ничего не давали в плане взлома. Пока что алгоритм выглядит так:
1. при запуске программы с ключом создается сессия, происходит обмен сеасовыми ключами и подтверждение подлинности (ака программа должна знать протокол, ключ тоже), кроме того программе предлагается сохранить состояние ключа (оно зашифровано и имеет MAC, тоесть без знания ключа подделать в программе нельзя, посмотреть тоже), сам ключ также запоминает его.   ( из за этого все сеансовые переменные гарантированно уникальны тк механизм их формирования и записи состояния это обеспечивает, )
2. любое обращение к ключу использует сеансовые ключи шифрования и счетчики сообщений, так что если сеанс по какой либо причине прервался или появились/пропали/испортились сообщения сеанс внутри ключа закрывается и требуется заново создавать сессию-туннель с ключом.

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

Теперь, ворох проблем с которым я столкнулся включает такие вещи как ограниченный ресурс ключа, тормознутость апи, которая на моем компутере не дает выполнить больше 100 вызовов/секунду для кода внутри ключа (это без аргументов, если передавать буфер то скорость линейно падает, для буфера приема/передачи в 512 она падает в 4 раза например  до 25 вызовов/с , это функция-пустышка в ключе, для рабочей будет медленней) . Еще если непрерывно делать вызовы к ключу, то апи негуманно использует сразу целый процессор на 100%  для вычислений, спрашивается зачем все это барахло если протокол давно расшифрован а надежность обеспечивается секретным алгоритмом.Еще одна занятная проблема это ECC, некоторое время назад я сильно жалел что в ключе реализована лишь подпись, использовать код ключа для обмена сеансовыми ключами не выйдет.
Справедливости ради скажу, что часть проблем я уже поборол, это видно по алгоритму, например данные записываются в ключе раз за сессию, а не для каждого обращения, это экономит ресурс, а ECC код пришлось добавить в программу ключа. Осталось придумать нечто эффективное для того, чтобы обойти тормоза при работе с ключом и апи.

(2012-04-11 17:27:14 отредактировано Denis)

Re: Ключи Code, вопросы по использованию

Сложно объяснить всё сразу, поэтому буду делать это по частям. Сначала я расскажу то, что знаю о ключах, а потом поясню, как это относится к практике.

Я не сталкивался со старыми LPT-ключами, которые были до Stealth II и мало что про них знаю, поэтому рассматривать их не буду (да и в продаже их уже нет). Доступные сейчас ключи можно разделить на три поколения:
    1. Stealth II, III - ключи с одним криптоалгоритмом (GSII64), без встроенного шифрования протокола обмена.
    2. Sign – ключи имеют несколько криптоалгоритмов, в том числе ассиметричной подписи. Протокол обмена шифруется с помощью ассиметричной криптографии и разбавлен случайными «мусорными» пакетами.
    3. Code – позволяют реализовать и загрузить собственные алгоритмы,  а также включает в себя почти всю функциональность Sign. Протокол их обмена также шифруется.

Защита, построенная на ключах 1 и 2 поколений, с теми или иными модификациями использовала два механизма – динамическая расшифровка части программы на ключе и постоянный опрос ключа (aka схема «вопрос-ответ»).

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

Для ключей второго поколения с зашифрованным трафиком, USB-дампер выдаёт кучу шифро-мусора. А из-за того что при каждом запуске программы ключ шифрования меняется, этот мусор нельзя подсунуть программе повторно, даже если шифруемый трафик совпадает до байта. В документации я этого не нашел (может плохо искал), но разработчики уверяют, что трафик также разбавляется ложными пакетами-пустышками.
В такой защите надо бояться грамотно расставленных брекпоинтов в коде программы, особенно в тех местах, где вызывается GuardantAPI, т.к. на этой стадии контрольные вопросы ещё не зашифрованы. Помогают всё те же методы, что и с первым поколением, плюс накрыть код программы протектором. Можно использовать сторонний, а можно Guardant-овский. Опять же, если верить разработчикам, то «родной» протектор имеет свои полезные плюшки (https://www.guardant.ru/technology/monilith/). В сравнении с первым поколением для создания эмулятора придётся ковыряться в коде приложения, ища ВСЕ вызовы, сняв перед этим протектор и отключив контроль целостности API. Такая нудная работа требует значительного количества человеко-часов квалифицированного взломщика, который в свою очередь требует от заказчика значительного количества денежной массы :)

В третьем поколении можно загружать свои собственные алгоритмы, что наконец-то (аллилуйя!) позволяет реализовать защиту принципиально отличную от схемы «вопрос-ответ». Для любителей «классической миссионерской», можно конечно и по старинке, в ключе есть тот же функционал, что и в предыдущих моделях, но, на мой взгляд, это как микроскопом гвозди забивать. Трафик по-прежнему шифруется, что создаёт дополнительную трудность для анализа логики реализованной в ключе. Но опять же, на мой взгляд, при грамотном построении защиты на основе загружаемого кода, без этого шифрования можно было бы и обойтись, т.к. только тормозит общение с ключом. Видимо это было сделано из желания «подстраховать» некоторых нерадивых разработчиков защит.

P.S. Google, привёл меня вот к этой статье http://habrahabr.ru/company/aktiv-company/blog/138641/, где рассказывается о том же, но подробнее и с картинками.

Пейте сладкий чай!

Re: Ключи Code, вопросы по использованию

Теперь применительно к практике.

Neekeetos пишет:

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

Когда я исследовал предложения по защите на ключах, я также изучал и предложения о взломе и эмуляции этих ключей. Предложений для старенького Stealth II можно найти в количестве, а вот для Sign всё крайне вяло, и только какие-то мутновато-частные случаи. Видимо шифрованный обмен и параноидальное полиморфизирование/виртуализирование кода Guardant-овского API дали свои плоды. Примеров взлома с Code мне вообще не попалось (частично это можно списать на «молодость» ключа).
Я считаю, что ключ это всего лишь инструмент, а стойкость защиты ВСЕГДА зависит от использующего его разработчика. Качественную защиту можно сделать и с функционалом Stealth II, хотя на Code это проще.

Neekeetos пишет:

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

Это поверх уже имеющегося туннеля реализованного в Code? Там и встроенный то исполняет скорее страховочную функцию для схем «вопрос-ответ», пожирая при этом процессорное время в момент обращения к ключу, т.к. вся криптография там для затруднения анализа крутится на встроенной в API виртуальной машине. Упор лучше делать не на это, а на перенос кусочков логики ПО в ключ. Надёжнее интегрировать ПО в защиту, чем защиту в ПО.

Neekeetos пишет:

2. любое обращение к ключу использует сеансовые ключи шифрования и счетчики сообщений, так что если сеанс по какой либо причине прервался или появились/пропали/испортились сообщения сеанс внутри ключа закрывается и требуется заново создавать сессию-туннель с ключом.

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

Neekeetos пишет:

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

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

Neekeetos пишет:

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

Так в этом же и особенность Code, что в нём не обязательно пользоваться «вшитыми» алгоритмами, а можно портировать в него свои, например тот же RSA.

P.S. Мне нравится ваше желание сделать что-то новое и интересно в защите ПО, если у вас будет возможность отпишитесь, чего удалось добиться. Мне тоже приходятся «варится в собственном соку» и сторонне мнение с новыми идеями часто помогает.

Пейте сладкий чай!

Re: Ключи Code, вопросы по использованию

Denis пишет:

Видимо шифрованный обмен и параноидальное полиморфизирование/виртуализирование кода Guardant-овского API дали свои плоды.

Скажем так, весь этот шифрованый обмен и прочее реализовано в ключе с одной целью  - припудрить мозги потенциальным покупателям. Учитывая что вызовы апи доступны для  мониторинга ( даже в случае статической линковки - библиотека то на сайте лежит, все спокойно находится в коде по сигнатурам), любой вариант передачи данных между ключом и приложением равнозначен отсутствию какой либо шифровки вообще. По поводу плодов, они примерно такие - http://rus.dongla.net/guardant.html,  как я уже написал даже для новых ключей протокол очевидно изучен даже на уровне обмена по юсб, тоесть он даже формально не стойкий, поскольку любой балбес может по записи юсб обмена расшифровать передаваемые данные(это кстати еще одно подтверждение тому что все это для антуражу а не для какой то реальной защиты), такое в нормальной схеме обмена ключами невозможно вообще. Видимо хваленый обмен сеансовыми ключами происходит в открытую, детский сад.

Denis пишет:

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

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

Denis пишет:

P.S. Мне нравится ваше желание сделать что-то новое и интересно в защите ПО, если у вас будет возможность отпишитесь, чего удалось добиться. Мне тоже приходятся «варится в собственном соку» и сторонне мнение с новыми идеями часто помогает.

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

Denis пишет:

Вот про это я и говорил Антону, когда предупреждал о возможной потере питания ключом

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