Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how does one securely clear std::string?

Tags:

How does one store sensitive data (ex: passwords) in std::string?

I have an application which prompts the user for a password and passes it to a downstream server during connection setup. I want to securely clear the password value after the connection has been established.

If I store the password as a char * array, I can use APIs like SecureZeroMemory to get rid of the sensitive data from the process memory. However, I want to avoid char arrays in my code and am looking for something similar for std::string?

like image 530
ajd. Avatar asked Apr 18 '11 02:04

ajd.


People also ask

What does std::string () do?

std::string class in C++ C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.

What is the difference between std::string and string?

std::string is the string class from the standard C++ library. String is some other string class from some other library. It's hard to say from which library, because there are many different libraries that have their own class called String.

What is std::string data?

std::string::dataReturns a pointer to an array that contains the same sequence of characters as the characters that make up the value of the string object.

Why do I need std::string?

Because the declaration of class string is in the namespace std. Thus you either need to always access it via std::string (then you don't need to have using) or do it as you did.


2 Answers

Based on the answer given here, I wrote an allocator to securely zero memory.

#include <string> #include <windows.h>  namespace secure {   template <class T> class allocator : public std::allocator<T>   {   public:      template<class U> struct rebind { typedef allocator<U> other; };     allocator() throw() {}     allocator(const allocator &) throw() {}     template <class U> allocator(const allocator<U>&) throw() {}      void deallocate(pointer p, size_type num)     {       SecureZeroMemory((void *)p, num);       std::allocator<T>::deallocate(p, num);     }   };    typedef std::basic_string<char, std::char_traits<char>, allocator<char> > string; }  int main() {   {     secure::string bar("bar");     secure::string longbar("baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar");   } } 

However, it turns out, depending on how std::string is implemented, it is possible that the allocator isn't even invoked for small values. In my code, for example, the deallocate doesn't even get called for the string bar (on Visual Studio).

The answer, then, is that we cannot use std::string to store sensitive data. Of course, we have the option to write a new class that handles the use case, but I was specifically interested in using std::string as defined.

Thanks everyone for your help!

like image 92
ajd. Avatar answered Oct 04 '22 19:10

ajd.


openssl went through a couple of iterations of securely erasing a string until it settled on this approach:

#include <string.h> #include <string>  // Pointer to memset is volatile so that compiler must de-reference // the pointer and can't assume that it points to any function in // particular (such as memset, which it then might further "optimize") typedef void* (*memset_t)(void*, int, size_t);  static volatile memset_t memset_func = memset;  void cleanse(void* ptr, size_t len) {   memset_func(ptr, 0, len); }  int main() {   std::string secret_str = "secret";   secret_str.resize(secret_str.capacity(), 0);   cleanse(&secret_str[0], secret_str.size());   secret_str.clear();    return 0; } 
like image 22
ericcurtin Avatar answered Oct 04 '22 17:10

ericcurtin