Переход от защиты 2-го поколения к защите 3-го

Обращаюсь к специалистам компании Актив. Защита нашего ПО разработана на основе ключей Guardant 2-го поколения. Есть ли методические материалы для разработчиков, с помощью которых мы сможем быстро переписать свою защиту под ключи 3-го поколения ???

Re: Переход от защиты 2-го поколения к защите 3-го

Уточните, пожалуйста, переход с каких именно ключей и на какие имеется в виду.

Если речь идет о переходе с ключей Stealth II\Stealth III на ключи последнего поколения (Sign, Time, Code), то для того, чтобы все работало, потребуется изменить только критерии поиска ключей. Радикальных изменений не потребуется.

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

Re: Переход от защиты 2-го поколения к защите 3-го

Алексей Перепелов пишет:

Уточните, пожалуйста, переход с каких именно ключей и на какие имеется в виду.

Если речь идет о переходе с ключей Stealth II\Stealth III на ключи последнего поколения (Sign, Time, Code), то для того, чтобы все работало, потребуется изменить только критерии поиска ключей. Радикальных изменений не потребуется.

Нам необходимо перейти со Stealth II на Sign.
Если я правильно понял, то менять нужно не только критерии поиска ключа, но и названия и синтаксис команд API.
Поэтому и спрашиваю, есть ли методические материалы, которые помогут нам быстро перестроить свою защиту ?

Re: Переход от защиты 2-го поколения к защите 3-го

Нам необходимо перейти со Stealth II на Sign.
Если я правильно понял, то менять нужно не только критерии поиска ключа, но и названия и синтаксис команд API.
Поэтому и спрашиваю, есть ли методические материалы, которые помогут нам быстро перестроить свою защиту ?

Насколько я понял, вы используете ПО Guardant версии 4.хх и старое API с функциями вида nskRead, nskWrite и т.п.
Готовых методических материалов по переходу с Stealth II на Sign в таких случаях нет, и их создание, признаюсь, отличная идея. Мы включим это в план работ.

Что касается перехода, могу сказать следующее:

1. Новое API похоже на старое - перечень выполняемых операций в основе тот же, но существенно расширенный возможностями современных ключей. Если вы активно используете API, то кое-какая работа потребуется. Например ранее вы могли в любой момент вызвать nskRead или nskTransform задав ей Read-код и прочие параметры. Работа же с Sign ключами организована в шифрованные сессии - указав код доступа и выполнив логин на ключ вы можете вызывать GrdRead или GrdTransform с параметрами аналогичными nsk-функциями, но весь передаваемый трафик между приложением и ключом будет надежно защищен.

2. Касательно аппаратных алгоритмов - со Stealth II в новые ключи мигрировали только алгоритмы на основе GSII64, алгоритмы же Stealth I перешедшие в Stealth II более не поддерживаются. Если у вас работа завязана на них, то потребуется больше переделок. Если же используется GSII64, то все ограничится переходом на новое API без изменения логики работы.

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

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

Re: Переход от защиты 2-го поколения к защите 3-го

AndreyStepin пишет:

Насколько я понял, вы используете ПО Guardant версии 4.хх и старое API с функциями вида nskRead, nskWrite и т.п.
Готовых методических материалов по переходу с Stealth II на Sign в таких случаях нет, и их создание, признаюсь, отличная идея. Мы включим это в план работ.

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

Мы действительно используем в своей защите старое API с функциями вида nskRead, nskWrite и т.п.
Попробуем воспользоваться текущей документацией разработчика к Sign.
Если что-то не будет получаться, то будем обращаться к вам за поддержкой.

Спасибо.

Re: Переход от защиты 2-го поколения к защите 3-го

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

Re: Переход от защиты 2-го поколения к защите 3-го

Анатолий пишет:

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

