Чи можу я використовувати спеціальний розподільник для std :: array для захищених криптографічних ключів?


9

Я знаю 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);
    }
}

Але цього, очевидно, не вистачає блокування пам'яті і ускладнює схему продуктивності, std::arrayяку потрібно отримати, std::arrayв першу чергу, використовуючи.

Чи є краще рішення?


Коментарі не для розширеного обговорення; ця розмова була переміщена до чату .
Самуель Liew

Вибачте, це було для модників; іншим був мод, який відхилив прапор, а не ти. Єдине, що ви можете зробити, це, звичайно, вказати, чи правильні відповіді чи ні, тож я можу призначити виграш за найкращим. Я, звичайно, можу себе оцінити, але я не такий великий експерт. Причина виграші все одно зникає після її присвоєння.
Maarten Bodewes

@ Maarten-reinstateMonica На жаль, жодна з відповідей не вирішує проблему в чистому вигляді.
Квантовий фізик

@TheQuantumPhysicist Що потрібно вважати чистим способом? Чи можете ви спробувати зробити ці вимоги явними? Це допомагає задуматися і про можливе рішення. Я думаю, я можу знати, що ти маєш на увазі, але я також думаю, що ти можеш бути більш точним.
Maarten Bodewes

@ Maarten-reinstateMonica Використання алокатора, який у нас вже є якимось чином. Переписування матеріалів з нуля - погана ідея і вимагатиме певного тестування. Це має бути останнім засобом. Наведені нижче відповіді пропонують очевидні рішення, які я вже згадував, що уникаю в коментарях (перед тим, як перенести їх у чат).
Квантовий фізик

Відповіді:


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

4

Я знаю std::array, повністю виділений у стеку

Це не зовсім так. std::arrayне виділяє жодної пам’яті, тому це залежить від того, куди ви її виділите.

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

Але цього, очевидно, не вистачає блокування пам'яті і ускладнює схему продуктивності, 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;
    }
}

Отже, ви можете просто зателефонувати mlockабо будь-який портативний аналог в SecureArrayконструктор.

По-друге, який приріст продуктивності ви очікуєте отримати? Швидкість читання / запису пам'яті не залежить від того, де ви виділите масив, на купі чи на стеці. Отже, мова йде про те, як швидко можна виділити та заблокувати пам'ять. Якщо продуктивність критична, блокування пам'яті може бути занадто повільним (чи ні, хто знає?), Щоб викликати це щоразу в SecureArrayконструкторі, навіть якщо пам'ять виділяється на стек.

Отже, зручніше користуватися std::vectorспеціальним алокатором. Це може попередньо виділити та передблокувати великі шматки пам’яті, тому швидкість розподілу буде майже такою ж швидкою, як на стеку.


Йдеться зовсім не про швидкість, це про безпеку та переконайтеся, що речі не рухаються, оскільки переміщення загалом означає копіювання.
Maarten Bodewes

2
@ Maarten-reinstateMonica хм ... здається, я не отримав наміру використовувати std::arrayзамість цього std::vectorв першу чергу. Я подумав, що мова йде про швидкість розподілу.
Стас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.