Nullify QString Data Byte

I use QStringto store passwords. To be more precise, I use QStringto extract passwords from the GUI. The fact is that after using / using a password, I need to collapse (0) internal QStringdata bytes with a password in order to completely exclude it from memory.

Here are my studies:

  • After QStringdestruction, the data remains in non-zero memory;
  • When I try to modify QStringto execute it with zeros, it launches the copy-on-write idiom and allocates new memory for the modified data variant. Old data remains intact. The same thing happens even if I use the method QString::data(). Not quite sure why - probably because it returns not raw char *, but QChar *;
  • QString::clear(), = ""Really it is the same COW, as described above.

Q: How can I implement the correct cleaning QStringto prevent password leakage?

+4
source share
2 answers

. , , , - Qt Creator, QStrings, , .

constData()

Qt docs QString:: data():

constData() , .

, :

QString str = "password";
QString str2 = str;
QChar* chars = const_cast<QChar*>(str.constData());
for (int i = 0; i < str.length(); ++i)
    chars[i] = '0';
// str and str2 are now both zeroed

const_cast, const, undefined.

Qt docs :

. , , . , , ; . .

, , :

STL: , . , , . :.

QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.

QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
    Now we should be careful with iterator i since it will point to shared data
    If we do *i = 4 then we would change the shared instance (both vectors)
    The behavior differs from STL containers. Avoid doing such things in Qt.
*/

a[0] = 5;
/*
    Container a is now detached from the shared data,
    and even though i was an iterator from the container a, it now works as an iterator in b.
*/

, " " , , copy-on-write. , "" begin() end() , :

QString str = "password";
QString::iterator itr = str.begin();
QString::iterator nd = str.end();
QString str2 = str;

while (itr != nd)
{
    *itr = '0';
    ++itr;
} // str and str2 still point to the same data and are both zeroed
+2

, . , . , QString, .

, , std::basic_string , (. ). char, . , std::basic_string QChar, Unicode ++ 11 (char16_t, char32_t...) , ANSI.

, , , keyPressEvent/keyReleaseEvent, , char. paintEvent, , , . , .


:

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) {}
  };
}
+1

Source: https://habr.com/ru/post/1680750/


All Articles