文字列をSecureStringに変換


回答:


137

あなたはしません。SecureStringオブジェクトを使用する理由は、文字列オブジェクト(メモリに読み込まれ、ガベージコレクションまでプレーンテキストで保持される)を作成しないようにするためです。ただし、文字を追加することで、SecureStringに文字を追加できます。

var s = new SecureString();
s.AppendChar('d');
s.AppendChar('u');
s.AppendChar('m');
s.AppendChar('b');
s.AppendChar('p');
s.AppendChar('a');
s.AppendChar('s');
s.AppendChar('s');
s.AppendChar('w');
s.AppendChar('d');

13
「組み合わせは12345……それは馬鹿が彼の荷物に持っているようなものです!」
Kolobキャニオン2017

8
私が見るのは*****
Ian Boyd

AppendChar実行時まで実行されないため、これらの文字はILから読み取ることができますか?おそらく、コンパイル時の難読化も役立つでしょう...つまり、パスワードをハードコーディングしている場合です。
samis

5
それは不十分な議論です。どこでパスワードを取得しますか?フォームまたはコマンドラインから。安全な文字列をデバイスまたはコマンドライン引数から直接読み取るメソッドを作成するまで、文字列をSecureStringに変換する必要があります。
クォークリー

1
@DonaldAireyはシークレットマネージャーからパスワードを取得します。通常、ここで取り上げる秘密はユーザーパスワードではなく、特権の昇格やデータ漏洩につながる可能性のあるものです。つまり、パスワードは他のサービスのためのものであり、コマンドラインやネットワークチャネルを介して平文で渡すことはできません。
バリーケリー

159

SecureStringとを変換する別の方法もありStringます。

1. StringからSecureString

SecureString theSecureString = new NetworkCredential("", "myPass").SecurePassword;

2. SecureStringからStringへ

string theString = new NetworkCredential("", theSecureString).Password;

こちらがリンクです


3
これは、最も一般的なユースケースにとって、断然最高のソリューションです。
Dan Bechard 2017

16
SecureStringコードでstring保護する値を持つオブジェクトを作成する場合は、a を使用しても意味がありません。の目的はSecureString、マネージメモリに文字列が含まれないようにすることです。そのため、そのメモリを調査する攻撃者は、非表示にする値を見つけることができます。以来NetworkCredential、あなたが呼び出しているコンストラクタが...確かに行く方法はありません文字列を、必要とし、あなたのコードは、にし、SecureStringから変換する簡単な方法はあるが、それを使用すると、単純なを使用して安全なようにコードを作るstring
ジャンパオロ

14
@GianPaoloは理論的には正しいのですが、実際にはSecureString、一部のライブラリを操作するときにも引き続き使用する必要があります。ここで正直に言いましょう。誰かがアプリケーションのメモリをアクティブにスキャンしている場合は、すでに失っています。SecureStringを正しく使用したとしても(私がこれまでに見たことがない)、他に抽出する価値のあるデータがあるでしょう。
ジョナサンアレン

1
@JonathanAllen:あなたはおそらく正しいですが、私たちにはセキュリティを後付けとして扱う文化があるからです。レシピのウェブサイトを作成している場合、北朝鮮はプログラムのメモリをスキャンしようとはしません。銀行のソフトウェアを作成している場合、脅威はより現実的です。
エリックJ.

58

以下のメソッドは、文字列を安全な文字列に変換するのに役立ちます

private SecureString ConvertToSecureString(string password)
{
    if (password == null)
        throw new ArgumentNullException("password");

    var securePassword = new SecureString();

    foreach (char c in password)
        securePassword.AppendChar(c);

    securePassword.MakeReadOnly();
    return securePassword;
}

26
+1ですが、パスワードを文字列パラメータとして渡すと、マネージメモリに暗号化されていない文字列インスタンスが作成され、そもそも「SecureString」の目的が無効になることに注意してください。来てこのコードを使用する将来の人々のためにこれを指摘するだけです。
コーディ

19
@Codyこれは事実であり、良い点ですが、SecureStringが安全かどうかを気にせず、一部のMicrosoft APIがパラメーターとしてそれを必要とするため、SecureStringを使用しているだけです。
Dan Bechard 2017

3
@Codyは、SecureStringクラスでさえ文字列の暗号化を維持できないことを示しています。MSがgithub.com/dotnet/platform-compat/blob/master/docs/DE0001.mdタイプの廃止を検討しているのはこのためです
Martin Brown、

19

あなたはこれに従うことができます:

string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();

11

これは安価なlinqトリックです。

            SecureString sec = new SecureString();
            string pwd = "abc123"; /* Not Secure! */
            pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
            /* and now : seal the deal */
            sec.MakeReadOnly();

32
この答えは、プレーンテキストの一時的なコピーはワンショットで生成することができますどのように多くの練習を見ているされて
マイク・キャロン

1
@ john-daggが提案したように、パスワードを使用して文字列を設定しないことをお勧めします。これを行うと、securestringを使用する利点がなくなるためです。パスワードをプレーンテキストで入力した場合、後でsecurestringを使用しても何も保護されません。securestringは、逆アセンブリやデバッガーを見ている人から文字列を保護するためのものであることをご理解いただければ幸いです。IL/メモリの内容を確認してください。
user734028

