Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: OpenSSL - генерация RSA ключей  (Прочитано 13533 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 03-09-2019 13:19 » 

пытаюсь при помощи библиотеки OpenSSL сгенерить открытый и закрытый ключи RSA

вот такой код, найденный в интернете, позволяет сохранить ключи в файлы

Код: (C++)
RSA*    rsa=0;
BIGNUM* bignum=0;
BIO*    bp_public=0;
BIO*    bp_private=0;
do
{
        int             ret = 0;
        int             bits = 2048;
        unsigned long   e = RSA_F4;

        // 1. generate rsa key
        bignum = BN_new();
        ret = BN_set_word(bignum,e);
        if(ret != 1)break;

        rsa = RSA_new();
        ret = RSA_generate_key_ex(rsa, bits, bignum, 0);
        if(ret != 1)break;

        // 2. save public key
        bp_public = BIO_new_file("public.pem", "w+");
        ret = PEM_write_bio_RSAPublicKey(bp_public, rsa);
        if(ret != 1)break;

        // 3. save private key
        bp_private = BIO_new_file("private.pem", "w+");
        ret = PEM_write_bio_RSAPrivateKey(bp_private, rsa, NULL, NULL, 0, NULL, NULL);
        if(ret != 1)break;

        int iii=1;
}while(0);

// 4. free
if(bp_public )BIO_free_all(bp_public);
if(bp_private)BIO_free_all(bp_private);
if(rsa       )RSA_free    (rsa);
if(bignum    )BN_free     (bignum);

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

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

Добавлено через 44 секунды:
как вариант - подскажите более вменяемую библиотеку/реализацию для c++

« Последнее редактирование: 03-09-2019 13:19 от Алексей1153 » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 03-09-2019 21:39 » 

В доке есть:
BIO *mem = BIO_new(BIO_s_mem());
попробуй...


EXAMPLE
       Create a memory BIO and write some data to it:

        BIO *mem = BIO_new(BIO_s_mem());
        BIO_puts(mem, "Hello World\n");

       Create a read only memory BIO:

        char data[] = "Hello World";
        BIO *mem;
        mem = BIO_new_mem_buf(data, -1);

       Extract the BUF_MEM structure from a memory BIO and then free up the BIO:

        BUF_MEM *bptr;
        BIO_get_mem_ptr(mem, &bptr);
        BIO_set_close(mem, BIO_NOCLOSE); /* So BIO_free() leaves BUF_MEM alone */
        BIO_free(mem);
« Последнее редактирование: 03-09-2019 21:41 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 04-09-2019 03:39 » 

Ром, спасибо, теперь разобрался )
Вот вариант, где есть сохранение и в файл, и в вектор. Результаты идентичные

Код: (C++)
RSA*    rsa=0;
BIGNUM* bignum=0;

std::vector<char> key_public;
std::vector<char> key_private;
do
{
        const int bits=2048;
        const BN_ULONG e = RSA_F4;
        int result=0;

        //генерация ключей, заполнение структуры RSA
        bignum = BN_new();
        result = BN_set_word(bignum,e);
        if(result != 1)break;

        rsa = RSA_new();
        result = RSA_generate_key_ex(rsa, bits, bignum, 0);
        if(result != 1)break;

        //сохранение в файлы
        {
                //public
                if(BIO* file=BIO_new_file("public.pem", "w+"))
                {
                        result=PEM_write_bio_RSAPublicKey(file, rsa);
                        if(result != 1)
                        {
                                //файл не создан
                        }
                        BIO_free_all(file );
                }

                //private
                if(BIO* file=BIO_new_file("private.pem", "w+"))
                {
                        result=PEM_write_bio_RSAPrivateKey(file, rsa, 0, 0, 0, 0, 0);
                        if(result != 1)
                        {
                                //файл не создан
                        }
                        BIO_free_all(file);
                }
        }

        //сохранение в память
        {
                //public
                {
                        BIO* memo=BIO_new(BIO_s_mem());
                        result = PEM_write_bio_RSAPublicKey(memo, rsa);
                        if(result != 1)
                        {
                                //не удалось записать в память
                                BIO_free(memo);
                        }
                        else
                        {
                                BUF_MEM* bufptr=0;
                                BIO_get_mem_ptr(memo, &bufptr);
                                BIO_set_close(memo, BIO_NOCLOSE);
                                BIO_free(memo);

                                if(bufptr->length && bufptr->data)
                                {
                                        key_public.assign(bufptr->data,bufptr->data+bufptr->length);
                                }

                                BUF_MEM_free(bufptr);
                        }

                }

                //private
                {
                        BIO* memo=BIO_new(BIO_s_mem());
                        result = PEM_write_bio_RSAPrivateKey(memo, rsa, 0, 0, 0, 0, 0);
                        if(result != 1)
                        {
                                //не удалось записать в память
                                BIO_free(memo);
                        }
                        else
                        {
                                BUF_MEM* bufptr=0;
                                BIO_get_mem_ptr(memo, &bufptr);
                                BIO_set_close(memo, BIO_NOCLOSE);
                                BIO_free(memo);

                                if(bufptr->length && bufptr->data)
                                {
                                        key_private.assign(bufptr->data,bufptr->data+bufptr->length);
                                }

                                BUF_MEM_free(bufptr);
                        }
                }
        }

        int iii=1;
}while(0);

