информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Сетевые кракеры и правда о деле ЛевинаГде водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Microsoft обещает радикально усилить... 
 Ядро Linux избавляется от российских... 
 20 лет Ubuntu 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / theory
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
cryptEncrypt() возвращает ошибку оказывается ) 13.06.06 14:28  Число просмотров: 3839
Автор: nop Статус: Незарегистрированный пользователь
<"чистая" ссылка>
subj ^^
<theory>
вопрос по cryptlib (RSA) 10.06.06 00:19  
Автор: nop Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Я пытаюсь освоить RSA. Более ли менее вникнуть в библиотечные функции cryptlib мне вроде бы удалось. Но возник вопрос, у меня есть 128-байтный public key, который мне передаётся по сети неким приложением. Кто-нибудь может подсказать, как этот публичный ключ использовать в cryptlib, чтобы зашифровать им какие-либо данные?
продолжаю соло) 12.06.06 10:13  
Автор: nop Статус: Незарегистрированный пользователь
<"чистая" ссылка>
продолжаю соло)

int main(int argc, char* argv[]) {
char *buffer = "hello world!\0";
CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_RSA;
CRYPT_CONTEXT cryptContext;
CRYPT_KEYSET cryptKeyset;

cryptInit();
cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_RSA );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,"AAAAAAAAAAAAAA", 14 );
cryptGenerateKey( cryptContext );

printf("buffer: %s\n",buffer);
cryptEncrypt( cryptContext, buffer, strlen(buffer) );
printf("buffer: %s\n",buffer);

cryptEnd();

return 0;
}

на экран выводит:
buffer: hello world!
buffer: hello world!

