Tôi có thể sử dụng một cấp phát tùy chỉnh cho std :: mảng cho các khóa mật mã an toàn không?


9

Tôi biết std::arrayđược phân bổ hoàn toàn trong ngăn xếp, nhưng câu hỏi này được thúc đẩy bởi các mối quan tâm bảo mật đòi hỏi hai điều:

  1. Dữ liệu trong std::arraysẽ là zerod hoặc ngẫu nhiên khi hủy
  2. Dữ liệu trong std::arraysẽ bị khóa , sao cho nó không bao giờ vào đĩa mà không gặp sự cố hoặc trên bộ nhớ trao đổi

Thông thường, với std::vector, giải pháp là để tạo ra một cấp phát tùy chỉnhlàm các điều ấy . Tuy nhiên, đối với std::array, tôi không thấy làm thế nào để làm điều này, và do đó câu hỏi này.

Điều tốt nhất tôi có thể làm là đây:

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);
    }
}

Nhưng điều này rõ ràng là thiếu khóa bộ nhớ và làm phức tạp sơ đồ hiệu suất của std::arrayđiều đó sẽ đạt được bằng cách sử dụng std::arrayở nơi đầu tiên.

Có giải pháp nào tốt hơn không?


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Samuel Liew

Xin lỗi, đó là cho các mod; cái kia là mod từ chối cờ chứ không phải bạn. Tất nhiên, điều duy nhất bạn có thể làm là cho biết câu trả lời có đúng hay không, vì vậy tôi có thể gán tiền thưởng cho câu trả lời tốt nhất. Tất nhiên tôi có thể đánh giá bản thân mình, nhưng tôi không phải là một chuyên gia tuyệt vời. Lý do cho tiền thưởng biến mất dù sao đi nữa một khi nó được chỉ định.
Maarten Bodewes

@ Maarten-rebstateMonica Thật không may, không có câu trả lời nào giải quyết vấn đề một cách sạch sẽ.
Nhà vật lý lượng tử

@TheQuantumPhysicist Điều gì sẽ được coi là một cách sạch sẽ? Bạn có thể thử và làm cho những yêu cầu rõ ràng? Điều đó giúp suy nghĩ về một giải pháp có thể là tốt. Tôi nghĩ rằng tôi có thể biết ý của bạn, nhưng tôi cũng nghĩ bạn có thể chính xác hơn.
Maarten Bodewes

@ Maarten-rebstateMonica Sử dụng bộ cấp phát mà chúng tôi đã có theo một cách nào đó. Viết lại công cụ từ đầu là một ý tưởng tồi và sẽ yêu cầu thử nghiệm. Đó nên là phương sách cuối cùng. Các câu trả lời dưới đây đang gợi ý các giải pháp rõ ràng mà tôi đã đề cập đến trong phần bình luận (trước khi chuyển chúng sang trò chuyện).
Nhà vật lý lượng tử

Câu trả lời:


5

std::arraykhông thể sử dụng một bộ cấp phát; tuy nhiên, có vẻ như lớp SecureArray của bạn có thể đạt được những gì bạn muốn thông qua một hàm tạo / giải mã tùy chỉnh.

Một cái gì đó như thế này:

#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);
    }
};

4

Tôi biết std::arraylà hoàn toàn được phân bổ trong ngăn xếp

Điều này hoàn toàn không đúng. std::arraykhông phân bổ bất kỳ bộ nhớ, vì vậy nó phụ thuộc vào nơi bạn phân bổ nó.

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

Nhưng điều này rõ ràng là thiếu khóa bộ nhớ và làm phức tạp sơ đồ hiệu suất của std::arrayđiều đó sẽ đạt được bằng cách sử dụng std::arrayở nơi đầu tiên.

Thứ nhất, nó không phải là một vấn đề để khóa bộ nhớ trên ngăn xếp. Xem ví dụ 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;
    }
}

Vì vậy, bạn chỉ có thể gọi mlockhoặc bất kỳ tương tự di động trong SecureArrayconstructor.

Thứ hai, những gì bạn đạt được hiệu suất đạt được? Tốc độ đọc / ghi bộ nhớ không phụ thuộc vào nơi bạn phân bổ mảng của mình, trên heap hoặc trên ngăn xếp. Vì vậy, tất cả là về tốc độ bạn có thể phân bổ và khóa bộ nhớ. Nếu hiệu suất là quan trọng, khóa bộ nhớ có thể quá chậm (hoặc không, ai biết?) Để gọi nó mỗi lần trong hàm SecureArraytạo ngay cả khi bộ nhớ được cấp phát trên ngăn xếp.

Vì vậy, nó thuận tiện hơn để sử dụng std::vectorvới phân bổ tùy chỉnh. Nó có thể preallocate và prelock bộ nhớ lớn, do đó tốc độ phân bổ sẽ nhanh như trên stack.


Đây hoàn toàn không phải là về tốc độ, đó là về bảo mật và đảm bảo rằng mọi thứ không bị di chuyển, vì di chuyển thường có nghĩa là sao chép.
Maarten Bodewes

2
@ Maarten-recoveryMonica hmm ... có vẻ như tôi đã không có ý định sử dụng std::arraythay vì std::vectorở nơi đầu tiên. Tôi nghĩ đó là về tốc độ phân bổ.
Stas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.