2009-07-23 1 views
2

Я хочу использовать данные OpenSSL для использования в качестве случайных семян во время подписания данных с помощью ключа EC. Я делаю это, чтобы сравнить мое приложение с другим ссылочным (закрытый источник). Эта утилита принимает файл с закрытым ключом, файл с данными для подписи и файл со случайными данными в качестве параметров.Как я могу передать случайные данные OpenSSL для использования в подписке ECDSA?

У меня есть генерация ключей EC и подписание данных вниз, но я не могу сравнивать эти два приложения, так как у меня нет общего места. OpenSSL генерирует случайные данные, используемые при подписании данных (возможно, из/dev/random) и, таким образом, дает мне другую подпись для каждого запуска.

Я пробовал RAND_clear() в сочетании с RAND_add(), но продолжаю меняться подписи. Либо я не понимаю всю концепцию ECDSA, либо я делаю что-то неправильно.

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

Любая помощь/указатели/ссылки были бы весьма признательны.

char * key_as_binary_data; //369368AF243193D001E39CE76BB1D5DA08A9BC0A63307AB352338E5EA5C0E05A0C2531866F3E3C2702 
int data_size; //Size of the key buffer 
EC_POINT * ecpoint = NULL; 
EC_GROUP * ecgroup = NULL; 
EC_KEY * eckey = NULL; 
point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; 
int asn1_flag = OPENSSL_EC_NAMED_CURVE; 

eckey = EC_KEY_new(); 
ecpoint = EC_POINT_new(ecgroup); 
ecgroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("sect163k1")); 
EC_GROUP_set_asn1_flag(ecgroup, asn1_flag); 
EC_GROUP_set_point_conversion_form(ecgroup, form); 
EC_KEY_set_group(eckey,ecgroup); 
EC_KEY_generate_key(eckey); 

//This gives me a null ecpoint 
EC_POINT_oct2point(ecgroup,ecpoint,key_as_binary_data,data_size-1,ctx); 
EC_KEY_set_public_key(eckey,ecpoint); 
+1

Если вы хотите получить помощь с EC_POINT_oct2point(), вы должны показать нам, как вы его вызываете. – caf

ответ

0

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

алгоритм изложен на википедии Elliptic_Curve_DSA Чтение «алгоритм генерации подписи» оказывается случайная информация используется, чтобы помочь в силе подписи и сделать его труднее атаковать, чтобы выяснить, закрытый ключ.

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

См. Раздел «Алгоритм проверки подписи», чтобы убедиться, что шаги проверки - это те, которые вы хотите использовать, чтобы подтвердить, что ваша версия openssl выводит допустимые подписи w.r.t. метод ECDSA и программа с закрытым исходным кодом.

+0

Заявка на справочную программу для поддержки FIPS 186-2 и предоставляется в качестве утилиты для подписи данных для использования на микропроцессоре. Я надеялся, что могу использовать один и тот же секретный ключ, случайные данные и данные как с моей программой, так и с справочной программой и получить одну и ту же подпись. Без возможности застраховать оба приложения использовать одни и те же случайные данные, мне придется вернуться к полной проверке подписи. Спасибо за ввод. – Belrog

0

Я не могу найти документы для RAND_clear, поэтому не могу комментировать, почему это не приводит к воспроизводимым случайным числам.

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

Так, например (очень плохие примеры, конечно), одна реализация может сделать это:

int random_number = rand() % n; 

и другой может сделать это:

int random_number = (rand() * n)/RAND_MAX; 

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

+0

Да, недостаток документов - главное препятствие для меня. Я пробовал код, пытаясь найти способы сделать то, что мне нужно. Спасибо за разъяснения. Кажется, я снова пытаюсь выяснить, как импортировать этот открытый ключ. Я надеялся предоставить случайные данные, а не только семя. Это, на мой взгляд, решило бы компонент случайных данных, но я пока недостаточно отчаянно, чтобы идти на случайный движок. – Belrog

2

Это, как вы должны идти о загрузке, что открытый ключ:

EC_KEY *key = NULL; 
    EC_POINT *pub_key; 
    const EC_GROUP *group; 

    SSL_library_init(); 
    SSL_load_error_strings(); 

    key = EC_KEY_new_by_curve_name(NID_sect163k1); 
    group = EC_KEY_get0_group(key); 
    pub_key = EC_POINT_new(group); 

    EC_POINT_hex2point(group, 
    "369368AF243193D001E39CE76BB1D5DA08A9BC0A63307AB352338E5EA5C0E05A0C2531866F3E3C2702", pub_key, NULL); 

    EC_KEY_set_public_key(key, pub_key); 

    if (!EC_KEY_check_key(key)) { 
    printf("EC_KEY_check_key failed:\n"); 
    printf("%s\n",ERR_error_string(ERR_get_error(),NULL)); 
    } else { 
    printf("Public key verified OK\n"); 
    } 

кажется проверить ОК, поэтому он должен работать для проверки подписи.

Я думаю, что ваша ошибка, возможно, только что передала NULL (в ecgroup) в EC_POINT_new().

2

Причина, по которой вы получаете разные результаты, несмотря на то, что вы очищаете пул и перезагружаете его, заключается в том, что по умолчанию реализация RAND в OpenSSL приведет к выходу pid в выходной блок (именно для того, чтобы даже приложения, использующие одно и то же семя, не получить тот же вывод PRNG, поскольку 99,9% времени, которое происходит, - это Bad Thing).

Кроме того, даже если это не так, маловероятно, что ваше ссылочное приложение использует тот же PRNG, что и OpenSSL, чтобы превратить исходный файл в последовательность случайных байтов. (Если ваше ссылочное приложение фактически также использует OpenSSL, конечно). То, что вам нужно сделать, - это сначала выяснить, какой PRNG использует эталонное приложение - это может быть стандартный дизайн PRNG, такой как X9.31 или FIPS-186, или может быть что-то совершенно обычай. Затем переопределите этот проект для OpenSSL и подключите его через RAND_set_rand_method.

Как проверке: он выглядит, как вам нужно переставлять строки:

ecpoint = EC_POINT_new(ecgroup); 
    ecgroup = EC_GROUP_new_by_curve_name(OBJ_sn2nid("sect163k1")); 

В противном случае ecpoint установлено значение NULL, с самого начала, и это вызывает EC_KEY_generate_key на неудачу, потому что группа устанавливается в NULL , Цитируя крипто OpenSSL-0.9.8k в/ес/ec_key.c:

if (!eckey || !eckey->group) 
    { 
    ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); 
    return 0; 
    } 
+0

Это имеет большой смысл. Справочное приложение использует данный файл в качестве источника случайных данных. Естественно, что они могут делать что-либо со случайностью, но при сравнении сигнатур последовательных прогонов они равны. Я считаю, что это показывает, что данный случайный источник фактически используется как таковой, без изменений. Посещение OpenSSL их внутреннего RAND-механизма - это, безусловно, лучший способ для случайности - если вы не хотите случайности :) Подмена строк - очевидная ошибка, неудивительно, что я пропустил ее. Спасибо вам за помощь. – Belrog

1

Вы можете контролировать случайные данные OpenSSL производит во время подписания с помощью метода:

ECDSA_SIG* ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);

где kinv является случайное число, которое используется во время подписания.

Смежные вопросы