Как уже писал выше мой коллега,  в новые ключи мигрировали только алгоритмы на основе GSII64, алгоритмы же Stealth I перешедшие в Stealth II более не поддерживаются. Если у Вас работа завязана на них, то потребуется больше переделок. Если же используется GSII64, то все ограничится переходом на новое API без изменения логики работы.

Re: Переход от защиты 2-го поколения к защите 3-го

Еще один вопрос:
Начиная  с какой версии драйверов осуществляется поддержка ключей Sign?

Re: Переход от защиты 2-го поколения к защите 3-го

Анатолий пишет:

Еще один вопрос:
Начиная  с какой версии драйверов осуществляется поддержка ключей Sign?

Начиная с версии 5.30 от 12 ноября 2008 года. (информация с нашего сайта https://www.guardant.ru/support/softwar … -2008.html )

Ещё хочу обратить Ваше внимание на то что ключ Sign может работать без драйвера. (подробнее об этом Вы можете узнать на нашем сайте https://www.guardant.ru/technology/hid-mode/ )

Re: Переход от защиты 2-го поколения к защите 3-го

Здравствуйте, у меня вопрос подобный, только  интереcует переход с ключей Net II  на Net III или более современные, Guardant Sign Net, Guardant Time Net.

Re: Переход от защиты 2-го поколения к защите 3-го

chip685 пишет:

Здравствуйте, у меня вопрос подобный, только  интереcует переход с ключей Net II  на Net III или более современные, Guardant Sign Net, Guardant Time Net.

Для сетевых версий ключей Guardant справедливы все вышеизложенные в данной теме рекомендации. Принципиальных различий в подходе к миграции со старых сетевых ключей на новые (относительно локальных ключей) нет.

Re: Переход от защиты 2-го поколения к защите 3-го

Столкнулись с такой проблемой:
в API 4 мы активно использовали функции EnCode и Decode.
В списке хранили некоторые константы закодированные, а при работе программы их раскодировали (с указанием пароля).
При переводе защиты на API 5 обнаружилось, что функция GrdDecode при тех же данных, том же пароле и методе дает совсем другой результат, нежели DeCode.
В документации заявлено, что новые функции оставили для совместимости со старыми версиями.
Но на деле они дают другой результат.

Что делать в этом случае???

Набор зашифрованных констант большой. Перекодировать их заново трудоемко.

Re: Переход от защиты 2-го поколения к защите 3-го

plohushko пишет:

Столкнулись с такой проблемой:
в API 4 мы активно использовали функции EnCode и Decode.
В списке хранили некоторые константы закодированные, а при работе программы их раскодировали (с указанием пароля).
При переводе защиты на API 5 обнаружилось, что функция GrdDecode при тех же данных, том же пароле и методе дает совсем другой результат, нежели DeCode.
В документации заявлено, что новые функции оставили для совместимости со старыми версиями.
Но на деле они дают другой результат.

Что делать в этом случае???

Набор зашифрованных констант большой. Перекодировать их заново трудоемко.

Уточните, пожалуйста, в каких именно ключах (StealthII или Sign) Вы собираетесь использовать данные функции шифрования?
Также пришлите нам на почтовый ящик - hotline@guardant.ru, тестовые примеры (под API v4 и API v5) на которых проявляется данное поведение и файл маски прошиваемой в используемый ключ.

Re: Переход от защиты 2-го поколения к защите 3-го

API 4 использовали на StealthII
API 5 - Sign

Re: Переход от защиты 2-го поколения к защите 3-го

plohushko пишет:

API 4 использовали на StealthII
API 5 - Sign

Тут нужно обратить внимание на то, что функция GrdDecode получает пароль инициализированный функцией GrdCodeInit, которая в свою очередь использует для преобразования аппаратный алгоритм типа Fast (о чем написано в документации по Guardant API v5).
Алгоритм типа Fast был реализован в ключах Stealth и StealthII, в ключах Sign такого алгоритма нет.
Таким образом, функции GrdCodeInit, GrdEnCode и GrdDeCode в ключах Sign работать не будут.

Re: Переход от защиты 2-го поколения к защите 3-го

Мы CodeInit не использовали, поскольку в качестве пароля функциям Encode и Decode в любом случае передается строка. И это прекрасно работало.
На Sign функции GrdEnCode и GrdDeCode тоже прекрасно работают без GrdCodeInit, только дают не те результаты, что их предшественники при тех же заданных парметрах.

Re: Переход от защиты 2-го поколения к защите 3-го

Я могу проверить работу GrdEnCode и GrdDeCode на StealthII при тех же параметрах. Но думаю, результат будет тот же, поскольку эти функции делаю преобразование программно.

Re: Переход от защиты 2-го поколения к защите 3-го

Т.е. не будут работать так, ка на старом API

(2012-04-02 09:44:10 отредактировано Антон Тихиенко)

Re: Переход от защиты 2-го поколения к защите 3-го

plohushko пишет:

Я могу проверить работу GrdEnCode и GrdDeCode на StealthII при тех же параметрах. Но думаю, результат будет тот же, поскольку эти функции делаю преобразование программно.

plohushko пишет:

Т.е. не будут работать так, ка на старом API

Попробовал воспроизвести описанную ситуацию следующим образом:
1) Использовал API из состава комплекта разработчика версии 4.88, где при помощи функций nskEnCode и nskDeCode закодировал и раскодировал некоторые данные:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include "nvskey32.h"
#include "nvkeyerr.h"

/*** Definitions ************************************************************/
#define Crypt   0x8566783lu       /* Random value for access codes security */
#define DataLen 32lu              /* Data length                            */
#define ReadWriteAddr uam_dwIndex /* Address for Read/Write functions       */
                                  /* (Index field used )                    */

/*** Data variables *********************************************************/
        int     nRet;                        /* Return code                 */
        DWORD   dwCRCbefore;                 /* CRC of original data        */
        DWORD   dwCRCafter;                  /* CRC of restored data        */
        
        char sPassword[nsars_Fast] = "__this_string_must_be_32-bytes_";
           char sData[]               = "Test 32 bytes for Encode/Decode.\0";
        
/*****************************************************************************
*       Main function                                                        *
*****************************************************************************/

int main( void )
{
        
/*--------------------------------------------------------------------------*/
/*  Fast reversible data transformation.                            */
/*--------------------------------------------------------------------------*/
        printf ( "\nEncoding/Decoding data using password.");

/*  Calculate CRC of initial data                                           */
        dwCRCbefore = nskCRC  ( sData, DataLen, ns_StartCRC );
        printf( "\n         BEFORE EnCode = '%s' CRC = 0x%lX",
                                         sData, dwCRCbefore );
/* Encode string using password                                             */
        nRet = nskEnCode  ( nsat_Algo0, sPassword, sData, DataLen );
        sData[DataLen] = '\0';
        printf( "\n         AFTER  EnCode = '%s'", sData );

/* Decode string using password                                             */
        nRet = nskDeCode  ( nsat_Algo0, sPassword, sData, DataLen );

/* Calculate CRC of decoded data                                            */
        dwCRCafter = nskCRC  ( sData, DataLen, ns_StartCRC );
        printf( "\n         AFTER  DeCode = '%s' CRC = 0x%lX",
                                         sData, dwCRCafter );

/*--------------------------------------------------------------------------*/
/* Verify CRC.                                                     */
/*--------------------------------------------------------------------------*/
        printf ("\nVerify CRC : " );
        if (dwCRCbefore==dwCRCafter)
                 printf( "CRC OK." );
        else
                 printf( "CRC ERROR." );

/*--------------------------------------------------------------------------*/
/* End of tests                                                             */
/*--------------------------------------------------------------------------*/
        printf( "\n\n End of tests... Press [Enter]" );
        getch();

        return nse_Ok;
}
/*--------------------------------------------------------------------------*/

Результат:
https://forum.guardant.ru/uploads/legacy/users/1000/31/tmp/thumb/p16posmth218qo1l7v8kc1eqv1b0q1.jpg

2) Похожий пример сделал для Guardant API из состава комплекта разработчика версии 5.52, где соответственно использовал функции GrdEnCode и GrdDeCode:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include "GrdAPI.h"
#include "GrdDongle.h"