Есть идеи, почему текст не зашифровывается? :\ Что я не так делаю? Ниодна из функций ошибок не возвращает - проверял.
Заранее извиняюсь, что не видел в глаза этот cryptlib, но... 13.06.06 10:35  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 13.06.06 10:37  Количество правок: 1
<"чистая" ссылка>
> char *buffer = "hello world!\0";
> printf("buffer: %s\n",buffer);
> cryptEncrypt( cryptContext, buffer, strlen(buffer)
> printf("buffer: %s\n",buffer);
> на экран выводит:
> buffer: hello world!
> buffer: hello world!

Заранее извиняюсь, что не видел в глаза этот cryptlib, но для решения задачи это и не надо. Достаточно С знать и, собственно, RSA.
Шифровка не может быть в buffer по нескольким причинам:
1. Нехорошо "портить" исходный текст.
2. buffer, указатель, указывающий на константу. При ожидаемой модификации будет segmentation fault.
3. Шифровка будет соизмерима с длиной ключа, а не с исходным текстом. Так что она просто не поместится в buffer, если strlen(buffer)<sizeof(cryptContext->key) (извиняюсь за корявое неравенство).
4. По хорошему функция шифрования должна возвращать шифровку и (полагаю) должна быть описана примерно так: char *cryptEncrypt( cryptContext, buffer, strlen(buffer) ); Возможно и другие варианты, например cryptContext->cifer и будет указателем на зашифрованый текст.
C_ret cryptencrypt( c_in crypt_context cryptcontext, c_inout... 13.06.06 14:21  
Автор: nop Статус: Незарегистрированный пользователь
<"чистая" ссылка>
> > char *buffer = "hello world!\0";
> > printf("buffer: %s\n",buffer);
> > cryptEncrypt( cryptContext, buffer, strlen(buffer)
> > printf("buffer: %s\n",buffer);
> > на экран выводит:
> > buffer: hello world!
> > buffer: hello world!
>
> Заранее извиняюсь, что не видел в глаза этот cryptlib, но
> для решения задачи это и не надо. Достаточно С знать и,
> собственно, RSA.
> Шифровка не может быть в buffer по нескольким причинам:
> 1. Нехорошо "портить" исходный текст.
> 2. buffer, указатель, указывающий на константу. При
> ожидаемой модификации будет segmentation fault.
C_RET cryptEncrypt( C_IN CRYPT_CONTEXT cryptContext, C_INOUT void C_PTR buffer,C_IN int length );
так определяется функция шифрования в загловочном файле cryptlib. C_RET - это int, которая возвращает либо 1, либо ошибку.
А C_INOUT void C_PTR buffer - обратите внимание на C_INOUT... То есть как раз в buffer должен быть записан зашифрованный текст :\

> Возможно и другие варианты, например cryptContext->cifer
> и будет указателем на зашифрованый текст.
Да дело в том, что cryptContext - это не класс, не структура, а тоже обычный int...

А вы работали когда-нибудь с RSA? Может сможете мне посоветовать библиотеку, которой сами пользовались... А то с этой косяки одни :\
Писал библиотечку для работы с длинными числами... 13.06.06 17:19  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 13.06.06 17:31  Количество правок: 1
<"чистая" ссылка>
> А вы работали когда-нибудь с RSA? Может сможете мне
> посоветовать библиотеку, которой сами пользовались... А то
> с этой косяки одни :\

Писал библиотечку для работы с длинными числами неограниченной длины. Реализовать RSA - десяток строк, которые не написал за ненадобностью. Задача другая.
Для RSA в библиотечке всего-то пяток оконченных функций надо дергать (Возведение в степень по модулю, генерация больших чисел, проверка на простоту, генерация больших простых, нахождение НОД, умножение, вычитание, ну можно еще несколько вспомогательных, например atoi).
Есть готовая библиотечка, если не ошибаюсь в исходниках GNUшная. Кто-то здесь ее рекомендовал. Ключевое слово для поиска "GMP".
cryptEncrypt() возвращает ошибку оказывается ) 13.06.06 14:28  
Автор: nop Статус: Незарегистрированный пользователь
<"чистая" ссылка>
subj ^^
Замечание 13.06.06 12:55  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Заранее извиняюсь, что не видел в глаза этот cryptlib, но
> для решения задачи это и не надо. Достаточно С знать и,
> собственно, RSA.
> Шифровка не может быть в buffer по нескольким причинам:
> 1. Нехорошо "портить" исходный текст.

Это не проблема

> 2. buffer, указатель, указывающий на константу. При
> ожидаемой модификации будет segmentation fault.

Не факт. Принимаемое значение скорее всего (char *), а не (char[]) и не (const char *). Очень многие библиотечные функции для возвращаемого значения используют вот такую вот пару буфер/длина. То что на самом деле буфер - константа - это не проблема библиотеки, а проблема клиента этой библиотеки (вполне возможно где то в описалове это указано)

> 3. Шифровка будет соизмерима с длиной ключа, а не с
> исходным текстом. Так что она просто не поместится в
> buffer, если strlen(buffer)<sizeof(cryptContext->key)
> (извиняюсь за корявое неравенство).

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

> 4. По хорошему функция шифрования должна возвращать
> шифровку и (полагаю) должна быть описана примерно так: char
> *cryptEncrypt( cryptContext, buffer, strlen(buffer) );
> Возможно и другие варианты, например cryptContext->cifer
> и будет указателем на зашифрованый текст.

Как по мне возврат буфера - плохая идея, а вот возврат шифровки в контексте - вполне возможный вариант. Если так, то скорее всего должна быть еще и функция-getter для сокрытия внутренностей контекста.
Я ж не про ошибки на этапе компиляции. Ну пусть это не... 13.06.06 13:45  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Отредактировано 13.06.06 13:48  Количество правок: 2
<"чистая" ссылка>
> > 2. buffer, указатель, указывающий на константу. При
> > ожидаемой модификации будет segmentation fault.
>
> Не факт. Принимаемое значение скорее всего (char *), а не
> (char[]) и не (const char *). Очень многие библиотечные

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

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

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

> > 3. Шифровка будет соизмерима с длиной ключа, а не с
> > исходным текстом. Так что она просто не поместится в
> > buffer, если
> strlen(buffer)<sizeof(cryptContext->key)
> > (извиняюсь за корявое неравенство).
>
> Вот это 100%. Причем вполне возможно, что шифрование не
> происходит именно по этой причине. Просто переданный буфер
> меньше размера ключа и библиотека возвращается с ошибкой.

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

> > 4. По хорошему функция шифрования должна возвращать
> > шифровку и (полагаю) должна быть описана примерно так:
> char
> > *cryptEncrypt( cryptContext, buffer, strlen(buffer) );
> > Возможно и другие варианты, например
> cryptContext->cifer
> > и будет указателем на зашифрованый текст.
>
> Как по мне возврат буфера - плохая идея, а вот возврат
> шифровки в контексте - вполне возможный вариант. Если так,
> то скорее всего должна быть еще и функция-getter для
> сокрытия внутренностей контекста.

По мне тоже плохая, так как где-то должно быть описаны правила очистки буфера. То есть скорее всего он будет выделяться обычным malloc'ом, а высвобождать после использования должен пользователь(программист) библиотеки.
Возможет вариант (как sprintf), когда программист передает и буфер для результата плюс его длина или он обязан передать буфер достаточного размера.

Короче даже (тем более) для собственного самообразования рекомендуется написать все это самостоятельно, а не пользоваться чужой библиотекой.
Я тоже :-) 13.06.06 14:36  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Я ж не про ошибки на этапе компиляции. Ну пусть это не
> константная строка, описание char * еще не признак того,

Не признак. Просто буфер принято передавать либо как void* либо как char*
Первое совершенно не означает, что указатель указывает в НИКУДА, а второе не значит, что указатель - на СИМВОЛЫ (то бишь строка): bsd socket-ные функции тому пример. Это я к тому, что в доке к библиотеке должно было быть указано, изменяется ли буфер. Если да, то передать ему просто "Hello, world" тоже можно, но будут рантаймовые ошибки.

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

Ага.

> Если функция работает со строкой, то либо она ее не
> изменяет (не использует для возврата результата), либо
> конвертирует ее в такую же по длине и функции
> преобразования кодировки тому пример. Все остальное будет
> резать глаз/слух.

Тоже ага. Только как я сказал выше, не любой char* - строка.

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

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

PS: Топикстартер показал прототип. Буфер действительно in-out. Возникает вопрос, как получить длину ЗАШИФРОВАННЫХ данных исходя из этого прототипа.
ребят, это конечно всё хорошо, но... =) 13.06.06 14:42  
Автор: nop Статус: Незарегистрированный пользователь
<"чистая" ссылка>
В общем, дело такое:

