2017-12-01 8 views
0

ユーザーから収集する必要がある機密情報の文字列があります。私はこの情報を要求するためにWPF PasswordBoxを使用しています。初期化されていない場合、PasswordBoxコントロールは、オブジェクトではなくSecureStringオブジェクトであるSecurePasswordプロパティを提供します。私のアプリケーション内では、PasswordBoxのデータはSecureStringとして暗号化メソッドに渡されます。SecureStringからバイナリデータを正しく出力すると、後で文字列に変換できますか?

私ができる必要があるのは、最初に.Net stringにデータを変換せずに.Net stringの値を表すバイト配列にデータをマーシャルすることです。 !具体的には、

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`〜@の#$%...のような値を持つSecureString与え^ & *()_- + = {[}] | :;」」<、>。 ?/ ≈篭母

...私はStreamWriter

によってで連載され、ストリームに書き込まれての.NET文字列は同等であるバイト配列に変換する方法Marshal.SecureStringToCoTaskMemUnicode(...)を使用してより伝統的な西洋の文章でこれを行う。しかし、上記のテキスト文字列を追加した典型的でない文字と日本語の文字列を使って作成した場合(最後の太字の文字を参照)、IntPtrに割り当てられたUnicodeバイト配列を取得する方法が正しく動作しないようですもう

SecureStringのデータを安全に返して、返されたバイトデータが標準の.Net文字列のバイトデータと同じ構造になるようにするにはどうすればよいですか?

NOTE

現時点では、すべてのセキュリティ上の懸念を無視してください。私は自分のアプリケーションへのさまざまなセキュリティのアップグレードを行っています。今のところ、私はSecureStringを使用して機密データを暗号化装置に渡す必要があります。デクリプタ(今のところ)は、このデータをstringの値に復号化する必要があります。なぜなら、SecureStringのデータを、stringオブジェクトのバイナリ形式に似たシリアル化する必要があるからです。

私はこのアプローチが少し残念であることに同意しますが、私は既存のアプリケーションを段階的に改善する必要があります。最初の段階では、SecureStringオブジェクトのデータをユーザーから暗号化装置にロックしています。あなたはストリーミングするセキュリティで保護された文字列を記述する必要がある場合は

+0

https://codereview.stackexchange.com/a/107864/5297? – stuartd

+0

これは少し疑わしいと思うが、なぜ特定のものをロックしている場合にパスワード情報が必要なのか、ネットワーク共有、フォルダ、データベースなどのようなものへの不正アクセスを防ぐための方法やアプローチがある。あなたは本当にロックダウンしようとしているものを説明します..? – MethodMan

+0

@MethodMan私のメモを参照してください。私たちのアプリケーションは機密情報を収集し、それを安全な鍵で暗号化し、暗号化されたデータを配布し、別のロケールで解読する必要があります。最終的には、2番目のポイントのコードを更新してデータを復号化し、詳細をSecureStringsに保存します。しかし、私が述べたように、私はこれを複数段階のプロセスで行う必要があります。今のところ、暗号化を担当するアプリケーションは、解読された詳細を.Net文字列に簡単に再変換できるような方法でデータを送信する必要があります。 – RLH

答えて

1

、私はこのようなメソッドを作成することをお勧めしたい:あなたは本当にバイト配列が必要な場合は

public static class Extensions { 
    public static void WriteSecure(this StreamWriter writer, SecureString sec) { 
     int length = sec.Length; 
     if (length == 0) 
      return; 
     IntPtr ptr = Marshal.SecureStringToBSTR(sec); 
     try { 
      // each char in that string is 2 bytes, not one (it's UTF-16 string) 
      for (int i = 0; i < length * 2; i += 2) { 
       // so use ReadInt16 and convert resulting "short" to char 
       var ch = Convert.ToChar(Marshal.ReadInt16(ptr + i)); 
       // write 
       writer.Write(ch); 
      } 
     } 
     finally { 
      // don't forget to zero memory 
      Marshal.ZeroFreeBSTR(ptr); 
     } 
    } 
} 

は - あなたも、このメソッドを再利用することができます

byte[] result; 
using (var ms = new MemoryStream()) { 
    using (var writer = new StreamWriter(ms)) { 
     writer.WriteSecure(secureString); 
    } 
    result = ms.ToArray(); 
} 

最初のコメントからの方法は少し面白いかもしれませんが(それが重要かどうかはわかりません)。

関連する問題