2013-08-31 122 views
2

我已經將Christophe Devine的FIPS-197 compliant AES implementation包裝在託管的C++/CLI類中。在加密/解密每個4096字節的20到52個塊之後,我遇到了麻煩。我已經能夠縮小問題到這一點:內存和結構互操作性的C++/CLI編組/混疊

如果我宣佈一個本地指針aes_context結構,只是新一輪上漲在構造函數中aes_context,像這樣

Aes::Aes() 
    : m_Context(new aes_context) 
{ 
} 

然後代碼會運行良好。

但是,當我試圖宣佈aes_contextarray<System::Byte>^,然後在構造函數中執行此

Aes::Aes() 
    : m_Context(gcnew array<System::Byte>(sizeof(aes_context))) 
{ 
} 

雖然它編譯並在理論上應該工作,這個現在不

pin_ptr<System::Byte> pinned_context = &m_Context[0]; 
auto context = (aes_context*)pinned_context; 
aes_crypt_cbc(context, ...); 

有效和有限的經驗,這應該工作得很好。唯一的區別是內存是由GC分配的,我必須在將內存傳遞給AES庫之前對其進行固定。我還應該澄清這是一個在運行時發生的錯誤,而不是編譯器錯誤。

我無法以任何其他方式重現此問題,並且我針對其他參考實施運行的所有測試均未發現實施方面的任何問題。我甚至設置了兩個完全相同的測試用例,一個用C語言編寫,一個用C++/CLI(使用託管包裝調用AES庫);當託管的字節數組支持託管包裝器不起作用!

由於問題沒有通過公平的數據處理後顯示出來,我一直認爲這是一個截斷或對齊問題,但無論我多少分配過多,我都會得到相同的結果。

我正在使用Visual Studio 2012 C++編譯器。

有沒有人知道任何可能暗示爲什麼會出現這種情況?

+0

是'數組<系統::字節> ^'正確/有意? –

+0

@JonathanLeffler是的,它告訴C++/CLI編譯器它是一個託管類型。由'gcnew'返回的任何值都有'^'的類型來指示它的生命週期由GC管理。它反過來限制你如何使用這種類型來確保正確的行爲。 –

+0

好的 - 我對是否刪除它有所懷疑,並決定檢查。這是微軟對C++ 11標準(和/或任何早期的C++標準)的擴展,不是嗎? –

回答

3

不確定是只有問題,但aes_context被聲明爲包含指針rk;

typedef struct 
{ 
    int nr;      /*!< number of rounds */ 
    unsigned long *rk;   /*!< AES round keys */ 
    unsigned long buf[68];  /*!< unaligned data */ 
} 
aes_context; 

...由(例如)aes_setkey_enc指向一個地址insinde buf相同的上下文內設定;

ctx->rk = RK = ctx->buf; 

如果 - 這個指針,而且你的釘住指針之間 - 的情況下內存塊是在內存中移動,則將ctx-> RK將指向未分配的內存。

我懷疑製作m_Context固定指針,以保持它永久固定,而不是暫時固定它爲每個調用將使程序運行成功。

+1

當然,就是這樣!我改變了它,所以我存儲了'rk',相對'buf'和瞧。謝謝,我一直堅持這一段時間! –