char *buffer;
int status, blockSize = 10;
CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_RSA;
CRYPT_CONTEXT cryptContext;
CRYPT_KEYSET cryptKeyset;

/* Initialise cryptlib */
status = cryptInit();
if(cryptStatusError(status)) {
printf( "cryptInit() failed with error code %d.\n", status );
exit(EXIT_FAILURE);
}

buffer = (char *)malloc(300);
memset(buffer,'\x00',300);
memcpy(buffer,"hello world!",sizeof("hello world!"));

cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_RSA );
cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,"AAAAAAAAAAAAAA", 14 );
cryptGenerateKey( cryptContext );

printf("buffer: %s, len: %i\n",buffer, strlen(buffer));
status = cryptEncrypt( cryptContext, buffer, strlen(buffer));
if(cryptStatusError(status)) {
printf( "cryptEncrypt() failed with error code %d.\n", status );
exit(EXIT_FAILURE);
}

Вот что выводится на экран:
buffer: hello world!, len: 12
cryptEncrypt() failed with error code -3.

-3 в заголовках прописана как:
/* No error in function call */

#define CRYPT_OK 0 /* No error */

/* Error in parameters passed to function */

#define CRYPT_ERROR_PARAM1 -1 /* Bad argument, parameter 1 */
#define CRYPT_ERROR_PARAM2 -2 /* Bad argument, parameter 2 */
#define CRYPT_ERROR_PARAM3 -3 /* Bad argument, parameter 3 */
#define CRYPT_ERROR_PARAM4 -4 /* Bad argument, parameter 4 */
#define CRYPT_ERROR_PARAM5 -5 /* Bad argument, parameter 5 */
#define CRYPT_ERROR_PARAM6 -6 /* Bad argument, parameter 6 */
#define CRYPT_ERROR_PARAM7 -7 /* Bad argument, parameter 7 */


