2010-09-24 29 views
13

Esta pregunta sigue una sugerencia hecha por @sharptooth en this related question.¿Cómo escribir una clase segura con contraseña?

¿Se puede ajustar std::string para que sea seguro con contraseña?

Si no, ¿cuáles serían las pautas para escribir una clase de manejo de contraseñas (por lo tanto, una clase que tenga mucho cuidado con lo que escribe en la memoria y lo borre antes de la destrucción)?

+1

1) use std: wstring, 2) presione 0x2022 en lugar de símbolos de contraseña: o) En serio, si teme que otro proceso olfatee algo de su memoria, agregue/elimine alguna máscara (xor?) – alxx

+0

@alxx : ¿Cómo sería mejor usar 'std :: wstring' en lugar de' std :: string'? Me estoy perdiendo de algo ? – ereOn

+1

0x2022 es el símbolo de viñeta. ¿Consíguelo? :) – alxx

Respuesta

19

Sí, primero definir un asignador de costumbre:

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

Este asignador ceros la memoria antes de desasignar. Ahora typedef:

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

Sin embargo, hay un pequeño problema, std :: string puede utilizar la optimización de la cadena pequeña y almacenar algunos datos en el interior de sí mismo, sin la asignación dinámica. Por lo que debe explícitamente claro en la destrucción o la asignación en el montón con nuestro asignador personalizado:

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

} 

Esto garantiza que todos los datos se pone a cero antes de cancelación de asignación, incluyendo el tamaño de la cadena, por ejemplo.

+5

No use 'std :: fill_n', use algo como' SecureZeroMemory() '(http://msdn.microsoft.com/en-us/library/aa366877(VS.85).aspx) - con' std :: fill_n' el compilador podría optimizar el borrado. – sharptooth

+0

También hay un ajuste para forzar que 'std :: string' borre el espacio cuando el código de llamada hace que se acorte la cadena; por ejemplo, elimina los primeros N elementos y la cola se mueve" hacia la izquierda "y deja los caracteres" a la derecha " "¿?" – sharptooth

+1

@sharptooth SecureZeroMemory no es estándar y volátil impide la optimización. Sí, si no hay una llamada al sistema, algunos datos pueden permanecer en la memoria antes de que la CPU los vacíe. – ybungalobill

Cuestiones relacionadas