// Definitions
#define DataLen 32lu

// Data variables 
DWORD   dwCRC_Before;                                   // CRC of original data
DWORD   dwCRC_After;                                    // CRC of restored data
char sPassword[32] = "__this_string_must_be_32-bytes_";
char sData[]               = "Test 32 bytes for Encode/Decode.\0";

//----------------------------------------------------------------------------------------------
//       Main function
//----------------------------------------------------------------------------------------------
int main( int argc, char **argv )
{
    int            nRet;


    nRet = GrdStartup( GrdFMR_Local );

/*--------------------------------------------------------------------------*/
/* Fast reversible data transformation.                            */
/*--------------------------------------------------------------------------*/
        printf ( "\nEncoding/Decoding data using password.");

/*  Calculate CRC of initial data                                           */
        dwCRC_Before = GrdCRC  ( sData, sizeof(sData), (DWORD) Grd_StartCRC );
        printf( "\n         BEFORE EnCode = '%s' CRC = 0x%lX",
                                         sData, dwCRC_Before );
/* Encode string using password                                             */
        nRet = GrdEnCode  ( GrdAT_Algo0, sPassword, sData, DataLen );
        sData[DataLen] = '\0';
        printf( "\n         AFTER  EnCode = '%s'", sData );

/* Decode string using password                                             */
        nRet = GrdDeCode  ( GrdAT_Algo0, sPassword, sData, DataLen );

/* Calculate CRC of decoded data                                            */
        dwCRC_After = GrdCRC  ( sData, sizeof(sData), (DWORD) Grd_StartCRC );
        printf( "\n         AFTER  DeCode = '%s' CRC = 0x%lX",
                                         sData, dwCRC_After );

/*--------------------------------------------------------------------------*/
/* Verify CRC.                                                     */
/*--------------------------------------------------------------------------*/
       
        dwCRC_After = GrdCRC( sData, sizeof(sData), (DWORD) Grd_StartCRC );
        printf ("\nVerify CRC : " );
        if( dwCRC_Before == dwCRC_After )
            printf( "CRC OK." );
        else
            printf( "CRC ERROR." );
        
    nRet = GrdCleanup ();

    _getch ();
    return 0;
}
//----------------------------------------------------------------------------------------------

