2010-09-24 15 views
13

Bu soru, this related question numaralı telefondan @sharptooth tarafından yapılan bir öneriyi izliyor.Parola korumalı bir sınıf nasıl yazılır?

std::string, parola güvenli hale gelsin diye düzeltilebilir mi? Aksi takdirde, bir şifre-işleme sınıfı (yani belleğe yazdığı şey hakkında büyük bir özen gösterip yıkımdan önce temizleyen bir sınıf) yazmanın ilkeleri ne olurdu?

template <class T> class SecureAllocator : public std::allocator<T> 
{ 
public: 
    template<class U> struct rebind { typedef SecureAllocator<U> other; }; 

    SecureAllocator() throw() {} 
    SecureAllocator(const SecureAllocator&) throw() {} 
    template <class U> SecureAllocator(const SecureAllocator<U>&) throw() {} 

    void deallocate(pointer p, size_type n) 
    { 
     std::fill_n((volatile char*)p, n*sizeof(T), 0); 
     std::allocator<T>::deallocate(p, n); 
    } 
}; 

Bu ayırıcısı ayırmayı kaldırma önce hafızayı sıfırlar:

+1

1) std: wstring'i kullanın, 2) parola sembolleri yerine 0x2022'yi itin: o) Cidden, başka bir işlemin belleğinizden bir şey koklamasından korkuyorsanız, bazı maskeleri ekleyin/çıkarın (xor?) – alxx

+0

@alxx : Std :: string 'yerine std :: wstring 'kullanılması daha güvenli olur mu? Bir şey mi eksik? – ereOn

+1

0x2022 madde işareti simgesi. Anla? :) – alxx

cevap

19

Evet, öncelikle özel ayırıcısı tanımlayın. Şimdi typedef:

typedef std::basic_string<char, std::char_traits<char>, SecureAllocator<char>> SecureString; 

Ancak orada küçük bir sorun, std :: string küçük dize optimizasyonu kullanmak ve dinamik tahsisi olmadan kendi içinde bazı verileri depolayabilir. Yani yıkım açıkça anlaşılır o olmalı veya özel ayırıcısı ile öbek üzerinde tahsis:

int main(int, char**) 
{ 
    using boost::shared_ptr; 
    using boost::allocate_shared; 
    shared_ptr<SecureString> str = allocate_shared<SecureString>(SecureAllocator<SecureString>(), "aaa"); 

} 

Bu, tüm veriler serbest bırakma önce sıfırlanır garanti, örneğin dize boyutu da dahil olmak üzere.

+5

'std :: fill_n' kullanmayın,' SecureZeroMemory() 'gibi bir şey kullanın (http://msdn.microsoft.com/en-us/library/aa366877(VS.85).aspx) - std ile :: fill_n' derleyici, silme işlemini optimize edebilir. – sharptooth

+0

Ayrıca, std :: string'i zorlamak için bir ayar vardır: çağrı kodu, dizenin kısaltılmasına neden olduğunda alanı silebilir - örneğin ilk N öğesini kaldırır ve kuyruk, "sola doğru" hareket ettirir ve karakterleri "bırakır" "? – sharptooth

+1

@sharptooth SecureZeroMemory standart değildir ve uçucu, optimizasyonu önler. Evet, sistem çağrısı yoksa, CPU önbelleği temizlemeden önce bazı veriler bellekte kalabilir. – ybungalobill

İlgili konular