2013-05-08 2098 views
9

here我知道BN_CTX是一個保存BIGNUM臨時變量的結構。這些BIGNUM變量何時會輸入BN_CTX的BN_POOL?如果我有BN_CTX *ctx;(無論是在我的函數的頂部聲明,或通過作爲參數)一bignum_ctx,當我應該做的OpenSSL BN_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); 

回答

15

這裏我回答我自己的問題。我想這一直髮生在所以。

OpenSSL中的BIGNUM是一個複雜的結構,它保存了一個任意大的數字,因此反覆創建和釋放BIGNUM實例會導致相當大的開銷。 BIGNUM上下文或BN_CTX被創建並用於保存此開銷。

結構

的BN_CTX結構包含兩種結構:BN_POOLBN_STACKBN_POOL用一個鏈接列表保留一組臨時的bignum,而BN_STACK管理這個棧幀。

上創建

一個BN_CTX例如ctxBN_CTX_new()創建。函數必須先調用BN_CTX_start()才能獲得新的堆棧幀。通過調用BN_CTX_get(ctx),OpenSSL在ctxBN_POOL中查找未使用的bignum。如果沒有任何可用的臨時數字,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()時,會創建一個臨時的bignum並存儲在BN_POOL中並返回。 BN_CTX_get()在隨後的bar()中不會創建新的bignum,而是返回它首先創建的那個。這個臨時性質將在foo()中被BN_CTX_free()最終清除。

結論

當性能是關注的,使用BN_CTX通過將其傳遞到

  1. 需要BIGNUM結構保存臨時大數字功能,以節省BIGNUM創建的開銷,以及
  2. 被順序調用來執行某些bignum操作,或者
  3. 在循環中被重複調用。

請注意,存儲在BN_CTX中的雙子的數量存在限制。如果性能不是問題,那麼使用

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

就好。

+1

什麼是堆棧幀? – updogliu 2013-12-30 06:47:56

+0

由於一個BN_CTX對象'ctx'可以從函數傳遞給函數,棧幀是用來追蹤這些函數調用深度的信息(它傳遞'ctx'作爲參數)以及分配給內存的大小'ctx'。 – ChiaraHsieh 2013-12-30 07:06:46

+0

我想這是釋放tmp變量函數的功能。如果有一個函數使用了兩個tmp BIGNUM'bn1 = BN_CTX_get(ctx); bn2 = BN_CTX_get(ctx);'對我來說,釋放'bn1'而不是'bn2'是沒有辦法的。它們只能在BN_CTX_end上一起發佈。棧幀信息是要記住這個函數使用了兩個tmps'bn1'和'bn2',我猜。 – updogliu 2013-12-30 15:48:02