You have to be aware of all the temporary copies that may be done. If you want to avoid this you must manually erase memory before deallocating each temporal copy. Unfortunately that cannot be done with the standard QString
since the implementation is closed.
You can, however, specialise std::basic_string
using a custom allocator, which, before deleting can clean up the memory block (see below for an example). You can use this new secure string to manipulate your password instead of a plain char array, if you find it more convenient. I'm not sure is std::basic_string
can be specialised with QChar
, but if not you can use any of the Unicode characters from C++11 (char16_t
, char32_t
...) instead if you need other than ANSI support.
Regarding the user interface, I think an option you have is to create your own text input widget, reimplementing the keyPressEvent
/ keyReleaseEvent
to store the typed password into either the secure string or a char array. Also reimplement the paintEvent
to display only stars, dots, or whatever other masking character you want. Once the password has been used just clear the array or empty the secure string.
Update: example of secure string
namespace secure {
template<class T>
class allocator : public std::allocator<T> {
public:
typedef typename std::allocator<T>::pointer pointer;
typedef typename std::allocator<T>::size_type size_type;
template<class U>
struct rebind {
typedef allocator<U> other;
};
allocator() throw() :
std::allocator<T>() {}
allocator(const allocator& other) throw() :
std::allocator<T>(other) {}
template <class U>
allocator(const allocator<U>& other) throw() :
std::allocator<T>(other) {}
void deallocate(pointer p, size_type num) {
memset(p, 0, num); // can be replaced by SecureZeroMemory(p, num) on Windows
std::allocator<T>::deallocate(p, num);
}
};
class string : public std::basic_string<char, std::char_traits<char>, allocator<char>> {
public:
string() :
basic_string() {}
string(const string& str) :
basic_string(str.data(), str.length()) {}
template<class _Elem, class _Traits, class _Ax>
string(const std::basic_string<_Elem, _Traits, _Ax>& str) :
basic_string(str.begin(), str.end()) {}
string(const char* chars) :
basic_string(chars) {}
string(const char* chars, size_type sz) :
basic_string(chars, sz) {}
template<class _It>
string(_It a, _It b) :
basic_string(a, b) {}
};
}