//чистка выделенной памяти
if(rsa       )RSA_free    (rsa   );rsa=0;
if(bignum    )BN_free     (bignum);bignum=0;
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 04-09-2019 08:40 » 

допустим, ключи создавалиь с битностью 2048

а правильно ли я понимаю, что данные, скажем, длиной 259 байтов, одним блоком не шифруются, а разбиваются на блоки кратно значению (256-42)==(RSA_size()-paddingsize)==214 байта, и каждый блок на выходе даёт зашифрованный блок размером 256 ?

При раскодировании всё в обратном порядке - берём по 256, расшифровываем и складываем по <=214 байтов в результат

По крайней мере, я так попробовал - получилось (в том смысле, что то, что закодировал, идентично тому, что потом раскодировалось).
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 04-09-2019 14:51 » 

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

не осилил:
- шифрование публичным ключом (пока что это мою задачу не тормозит, поэтому не критично)

--------------------------------

удивляет дикость интерфейса openssl, как-будто это всё было написано лет 20 назад энтузиастом С (без плюсов). Удивляет пустота документации. Там просто перечислены функции и кратно рассказано о параметрах. По этим докам ничего не слепливается, либо нужно много много рыть интернет, а также подключать метод научного тыка  А черт его знает... Если бы в тех же доках были бы просто живые примеры, как из этих кубиков сделать нужное действие, было бы уже терпимо. Но, увы (

Альтернативу кто-нибудь знает ?  Краснею
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 04-09-2019 19:15 » 

Шифруешь приватным ключем? Это называют подписью. Для шифрования приватым ключем, обычно, сперва вычисляют хеш, который и шифруют. Хеш имеет фиксированную длину и непредсказуемые байты в составе, это, с одной стороны, упрощает задачу, с другой стороны, повышает стойкость.
Если ты хочешь восстановить потом данные, то да, придется либо брать больший ключ, либо шифровать кусками.

Шифрование публичным ключем принимает буфер любой длины, если не ошибаюсь. Ошибаюсь.


В доке все описано.
https://www.openssl.org/docs/man1.1.1/man3/RSA_public_encrypt.html
Для каждого режима заполнения указаны предельные размеры шифруемых данных. Заметь, используется RSA_size для определения базового размера, не надо высчитывать руками, чревато неприметными ошибками.

У тебя какая версия OpenSSL?
Кстати, какая цель шифрования?
« Последнее редактирование: 04-09-2019 21:43 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 05-09-2019 03:58 » 

RXL, шифрую публичным. В данный момент не шифрую, не сумел загрузить ключ, созданный PEM_write_bio_PUBKEY, в структуру RSA (если ключ создан PEM_write_bio_RSAPublicKey, то загрузить получается, но тогда ключ кривой). RSA_size - использую, ага (и ещё 42 байта для RSA_PKCS1_OAEP_PADDING нужно отнимать от этого значения)

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

цель шифрования - отдаю на ту сторону публичный ключ, мне приходит зашифрованный блок данных, раскрываю приватным
Записан

darkelf
Молодой специалист

no
Offline Offline

« Ответ #7 : 05-09-2019 06:55 » 

Как вариант - попробуйте посмотреть в сторону GNU TLS, если подходит лицензия. Если я правильно понял, то она тоже должна уметь нечто подобное.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 06-09-2019 04:54 » 

darkelf, спасибо, посмотрю. А что там с лицензией?
Записан

darkelf
Молодой специалист

no
Offline Offline

« Ответ #9 : 06-09-2019 05:22 » new

LGPL (в принципе не страшно) и GPL
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines