OpenSSL BN_CTX用法

时间:2013-05-08 09:47:11

标签: openssl bignum

here我知道BN_CTX是一个保存BIGNUM临时变量的结构。那些BIGNUM变量何时进入BN_CTX的BN_POOL?如果我有一个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 个答案:

答案 0 :(得分:17)

我在这里回答我自己的问题。我想它总是在SO中发生。

OpenSSL中的BIGNUM是一个复杂的结构,它拥有一个任意大的数字,因此重复创建和释放BIGNUM实例将导致相当大的开销。创建BIGNUM上下文或BN_CTX并用于节省此开销。

<强>结构

BN_CTX结构包含两个结构:BN_POOLBN_STACKBN_POOL使用链表保留一组临时bignums,而BN_STACK管理堆栈帧。

创建

使用BN_CTX创建ctx实例BN_CTX_new()。函数必须先调用BN_CTX_start()才能获得新的堆栈帧。通过调用BN_CTX_get(ctx),OpenSSL会在BN_POOL ctx中查找未使用的bignum。如果没有任何可用的临时值,OpenSSL将创建一个并链接到链表。必须在将ctx作为参数传递给其他函数之前完成此操作。

当然,有一种机制可以阻止用户创建过多的临时bignums。您可以在BN_POOL内创建的预定义数量的bignums为16.一旦超出限制,OpenSSL库中的随机位置就会发生可能的分段错误。

退出

使用BIGNUM实例完成函数后,它从ctx获得并准备退出,调用BN_CTX_end()以释放临时bignums,这意味着这些bignums变为“未使用”并且可以被请求到下一个BN_CTX_get()

最后,可能在多次BN_CTX_start()BN_CTX_end()后,BN_CTX_end()被调用以释放BN_STACK结构,并清除BN_POOL中的免费bignums。< / p>

示例代码

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()时,会创建临时bignum并将其存储在BN_POOL中并返回。后续BN_CTX_get()中的bar()不会创建新的bignum,而是返回它首先创建的那个。 BN_CTX_free() foo()中的BN_CTX最终会清除这个临时的bignum。

<强>结论

当关注性能时,使用BN_CTX通过将BIGNUM创建的开销传递给

来保存BIGNUM创建的开销
  1. 要求BIGNUM结构保存临时大号,
  2. 按顺序调用以执行某些bignum操作,或
  3. 在循环中反复调用。
  4. 请注意bn = BN_new(); if (bn) BN_free(bn); 中存储的bignum数量有限制。如果性能不是问题,那么使用

    {{1}}

    很好。