2

我已将 Christophe Devine 的符合 FIPS-197 的 AES 实现封装在托管 C++/CLI 类中。在加密/解密 20 到 52 个每个 4096 字节的块后,我遇到了麻烦。我已经能够将问题缩小到这个:

如果我声明一个指向结构的本机指针aes_contextaes_context在构造函数中新建一个,就像这样

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

然后代码将运行良好。

但是当我尝试在构造函数中声明aes_contextasarray<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++ 编译器。

有谁知道任何可能暗示为什么会这样的事情?

4

1 回答 1

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为指向buf同一上下文内的内部地址;

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

如果 - 在该指针集和您固定指针之间 - 上下文内存块在内存中移动,则 ctx->rk 将指向未分配的内存。

我怀疑制作m_Context一个固定指针以使其永久固定而不是为每次调用临时固定它会使程序成功运行。

于 2013-08-31T05:03:16.550 回答