我可以使用 std::array 的自定义分配器来获取安全加密密钥吗?

The*_*ist 9 c++ arrays cryptography allocator c++11

我知道std::array在堆栈中完全分配,但这个问题是出于安全考虑,需要两件事:

  1. 中的数据std::array将在销毁时归零或随机化
  2. 输入的数据std::array将被锁定,这样它就不会在崩溃或交换内存时进入磁盘。

通常,std::vector解决方案是创建一个自定义分配器执行这些操作。然而,对于std::array,我不知道如何做到这一点,因此这个问题。

我能做的最好的是:

template <typename T, std::size_t Size>
struct SecureArray : public std::array<T, Size>
{
    static_assert(std::is_pod<T>::value, "Only POD types allowed")
    static_assert(sizeof(T) == 1, "Only 1-byte types allowed")
    virtual ~SecureArray()
    {
        std::vector<uint8_t> d = RandomBytes(Size); // generates Size random bytes
        std::memcpy(this->data(), d.data(), Size);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这显然缺乏记忆锁定和复杂化的表现方式std::array是通过使用来获得std::array在首位。

有没有更好的解决办法?

cly*_*yne 5

std::array不能使用分配器;但是,似乎您的 SecureArray 类可以通过自定义构造函数/解构函数实现您想要的。

像这样的东西:

#include <sys/mman.h>

template<class T, std::size_t Size>
struct SecureArray : public std::array<T, Size>
{
    // Your static_asserts...

    SecureArray(void) {
        mlock(std::array<T, Size>::data(), sizeof(T) * Size);
    }

    ~SecureArray(void) {
        char *bytes = reinterpret_cast<char *>(std::array<T, Size>::data());
        for (std::size_t i = 0; i < sizeof(T) * Size; i++)
            bytes[i] = 0;
        munlock(bytes, sizeof(T) * N);
    }
};
Run Code Online (Sandbox Code Playgroud)


Sta*_*tas 5

我知道std::array完全在堆栈中分配

这并不完全正确。std::array不分配任何内存,所以这取决于你分配它的位置。

auto* arr = new std::array<int, 100>(); // BUM! it is allocated on the heap
Run Code Online (Sandbox Code Playgroud)

但这显然缺乏内存锁定,并使首先std::array通过使用获得的性能方案变得复杂。std::array

首先,在堆栈上锁定内存不是问题。请参阅 POSIX 示例:

#include <iostream>
#include <sys/mman.h>
#include <array>

int main()
{
    std::array<int, 3> a = {1, 2, 3};        // std::array allocated on the stack
    if (mlock(a.data(), sizeof(a)) == 0)
    {
        std::cout << "LOCKED" << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以在构造函数中调用mlock或任何可移植的模拟SecureArray

其次,您期望获得什么性能提升?内存读/写速度并不取决于您在堆上或堆栈上分配数组的位置。因此,关键在于分配和锁定内存的速度。如果性能至关重要,那么即使内存是在SecureArray堆栈上分配的,内存锁定也可能太慢(或者慢,谁知道呢?)而无法每次在构造函数中调用它。

std::vector因此,与自定义分配器一起使用会更方便。它可以预分配和预锁定大内存块,因此分配速度几乎与堆栈上一样快。

  • @Maarten-reinstateMonica 嗯...看来我首先没有想到使用 `std::array` 而不是 `std::vector` 。我认为这与分配速度有关。 (2认同)