に変換する方法String
はSecureString
?
14 に答える
との間で変換する別の方法もありSecureString
ますString
。
1.文字列からSecureString
SecureString theSecureString = new NetworkCredential("", "myPass").SecurePassword;
2.SecureStringからStringへ
string theString = new NetworkCredential("", theSecureString).Password;
ここにリンクがあります
あなたはそうしない。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');
以下のメソッドは、文字列を安全な文字列に変換するのに役立ちます
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;
}
あなたはこれに従うことができます:
string password = "test";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();
これが安価なlinqトリックです。
SecureString sec = new SecureString();
string pwd = "abc123"; /* Not Secure! */
pwd.ToCharArray().ToList().ForEach(sec.AppendChar);
/* and now : seal the deal */
sec.MakeReadOnly();
これを捨てます。なんで?
すべての文字列を安全な文字列に変更することはできず、突然アプリケーションが「安全」になります。安全な文字列は、文字列を可能な限り暗号化して保持するように設計されており、非常に短い期間だけ復号化され、操作が実行された後にメモリを消去します。
アプリケーション文字列の保護について心配する前に、設計レベルの問題に対処する必要があるかもしれないと言って危険です。あなたがやろうとしていることについてもう少し情報を教えてください。そうすれば、私たちはより良い手助けをすることができるかもしれません。
unsafe
{
fixed(char* psz = password)
return new SecureString(psz, password.Length);
}
「それはポイントではありません」と言っているすべての人に指摘したいのですが、SecureString
この質問をする人の多くは、正当な理由があるかどうかにかかわらず、特に心配していないアプリケーションにいる可能性がありますパスワードの一時的なコピーはGC可能な文字列としてヒープに配置されますが、オブジェクトのみを受け入れるAPIを使用する必要がありSecureString
ます。だから、あなたはあなたが気にしないアプリを持っていますパスワードがヒープ上にあるかどうか、おそらく内部使用のみであり、パスワードは基盤となるネットワークプロトコルで必要とされるためにのみ存在し、パスワードが格納されている文字列を使用してリモートPowerShellを設定することはできません。ランスペース-しかし、SecureString
必要なものを作成するための簡単でわかりやすいワンライナーはありません。これは小さな不便ですが、実際に必要なアプリケーションが作成者に使用や仲介を誘惑しないようにするためには、おそらく価値がありSecureString
ます。:-)System.String
System.Char[]
派手なlinqはなく、すべての文字を手作業で追加するのではなく、単純で単純です。
var str = "foo";
var sc = new SecureString();
foreach(char c in str) sc.appendChar(c);
Spence(+1)に同意しますが、目的の学習またはテストのためにそれを行う場合は、文字列でforeachを使用し、AppendCharメソッドを使用して各文字をsecurestringに追加できます。
次の2つの拡張機能でうまくいくはずです。
char
アレイの場合public static SecureString ToSecureString(this char[] _self) { SecureString knox = new SecureString(); foreach (char c in _self) { knox.AppendChar(c); } return knox; }
そしてのために
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; }
推薦してくれたジョン・ダッグに感謝しAppendChar
ます。
string
aからaSecureString
への変換をステートメントに圧縮する場合は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
データによる初期化、そして最終的には変更からのロックです。
完全を期すために、char配列と文字列からSecureStringに変換し、また元に戻すための2つの単体テストとメソッドを追加しました。文字列は完全に避けて、ここで提供する方法のように、char配列へのポインタまたはchar配列自体のいずれかのみを渡すようにしてください。文字列は、管理されたメモリにプレーンテキストのデータを保持するため、かなり不確定な量であるため安全ではありません。次のGCが実行または強制されるまでの時間は、できるだけ早く文字配列をSecureStringに入れてそこに保持し、文字配列として再度読み取ることをお勧めします。
テストは次のようになります。
using NUnit.Framework;
using System;
using SecureStringExtensions;
using System.Security;
namespace SecureStringExtensions.Test
{
[TestFixture]
public class SecureStringExtensionsTest
{
[Test]
[TestCase(new char[] { 'G', 'O', 'A', 'T', '1', '2', '3' })]
public void CopyCharArrayToSecureStringAndCopyBackToCharArrayReturnsExpected(char[] inputChars)
{
SecureString sec = inputChars.ToSecureString();
var copiedFromSec = sec.FromSecureStringToCharArray();
CollectionAssert.AreEqual(copiedFromSec, inputChars);
}
[Test]
[TestCase("GOAT456")]
public void CopyStringToSecureStringAndCopyBackToUnsafeStringReturnsExpected(string inputString)
{
SecureString sec = inputString.ToSecureString();
var copiedFromSec = sec.FromSecureStringToUnsafeString();
Assert.AreEqual(copiedFromSec, inputString);
}
}
}
そして、ここに拡張メソッドがあります:
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace SecureStringExtensions
{
public static class SecureStringExtensions
{
public static SecureString ToSecureString(this string str)
{
return ToSecureString(str.ToCharArray());
}
public static SecureString ToSecureString(this char[] str)
{
var secureString = new SecureString();
Array.ForEach(str, secureString.AppendChar);
return secureString;
}
/// <summary>
/// Creates a managed character array from the secure string using methods in System.Runetime.InteropServices
/// copying data into a BSTR (unmanaged binary string) and then into a managed character array which is returned from this method.
/// Data in the unmanaged memory temporarily used are freed up before the method returns.
/// </summary>
/// <param name="secureString"></param>
/// <returns></returns>
public static char[] FromSecureStringToCharArray(this SecureString secureString)
{
char[] bytes;
var ptr = IntPtr.Zero;
try
{
//alloc unmanaged binary string (BSTR) and copy contents of SecureString into this BSTR
ptr = Marshal.SecureStringToBSTR(secureString);
bytes = new char[secureString.Length];
//copy to managed memory char array from unmanaged memory
Marshal.Copy(ptr, bytes, 0, secureString.Length);
}
finally
{
if (ptr != IntPtr.Zero)
{
//free unmanaged memory
Marshal.ZeroFreeBSTR(ptr);
}
}
return bytes;
}
/// <summary>
/// Returns an unsafe string in managed memory from SecureString.
/// The use of this method is not recommended - use instead the <see cref="FromSecureStringToCharArray(SecureString)"/> method
/// as that method has not got multiple copies of data in managed memory like this method.
/// Data in unmanaged memory temporarily used are freed up before the method returns.
/// </summary>
/// <param name="secureString"></param>
/// <returns></returns>
public static string FromSecureStringToUnsafeString(this SecureString secureString)
{
if (secureString == null)
{
throw new ArgumentNullException(nameof(secureString));
}
var unmanagedString = IntPtr.Zero;
try
{
//copy secure string into unmanaged memory
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secureString);
//alloc managed string and copy contents of unmanaged string data into it
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
if (unmanagedString != IntPtr.Zero)
{
Marshal.FreeBSTR(unmanagedString);
}
}
}
}
}
ここでは、System.Runtime.InteropServicesのメソッドを使用して、BSTR(バイナリアンマネージ文字列)を一時的に割り当て、一時的に使用されているアンマネージメモリを解放します。
この簡単なスクリプトを使用できます
private SecureString SecureStringConverter(string pass)
{
SecureString ret = new SecureString();
foreach (char chr in pass.ToCharArray())
ret.AppendChar(chr);
return ret;
}