Результат:
https://forum.guardant.ru/uploads/legacy/users/1000/31/tmp/thumb/p16posnck1f1o103jh8e1j3eini3.jpg
Таким образом видно что одинаковые данные одинаково верно кодируются/декодируются как Guardant API версии 4.88 так и 5.52.

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

пришлите нам на почтовый ящик - hotline@guardant.ru, тестовые примеры (под API v4 и API v5) на которых проявляется данное поведение и файл маски прошиваемой в используемый ключ.

(2012-03-29 22:08:41 отредактировано plohushko)

Re: Переход от защиты 2-го поколения к защите 3-го

я использовал ASCII, а не Algo0
и длина исходной строки 38 символов

привожу кусок кода Delphi

//длина зашифрованной строки
ns_SizeTAll = 38;

//зашифрованная строка
ns_CodeStringTAll: array[0..ns_SizeTAll-1] of CHAR =
'g4?!^!#[(#>W!E!0!H+7P?^(*(,:=.!&$=L!,d';

//пароль
ns_PasswordTAll: array[0..31] of BYTE =(
117,182,112, 36, 55,164,193,163, 79,155, 27,119,100,138,173,227,
49,156,164,218, 51,193,179,216, 54, 77,203,251,136,126,245, 50
);

....


          sdata:=ns_CodeStringTAll;
          sPassword:='';

