2010-03-10 12 views
40

Czy można to uprościć do jednej linijki? Zachęcamy do całkowitego przepisania go pod warunkiem, że secureString zostanie poprawnie zainicjowany.Używanie SecureString

SecureString secureString = new SecureString(); 
foreach (char c in "fizzbuzz".ToCharArray()) 
{ 
    secureString.AppendChar (c); 
} 
+1

Zobacz także: http://stackoverflow.com/questions/1800695/c-securestring-question –

+1

Nie zapomnij, aby Państwa 'SecureString' tylko do odczytu. – Greg

Odpowiedz

38

Można używać LINQ:

"fizzbuzz".ToCharArray().ToList().ForEach (p => secureString.AppendChar (p)); 
+1

+1 Właściwie to jest to to samo, co @Tod, ale z mniejszą liczbą linii. – Javier

+0

Myślę, że mogę rzucić to w metodę rozszerzenia, aby uzyskać to, co jestem po: processInfo.Password = new SecureSring() .FromString ("fizzbuzz") –

+25

Możesz uniknąć dodatkowej operacji .ToList() z następującymi: 'Array.ForEach (" fizzbuzz ".ToCharArray(), secureString.AppendChar);' –

25

Oprócz użyciu niebezpieczny kod i char*, nie jest (bardzo) lepszy sposób.

Nie chodzi tutaj o kopiowanie zawartości SecureString do/z normalnych ciągów znaków. Stała "fizzbuzz" jest tutaj wyciekiem bezpieczeństwa.

+0

Pokonaj mnie - +1. Dodatkowo dodatkowe zmiany, które należy wprowadzić, aby pozwolić na niebezpieczny kod, negują "oszczędności" na liniach kodu. –

+1

Czy większość haseł nie pochodzi z większości programów jako ciągów, a następnie trzeba je przekonwertować na SecureString? Nie wiesz, co masz na myśli, mówiąc "nie kopiować zawartości SecureString z normalnego łańcucha znaków". W normalnych warunkach będzie to hasło ciągowe. "fizzbuzz" to tylko hołd. –

+0

Tak, a to znacznie zmniejsza użyteczność SecureString. –

13
var s = "fizzbuzz".Aggregate(new SecureString(), (ss, c) => { ss.AppendChar(c); return ss; }); 
+0

To jest bardzo eleganckie. –

16

niewielka poprawa na odpowiedź Sascha za wymianą lambda z grupą metodą

"fizzbuzz".ToCharArray().ToList().ForEach(ss.AppendChar); 
38

Wystarczy użyć NetworkCredential. Ma wbudowaną logikę konwersji.

SecureString ss = new NetworkCredential("", "fizzbuzz").SecurePassword; 

Jak zauważyli inni, wszystkie te techniki taśmy korzyści bezpieczeństwa SecureString, ale w pewnych sytuacjach (na przykład w testach z jednostek), może to być akceptowalne.

Aktualizacja:

Jak zauważył w komentarzach, NetworkCredential może być również używany do konwersji SecureString powrotem na sznurku.

string s = new NetworkCredential("", ss).Password; 
+2

i nie jest dostępny wcześniej .Net 4.0 –

+2

Elegancki! I działa nawet w obu kierunkach. –

+0

@JohannesOvermann, co masz na myśli mówiąc * w obu kierunkach *? (O ile widzę, 'NetworkCredential' zużywa hasło w postaci zwykłego tekstu lub hasło' SecureString', ale tylko ujawnia hasło w postaci zwykłego tekstu w pierwszym przypadku.) – CodeFox

8

Oto jak NetworkCredential klasy z .NET robi:

SecureString secureString; 
fixed (char* chPtr = plainString) 
    secureString = new SecureString(chPtr, plainString.Length); 

brzydki ale prawdopodobnie najbardziej skuteczny.

+7

Należy zauważyć, że użycie 'fixed' wymaga' niebezpiecznego' bloku, który z kolei wymaga przełącznika kompilatora '/ unsafe'. – DonBoitnott

3

Od SecureString wykorzystuje interfejs IDispose. Możesz to zrobić w ten sposób.

SecureString secure = new SecureString(); 
foreach(var character in data.ToCharArray()) 
    secure.AppendChar(character); 

Zasadniczo parametr data.

Jeśli korzystasz z using, aby pomóc w złagodzeniu zasobów; będziesz uważać na zakres. Ale może to być korzystna alternatywa, w zależności od zastosowania.

Aktualizacja:

Można rzeczywiście zrobić metodą pełną Podpis:

public static SecureString ConvertStringToSecureString(this string data) 
{ 
    var secure = new SecureString() 
    foreach(var character in data.ToCharArray()) 
     secure.AppendChar(character); 

    secure.MakeReadOnly(); 
    return secure; 

} 

dla deszyfrowania, co chcesz zrobić:

public static string ConvertSecureStringToString(this SecureString data) 
{ 
    var pointer = IntPtr.Zero; 
    try 
    { 
      pointer = Marshal.SecureStringToGlobalAllocUnicode(data); 
      return Marshal.PtrToStringUni(pointer); 
    } 
    finally 
    { 
      Marshal.ZeroFreeGlobalAllocUnicode(pointer); 
    } 
} 

Poniższy article daje niektóre dodatkowe informacje.

0

najmniej ilość kodu, ponieważ .ToList() nie jest wymagany do tego:

Array.ForEach("fizzbuzz".ToCharArray(), secureString.AppendChar);