从这里中我了解到,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 *bn;,在什么情况下我应该使用
BN_CTX_start(ctx);
bn = BN_CTX_get(ctx);
BN_CTX_end(ctx);而不是只是新的和自由的实例?
bn = BN_new();
if (bn)
BN_free(bn);发布于 2013-05-16 03:56:14
我在这里回答我自己的问题。我想这种事总是会发生的。
OpenSSL中的BIGNUM是一个复杂的结构,包含任意大的数字,因此重复创建和释放BIGNUM实例将导致相当大的开销。创建并使用BIGNUM上下文或BN_CTX来节省此开销。
结构
BN_CTX结构包含两个结构:BN_POOL和BN_STACK。BN_POOL使用链接列表保存一捆临时符号,而BN_STACK则管理堆栈框架。
On Create
BN_CTX实例ctx是用BN_CTX_new()创建的。函数必须调用BN_CTX_start()才能首先获得新的堆栈帧。通过调用BN_CTX_get(ctx),OpenSSL在BN_POOL of ctx中查找未使用的大号。如果没有可用的temp,OpenSSL将创建一个并链接到链接列表。这必须在将ctx作为参数传递给其他函数之前完成。
当然,有一种机制可以防止用户创建过多的临时宏。您可以在BN_POOL中创建的预定义值为16。一旦超出限制,可能的分割错误将在OpenSSL库中的任意位置发生。
在出口
在使用从ctx获得并准备退出的BIGNUM实例完成该函数之后,将调用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() in foo()释放。
结论
在考虑性能时,请使用BN_CTX将BIGNUM创建的开销传递给以下函数:
请注意,在BN_CTX中存储的大型表的数量是有限制的。如果性能不是问题,那么使用
bn = BN_new();
if (bn)
BN_free(bn);一切都很好。
https://stackoverflow.com/questions/16437475
复制相似问题