Güvenli şifreleme anahtarları için std :: array için özel bir ayırıcı kullanabilir miyim?


9

std::arrayYığında tamamen tahsis edildiğini biliyorum , ancak bu soru iki şey gerektiren güvenlik endişeleri tarafından teşvik ediliyor:

  1. İçindeki veriler std::arraysıfır veya imha üzerine rastgele olacak
  2. İçindeki veriler kilitlenecek , böylece kilitlenme veya takas belleğinde asla diske std::arraygitmeyecek

Genellikle ile std::vector, çözüm yaratmaktır özel allocator bunları yapar . Ancak, std::arraybunun nasıl yapılacağını ve dolayısıyla bu soruyu göremiyorum.

Yapabileceğim en iyi şey şudur:

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

Ancak bu açıkça bellek kilitlenmesinden yoksundur ve ilk etapta std::arraykullanılmasıyla elde edilecek performans şemasını zorlaştırır std::array.

Daha iyi bir çözüm var mı?


Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
Samuel Liew

Üzgünüm, bu modlar içindi; Diğeri ise bayrağı değil, modu reddeden moddu. Yapabileceğiniz tek şey elbette cevapların doğru olup olmadığını belirtmektir, böylece ödülü en iyi olana atayabilirim. Kendimi elbette değerlendirebilirim, ama o kadar da uzman değilim. Ödülün nedeni tayin edildikten sonra yine de kaybolur.
Maarten Bodewes

@ Maarten-reinstateMonica Maalesef cevapların hiçbiri sorunu temiz bir şekilde çözmüyor.
Kuantum Fizikçisi

@TheQuantumPhysicist Temiz bir yol olarak düşünmek için ne gerekir? Bu gereksinimleri açık hale getirebilir misiniz? Bu da olası bir çözümü düşünmeye yardımcı olur. Ne demek istediğini bildiğimi düşünüyorum, ama muhtemelen daha kesin olabileceğini düşünüyorum.
Maarten Bodewes

@ Maarten-reinstateMonica Zaten bir şekilde sahip olduğumuz bir ayırıcı kullanmak. Öğeleri sıfırdan yeniden yazmak kötü bir fikirdir ve çok fazla test gerektirecektir. Bu son çare olmalı. Aşağıdaki cevaplar, daha önce bahsettiğim, yorumlarda kaçındığım (sohbetleri taşımadan önce) bariz çözümler olduğunu gösteriyor.
Kuantum Fizikçisi

Yanıtlar:


5

std::arraybir ayırıcı kullanamaz; ancak, SecureArray sınıfınız özel bir kurucu / kod çözücü aracılığıyla istediğinizi başarabiliyor gibi görünüyor.

Bunun gibi bir şey:

#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

Ben std::arraytamamen yığın tahsis biliyorum

Bu tam olarak doğru değil. std::arraybellek ayırmaz, bu yüzden nereye ayırdığınıza bağlıdır.

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

Ancak bu açıkça bellek kilitlenmesinden yoksundur ve ilk etapta std::arraykullanılmasıyla elde edilecek performans şemasını zorlaştırır std::array.

İlk olarak, yığındaki belleği kilitlemek bir sorun değildir. POSIX örneğine bakın:

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

Böylece, sadece kurucuda mlockveya herhangi bir taşınabilir analogu çağırabilirsiniz SecureArray.

İkincisi, ne gibi bir performans kazancı bekliyorsunuz? Bellek okuma / yazma hızı, dizinizi nereye ayırdığınıza, yığına veya yığına bağlı değildir. Yani, her şey hafızayı ne kadar hızlı tahsis edip kilitleyebileceğinizle ilgilidir. Performans kritikse, bellek kilitleme yığınta SecureArraybellek ayrılmış olsa bile yapıcıda her seferinde çağıracak kadar yavaş olabilir (ya da bilmez?) .

Bu nedenle, std::vectorözel ayırıcı ile kullanmak daha kullanışlıdır . Büyük bellek yığınlarını önceden konumlandırabilir ve önleyebilir, bu nedenle ayırma hızı neredeyse yığındaki kadar hızlı olacaktır.


Bu hiç de hız ile ilgili değil, güvenlik ve her şeyin taşınmamasını sağlamaktır, çünkü hareket genellikle kopyalama anlamına gelir.
Maarten Bodewes

2
@ Maarten-reinstateMonica hmm ... görünüşe göre kullanma niyeti alamadım std::array yerine std::vectorilk etapta. Tahsis hızı ile ilgili olduğunu düşündüm.
Stas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.