Использование OpenSSL BN_CTX

Отсюда я понимаю, что BN_CTX - это структура, которая содержит временные переменные BIGNUM. Когда эти переменные BIGNUM войдут в BN_POOL BN_CTX? Если у меня есть bignum_ctx BN_CTX *ctx;(либо объявлен в верхней части моей функции, либо передан в качестве аргумента), когда я должен сделать

ctx = BN_CTX_new();
/* Do something */
BN_CTX_free(ctx);

и когда я должен сделать следующее вместо этого?

BN_CTX_start(ctx);
/* Do something */
BN_CTX_end(ctx);

И если у меня есть Bignum BIGNUM *bn;при каких обстоятельствах я должен использовать

BN_CTX_start(ctx);
bn = BN_CTX_get(ctx);
BN_CTX_end(ctx);

а не просто новый и бесплатный экземпляр?

bn = BN_new();
if (bn)
    BN_free(bn);

1 ответ

Здесь я отвечаю на свой вопрос. Я думаю, что это происходит все время в SO.

BIGNUM в OpenSSL - это сложная структура, которая содержит произвольно большое число, и, следовательно, многократное создание и освобождение экземпляров BIGNUM приведет к значительным накладным расходам. Контекст BIGNUM, или BN_CTX, создается и используется для сохранения этих издержек.

Состав

Структура BN_CTX содержит две структуры: BN_POOL а также BN_STACK, BN_POOL хранит связку временных бигнумов со связанным списком, а BN_STACK управляет фреймом стека.

При создании

BN_CTX пример ctx создан с BN_CTX_new(), Функция должна вызывать BN_CTX_start() чтобы получить новый кадр стека первым. По телефону BN_CTX_get(ctx), OpenSSL ищет неиспользованный бигнум в BN_POOL из ctx, Если нет доступного временного значения, OpenSSL создаст его и создаст ссылку на связанный список. Это должно быть сделано до прохождения ctx в качестве аргумента для других функций.

Конечно, есть механизм, предотвращающий создание пользователем слишком большого количества временных номеров. Заранее определенное количество бигнумов, которые вы можете создать в BN_POOL равно 16. Как только предел превышен, вероятная ошибка сегментации произойдет в случайном месте в библиотеке OpenSSL.

На выходе

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

Наконец, вероятно, после нескольких раз BN_CTX_start() а также BN_CTX_end(), BN_CTX_end() призван к свободе BN_STACK структура, и очистить свободные номера в BN_POOL,

Пример кода

void foo(){
    BN_CTX* ctx;
    ctx = BN_CTX_new();

    /* Using BIGNUM context in a series of BIGNUM operations */
    bar(ctx);
    bar(ctx);
    bar(ctx);

    /* Using BIGNUM context in a function called in loops */
    while(/*condition*/){
        bar(ctx);
    }

    BN_CTX_free(ctx);
}

А вот и функция bar( )

void bar(BN_CTX* ctx){
    BIGNUM *bn;
    BN_CTX_start(ctx);
    bn = BN_CTX_get(ctx);

    /* Do something with bn */

    BN_CTX_end(ctx);
}

Функция foo() создает новый контекст BIGNUM и передает его в качестве аргумента функции bar(), По первому разу bar() звонки BN_CTX_get()временный бигнум создается и сохраняется в BN_POOL и возвращается. BN_CTX_get() в последующем bar() не будет создавать новый bignum, но вместо этого возвращает тот, который был создан в первую очередь. Этот временный бигнум будет окончательно освобожден BN_CTX_free() в foo(),

Заключение

Когда производительность вызывает беспокойство, используйте BN_CTX чтобы сэкономить на создании BIGNUM, передав его функциям, которые

  1. требовать, чтобы структуры BIGNUM содержали временные большие числа, и
  2. вызываются последовательно для выполнения определенных операций bignum, или
  3. неоднократно называются в циклах.

Имейте в виду, что существует ограничение на количество бигнумов, хранящихся в BN_CTX, Если производительность не является проблемой, то с помощью

bn = BN_new();
if (bn)
    BN_free(bn);

просто отлично.

Другие вопросы по тегам