//собираем пароль в строку
          for i_sh:=0 to 31 do
          begin
            sPassword:=sPassword+chr(ns_PasswordTAll[i_sh]);
          end;

          showmessage(sPassword);
          showmessage(sdata);

          nRet := GrdDeCode(nsat_AlgoASCII, @sPassword[1], @sdata[1], ns_SizeTAll);

//выводим раскодированную строку - это наш результат
          showmessage(sdata);

...
в API 4 один результат
в API 5 - другой

(2012-04-02 10:49:49 отредактировано Антон Тихиенко)

Re: Переход от защиты 2-го поколения к защите 3-го

plohushko пишет:

я использовал ASCII, а не Algo0
и длина исходной строки 38 символов

Попробовал переделать примеры с учетом указанных изменений для API 4.88:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include "nvskey32.h"
#include "nvkeyerr.h"

/*** Definitions ************************************************************/
#define Crypt   0x8566783lu       /* Random value for access codes security */
#define DataLen 38lu              /* Data length                            */
#define ReadWriteAddr uam_dwIndex /* Address for Read/Write functions       */
                                  /* (Index field used )                    */

/*** Data variables *********************************************************/
        int     nRet;                        /* Return code                 */
        DWORD   dwCRCbefore;                 /* CRC of original data        */
        DWORD   dwCRCafter;                  /* CRC of restored data        */
        
        char sPassword[nsars_Fast] = "__this_string_must_be_32-bytes_";
           char sData[]               = "___Test 32 bytes for Encode/Decode.___\0";
        
/*****************************************************************************
*       Main function                                                        *
*****************************************************************************/

int main( void )
{
        
/*--------------------------------------------------------------------------*/
/*  Fast reversible data transformation.                            */
/*--------------------------------------------------------------------------*/
        printf ( "\nEncoding/Decoding data using password.");

/*  Calculate CRC of initial data                                           */
        dwCRCbefore = nskCRC  ( sData, DataLen, ns_StartCRC );
        printf( "\n         BEFORE EnCode = '%s' CRC = 0x%lX",
                                         sData, dwCRCbefore );
/* Encode string using password                                             */
        nRet = nskEnCode  ( nsat_AlgoASCII, sPassword, sData, DataLen );
        sData[DataLen] = '\0';
        printf( "\n         AFTER  EnCode = '%s'", sData );

/* Decode string using password                                             */
        nRet = nskDeCode  ( nsat_AlgoASCII, sPassword, sData, DataLen );

/* Calculate CRC of decoded data                                            */
        dwCRCafter = nskCRC  ( sData, DataLen, ns_StartCRC );
        printf( "\n         AFTER  DeCode = '%s' CRC = 0x%lX",
                                         sData, dwCRCafter );

/*--------------------------------------------------------------------------*/
/* Step 4: Verify CRC.                                                     */
/*--------------------------------------------------------------------------*/
        printf ("\nVerify CRC : " );
        if (dwCRCbefore==dwCRCafter)
                 printf( "CRC OK." );
        else
                 printf( "CRC ERROR." );

/*--------------------------------------------------------------------------*/
/* End of tests                                                             */
/*--------------------------------------------------------------------------*/
        printf( "\n\n End of tests... Press [Enter]" );
        getch();

        return nse_Ok;
}
/*--------------------------------------------------------------------------*/

Результат:
https://forum.guardant.ru/uploads/legacy/users/1000/31/tmp/thumb/p16pp0fpdp16mfd8hipao7m1tg61.jpg

API 5.52:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include "GrdAPI.h"
#include "GrdDongle.h"

// Definitions
#define DataLen 38lu