То есть получается ошибка в 3-ем аргументе. Там передаётся длина данных. Какая там может быть ошибка? :\
Например параметры int, char*, int. В зависимости от... 13.06.06 16:54  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> status = cryptEncrypt( cryptContext, buffer,
> strlen(buffer));
> if(cryptStatusError(status)) {
> printf( "cryptEncrypt() failed with error
> code %d.\n", status );
> exit(EXIT_FAILURE);
> }
>
> Вот что выводится на экран:
> buffer: hello world!, len: 12
> cryptEncrypt() failed with error code -3.
>
> -3 в заголовках прописана как:
> /* No error in function call */
>
> То есть получается ошибка в 3-ем аргументе. Там передаётся
> длина данных. Какая там может быть ошибка? :\

Например параметры int, char*, int. В зависимости от ключика/компилятора/модели_памяти int может иметь длину 2, 4 или 8 байт. Последнее маловероятно. То же самое с указателем. Параметры передаются через стэк. Функция, та, что в библиотеке, могла быть компильнута под другие размерности типов данных. Отсюда могут быть и отрицательные значения. Сам на подобное нарывался когда-то.
бред какой-то 13.06.06 14:47  
Автор: nop Статус: Незарегистрированный пользователь
<"чистая" ссылка>

> Вот что выводится на экран:
> buffer: hello world!, len: 12
> cryptEncrypt() failed with error code -3.
>
> -3 в заголовках прописана как:
> /* No error in function call */
>
> #define CRYPT_OK 0
> /* No error */
>
> /* Error in parameters passed to function */
>
> #define CRYPT_ERROR_PARAM1 -1 /* Bad
> argument, parameter 1 */
> #define CRYPT_ERROR_PARAM2 -2 /* Bad
> argument, parameter 2 */
> #define CRYPT_ERROR_PARAM3 -3 /* Bad
> argument, parameter 3 */
> #define CRYPT_ERROR_PARAM4 -4 /* Bad
> argument, parameter 4 */
> #define CRYPT_ERROR_PARAM5 -5 /* Bad
> argument, parameter 5 */
> #define CRYPT_ERROR_PARAM6 -6 /* Bad
> argument, parameter 6 */
> #define CRYPT_ERROR_PARAM7 -7 /* Bad
> argument, parameter 7 */
>
вот сорсы той самой функции:
C_RET cryptEncrypt( C_IN CRYPT_CONTEXT cryptContext,
C_INOUT void C_PTR buffer,
C_IN int length )
{
static const COMMAND_INFO cmdTemplate = \
{ COMMAND_ENCRYPT, COMMAND_FLAG_NONE, 1, 1 };
static const ERRORMAP errorMap[] = \
{ ARG_O, ARG_S, ARG_N, ARG_LAST };
COMMAND_INFO cmd;
int status;

/* Perform basic client-side error checking. In theory we should also
check for writeability since the encryption does an in-place update,
however when we're hashing data it's valid for the data to be read-
only so we only check for readability. In addition when hashing we
could be doing a hash-wrapup call so we allow a zero length and only
check the buffer if the length is nonzero */
if( !isHandleRangeValid( cryptContext ) )
return( CRYPT_ERROR_PARAM1 );
if( length < 0 )
return( CRYPT_ERROR_PARAM3 );
..............

Функция мне возвращает CRYPT_ERROR_PARAM3
Но у меня же length положительная однозначно. Я даже пробовал без strlen(buffer) просто число вставлять.
Может реализация отличается от опенсорса. Например добавлено... 13.06.06 16:45  
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
<"чистая" ссылка>
> if( !isHandleRangeValid( cryptContext ) )
> return( CRYPT_ERROR_PARAM1 );
> if( length < 0 )
> return( CRYPT_ERROR_PARAM3 );
> ..............
>
> Функция мне возвращает CRYPT_ERROR_PARAM3
> Но у меня же length положительная однозначно. Я даже
> пробовал без strlen(buffer) просто число вставлять.

Может реализация отличается от опенсорса. Например добавлено еще одно сравнение на превышение размера блока. То есть функция шифрует только один блок заданного размера. Короче или ей нужно передавать мЕньший блок, или кратный степени двойки, 64 бита, например.
Может еще что-нибудь вызвать или проинициализировать надо.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 1 s   Design: Vadim Derkach