23

機密データ (パスワードなど) を にどのように保存しstd::stringますか?

ユーザーにパスワードの入力を求め、接続のセットアップ中にそれをダウンストリーム サーバーに渡すアプリケーションがあります。接続が確立された後、パスワードの値を安全にクリアしたい。

パスワードをchar *配列として保存すると、 SecureZeroMemoryなどの API を使用してプロセス メモリから機密データを削除できます。ただし、コード内の char 配列を避けたいので、同様のものを探していstd::stringますか?

4

6 に答える 6

14

hereの回答に基づいて、メモリを確実にゼロにするアロケータを作成しました。

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

ただし、 のstd::string実装方法によっては、アロケータが小さな値に対してさえ呼び出されない可能性があります。たとえば、私のコードでは、(Visual Studio で)deallocate文字列に対して呼び出されることさえありません。bar

答えは、機密データを保存するために std::string を使用できないということです。もちろん、ユース ケースを処理する新しいクラスを作成するオプションもありますが、std::string定義どおりに使用することに特に関心がありました。

助けてくれてありがとう!

于 2011-04-20T19:43:29.573 に答える
4

後世のために、私はかつてこのアドバイスを無視してとにかく std::string を使用することに決め、c_str() (および const をキャストする) と volatile を使用して zero() メソッドを作成しました。注意してコンテンツの再割り当て/移動を行わず、必要な場所で手動で zero() を呼び出した場合、すべてが適切に機能しているように見えました。悲しいかな、別の重大な欠陥を難しい方法で発見しました: std::string は参照カウントされたオブジェクトになることもあります... c_str() でメモリ (または参照されたオブジェクトが指しているメモリ) を爆破すると、他のオブジェクトを無意識のうちに爆破します.

于 2012-10-03T12:22:51.630 に答える
-1

std::string は char* に基づいています。char* としてのすべての動的マジックの背後のどこかに。したがって、コードで char* を使用したくない場合でも、まだ char* を使用しています。これは、バックグラウンドで他のゴミが山積みになっているだけです。

私はプロセスメモリの経験があまりありませんが、いつでも各文字を反復処理して (パスワードを暗号化して DB に保存した後ですか?)、別の値に設定できます。

std::basic_string もありますが、それがどのような助けになるかはわかりません。

于 2011-04-18T03:03:29.157 に答える
-2
std::string mystring;
...
std::fill(mystring.begin(), mystring.end(), 0);

または、独自の関数を作成することもできます。

void clear(std::string &v)
{
  std::fill(v.begin(), v.end(), 0);
}
于 2011-04-18T08:43:44.993 に答える