8

これを捨てます。どうして?

すべての文字列を安全な文字列に変更するだけで、突然アプリケーションが「安全」になります。安全な文字列は、文字列を可能な限り暗号化し、操作が実行された後にメモリを消去する非常に短い期間のみ復号化するように設計されています。

アプリケーションの文字列を保護することを心配する前に、設計レベルの問題に対処する必要があるかもしれません。あなたがやろうとしていることについて、もう少し情報を提供してください。


1
それを使用してProcessStartInfoのパスワードを設定し、別のユーザーとしてexeを実行したいだけです。それでうまくいきました...
Developer404

4
私のアプリケーションは、安全なシステムで実行することによって保護されています。この特定の文字列がメモリ内で暗号化されるのを気にすることはできませんでした。このシステムには、侵害された場合に心配する必要のあるはるかに重要な情報があります。SecureStringは、私のプログラムが利用する必要のあるMicrosoft APIによって単純に要求されます。開発者が自分のユースケースを検討し、文字列をSecureStringsに変換することがコンテキスト内で有効な操作であるかどうかを判断することを意味します。
Dan Bechard 2017

したがって、このメソッドは、誰かがDotPeekのような逆コンパイラを使用している場合、誰かがパスワードを見るのを妨げませんか?この場合、文字列を非表示にする方法はありますか?
M.Parent

あなたが倒そうとしている脅威に応じて、いくつかの方法があります。ユーザー情報をローカル管理者以外から保護する場合は、WindowsのDPAPIメソッドを使用してファイルを暗号化し、そこにシークレットを保存して、安全な文字列に読み取ってから破棄できます。それが会社の秘密である場合、簡単な答えは、アプリケーションがそれを解読できるかどうかであり、最終的にユーザーも解読できるかどうかです。
Spence

6
unsafe 
{
    fixed(char* psz = password)
        return new SecureString(psz, password.Length);
}

5

派手なlinqはなく、手作業ですべての文字を追加するのではなく、単純明快です

var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);

さらに洗練されていて、変数を定義する必要はありません
bigworld12

ここにワンライナーがあります:var sc = new SecureString(); foreach(char c in "foo") sc.appendChar(c);
bigworld12

4

Spence(+1)に同意しますが、目的を学習またはテストするために行う場合は、文字列でforeachを使用し、AppendCharメソッドを使用して、各文字をsecurestringに追加できます。


3

私は「それはポイントではない、と言って、すべての人に指摘したいSecureStringこの質問をして、人々の多くは正当かどうか、何らかの理由のために、それらがされ、アプリケーションであるかもしれないことを、」ない特に持っていることについて懸念しますパスワードの一時的なコピーはGC対応の文字列としてヒープ上に置かれのみを受け入れるAPIを使用するSecureStringオブジェクト。だから、あなたは気にしないアプリを持っていますパスワードがヒープ上にあるかどうか、おそらく内部使用のみで、パスワードはそこにのみ存在します。これは、基礎となるネットワークプロトコルによって必要とされるためです。パスワードが格納されているその文字列は、たとえばリモートPowerShellのセットアップに使用できないランスペース-しかし、を作成するための簡単でわかりやすいワンライナーSecureStringあなたが必要とすること。これはマイナーな不便さですが、本当に必要なアプリケーションが作成者や仲介者を使用するように誘惑しないことを保証するためにおそらく価値ありSecureStringます。:-)System.StringSystem.Char[]


2

a stringからa SecureStringへの変換をLINQステートメントに圧縮したい場合は、次のように表現できます。

var plain  = "The quick brown fox jumps over the lazy dog";
var secure = plain
             .ToCharArray()
             .Aggregate( new SecureString()
                       , (s, c) => { s.AppendChar(c); return s; }
                       , (s)    => { s.MakeReadOnly(); return s; }
                       );

ただし、を使用LINQしてもこのソリューションのセキュリティは向上しないことに注意してください。からstringへの変換と同じ問題が発生しSecureStringます。オリジナルstringがメモリに残っている限り、データは脆弱です。

SecureStringとはいえ、上記のステートメントが提供できるのは、の作成とデータによる初期化をまとめ、最後に変更からロックすることです。


2

次の2つの拡張機能でうまくいくはずです。

  1. 以下のためのchar配列

    public static SecureString ToSecureString(this char[] _self)
    {
        SecureString knox = new SecureString();
        foreach (char c in _self)
        {
            knox.AppendChar(c);
        }
        return knox;
    }
  2. そして string

    public static SecureString ToSecureString(this string _self)
    {
        SecureString knox = new SecureString();
        char[] chars = _self.ToCharArray();
        foreach (char c in chars)
        {
            knox.AppendChar(c);
        }
        return knox;
    }

おかげジョンDaggのためAppendCharの勧告。


0

あなたはこの簡単なスクリプトを使うことができます

private SecureString SecureStringConverter(string pass)
{
    SecureString ret = new SecureString();

    foreach (char chr in pass.ToCharArray())
        ret.AppendChar(chr);

    return ret;
}

1
この回答は15か月前に投稿されました。もう一度投稿する必要は本当にありませんでした。
GSerg 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.