// Data variables 
DWORD   dwCRC_Before;                                   // CRC of original data
DWORD   dwCRC_After;                                    // CRC of restored data
char sPassword[32] = "__this_string_must_be_32-bytes_";
char sData[]               = "___Test 32 bytes for Encode/Decode.___\0";

//----------------------------------------------------------------------------------------------
//       Main function
//----------------------------------------------------------------------------------------------
int main( int argc, char **argv )
{
    int            nRet;


    nRet = GrdStartup( GrdFMR_Local );

/*--------------------------------------------------------------------------*/
/* Fast reversible data transformation.                            */
/*--------------------------------------------------------------------------*/
        printf ( "\nEncoding/Decoding data using password.");

/*  Calculate CRC of initial data                                           */
        dwCRC_Before = GrdCRC  ( sData, sizeof(sData), (DWORD) Grd_StartCRC );
        printf( "\n         BEFORE EnCode = '%s' CRC = 0x%lX",
                                         sData, dwCRC_Before );
/* Encode string using password                                             */
        nRet = GrdEnCode  ( GrdAT_AlgoASCII, sPassword, sData, DataLen );
        sData[DataLen] = '\0';
        printf( "\n         AFTER  EnCode = '%s'", sData );

/* Decode string using password                                             */
        nRet = GrdDeCode  ( GrdAT_AlgoASCII, sPassword, sData, DataLen );

/* Calculate CRC of decoded data                                            */
        dwCRC_After = GrdCRC  ( sData, sizeof(sData), (DWORD) Grd_StartCRC );
        printf( "\n         AFTER  DeCode = '%s' CRC = 0x%lX",
                                         sData, dwCRC_After );

/*--------------------------------------------------------------------------*/
/* Verify CRC.                                                     */
/*--------------------------------------------------------------------------*/
       
        dwCRC_After = GrdCRC( sData, sizeof(sData), (DWORD) Grd_StartCRC );
        printf ("\nVerify CRC : " );
        if( dwCRC_Before == dwCRC_After )
            printf( "CRC OK." );
        else
            printf( "CRC ERROR." );
        
    nRet = GrdCleanup ();

    _getch ();
    return 0;
}
//----------------------------------------------------------------------------------------------

Результат:
https://forum.guardant.ru/uploads/legacy/0/500/811/thumb/p16phbrr092i8p294r115je17061.jpg

Попробуйте, пожалуйста, задавать пароль для функций EnCode и DeCode просто 32-х байтовой строкой символов и передать его в явном виде (без дополнительных преобразований).
Также уточните, какая именно среда разработки (название, версия) использовалась при защите приложения на API 4 + StealthII и какая используется сейчас?

Re: Переход от защиты 2-го поколения к защите 3-го

Антон, моя почта wbp@mail.ru

Re: Переход от защиты 2-го поколения к защите 3-го

plohushko пишет:

Антон, моя почта wbp@mail.ru

Отправил письмо.

Re: Переход от защиты 2-го поколения к защите 3-го

проверил, к этому файлу в модуле grddelphi.pas путь прописан,
файл там лежит...
т.е. вроде всё корректно, но результаты разные...
куда дальше копать не понятно

Re: Переход от защиты 2-го поколения к защите 3-го

plohushko пишет:

проверил, к этому файлу в модуле grddelphi.pas путь прописан,
файл там лежит...
т.е. вроде всё корректно, но результаты разные...
куда дальше копать не понятно

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

Поэтому  для того, чтобы мы все-таки смогли обнаружить причину описанного Вами поведения софтовых функций, выполните следующие, обязательные, действия:
1)    Соберите, пожалуйста, два небольших теста, на которых _проявляется данный эффект_: то есть просто использование данных функций для API v4 и v5 с явно передаваемым паролем. Пришлите полный тестовый проект нам на почту;
2)    Обязательно уточните какая\ие верия-и (если, например, для тестов используются различные версии драйверов, то обязательно укажите какие и для какого API) драйвера Guardant используется?

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