2010-02-15 4 views
27

Ich frage mich, wie ich ein starkes und sicheres Passwort in C# generieren kann.Erzeugt ein starkes Passwort in C#?

ich ein wenig gegoogelt und sah diese Formel in Wikipedia, wo L die Länge des Passworts und N ist die Anzahl der möglichen Symbole:

alt text

Auch ich habe this question gefunden, aber aus irgendeinem Grund die Methode Membership.GeneratePassword gibt nur eine Zufallszahl mit 1 Ziffer zurück, die absolut kein Passwort. Alle übrigen Lösungen waren sehr langsam (> = 0,5 Sekunden).

Ich brauche Hilfe bei der Umsetzung dieser Formel (ich weiß nicht, wo ich anfangen soll). Sie können auch eine andere Lösung vorschlagen oder erklären, warum die GeneratePassword nicht funktioniert.

Antwort

73

Ich habe gerade versucht, die folgende in LINQPad:

System.Web.Security.Membership.GeneratePassword(25, 10) 

Dies ist das Passwort Ich habe:

[XTJ_67g.i/ag1rL)6_Yv>*+%

Oder, wenn das reicht nicht sicher, versuchen Sie dies:

System.Web.Security.Membership.GeneratePassword(128, 100) 

was mir beim dreimaligen Ausführen folgendes brachte:

|c^.:?m)#q+(]V;}[Z(})/?-;$][email protected]!|^/8*_9.$&.&!(?=^!Wx?[@%[email protected];)>N;&+*w[>$2+_$%l;+h+#zhs^{e?&=*(}X_%|:}]]}*X[+)Er%J/-=;Q0{:+=%c7:^$ 

/:_)hxF+*){2|;(>:*N^+!_&|}B.$})?[V=[+v({-:[email protected]$j?.[-}(@MHx+}(}Mz_S(7#4}{..>@G|!+++{+C=|_}=+r^@&$0;L*|kz-;$++/N3$=}?;%&]]*/^#^!+ 

:*{]-x^$g{|?*))[email protected]^.#%L;g|+)#[nq}?y(_(m;]S^I$*q=l-[_/?}&-!k^(+[_{Z|&:^%!_)!=p%=)=wYd-#.UP$%s1{*l%+[%[email protected]=.;{+M)!^}&d/]{];(&}

dies dauerte weniger als eine Sekunde, übrigens. Der Rahmen ist dein Freund.

Siehe http://msdn.microsoft.com/en-us/library/system.web.security.membership.generatepassword.aspx

+0

Bitte beachten Sie, dass der Editor nicht mit einigen Zeichen im Passwort freundlich spielt. – Will

+0

Wie gesagt, das ist eine großartige Methode, aber gibt nur eine Ziffer in meinem Computer und in vielen anderen Computern zurück. –

+4

@alon du machst es falsch. Vertrau mir. Diese Methode funktioniert und ist kugelsicher bei jeder .NET-Installation auf jedem Computer. – Will

1

Warum füllen Sie nicht einfach ein Array mit einigen Zeichen und wählen Sie zufällig eine Reihe von ihnen. Sie können sie in Gruppen einteilen, um sicherzustellen, dass Buchstaben und Sonderzeichen enthalten sind.

Sie müssen auch eine angemessene Länge und wie viel von jeder Gruppe von Zeichen enthalten und das ist es. Ich glaube nicht, dass Sie raffinierte Formeln brauchen.

+0

Ich glaube nicht, dass es für Brute-Force-Angriffe sicher genug ist und etc ... –

+1

Nichts ist ... Aber wenn Sie Ihre Anmeldungen bis 5 begrenzen Logins pro Stunde sagen, Sie reduzieren das Risiko des Brute-Force-Angriffs. – LiamB

+2

Was könnte schwieriger sein als zufällige Buchstaben zu wählen? – anthares

1

Für Systeme, die es sehr einfach, wirklich nutzergenerierte Passwörter nicht zulassen: Jedes Passwort, so sicher ist, wie es lang ist. Natürlich nicht mit Leuten, die Post-its an Monitore usw. anheften.

Sie möchten wahrscheinlich die Zeichenmenge maximieren, aus der das Passwort generiert wird. Durch das Einschränken der generierten Passwörter wird jedoch der Suchraum stark eingeschränkt und das Passwort weniger gesichert (). Dies gilt auch dann, wenn der Benutzer kein eigenes Passwort wählen kann.

Wenn Sie sowohl mit generierten als auch mit vom Benutzer erstellten Passwörtern umgehen, sind natürlich alle Wetten deaktiviert. Wahrscheinlich möchten Sie dann die Kennwörter so generieren, dass möglichst viele Zeichen aus verschiedenen Klassen verwendet werden, die einem starken, vom Benutzer gewählten Kennwort ähneln. Im Idealfall sollte es denselben Einschränkungen entsprechen, die auch das vom Benutzer erstellte Passwort erfüllen muss (falls vorhanden).

2

Wie wäre es Guid.NewGuid().ToString();?

+4

Entschuldigung, dieses kommt zurück 00000000-0000-0000-0000-000000000000 die ganze Zeit. Aber das wird funktionieren: Guid.NewGuid(). ToString() – Steven

+0

@Steven - Bearbeitet nach Vorschlag – Nifle

+0

er ... yeah ... das ist, was ich meinte .... oO – dkackman

9

Um Ihre Frage zu dieser Formel Adresse:

Die Formel sagt, dass ein Passwort der Länge L aus einem Alphabet von N Symbolen gezeichnet ein Passwort mit einer Länge von H aus einem Alphabet von zwei Symbolen gezeichnet entspricht . Wenn Sie zum Beispiel 64 Symbole haben (sagen wir abc ... xyzABC ... XYZ01 ... 89_!) Und das Passwort 10 Zeichen lang ist, dann gibt Ihnen das die gleiche Sicherheit wie ein Passwort 10 log2 64 = 60 Zeichen lang aus dem Alphabet "ab" gezogen.

Ein "log" ist der umgekehrte Vorgang der Potenzierung. Zwei bis sechste Kraft gibt dir vierundsechzig, daher gibt dir das "Zwei-Siegel" von vierundsechzig sechs.

1

ich würde Guid mich :) und machen den Benutzer bearbeiten das Passwort nach der Anmeldung

6

Ich weiß nicht, ob dies wird Ihnen helfen, aber das ist, was ich benutze, wenn ich eine zufällige generieren möchten Passwort, das auch stark ist. Es ist schnell und einfach zu implementieren/verstehen und ist nicht so viel von einem übertrieben wie die durch den Mitgliedschaftsanbieter oben ...

private string Token(byte Length) { 
     char[] Chars = new char[] { 
      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 
     }; 
     string String = string.Empty; 
     Random Random = new Random(); 

     for (byte a = 0; a < Length; a++) { 
      String += Chars[Random.Next(0, 61)]; 
     }; 

     return (String); 
    } 
+6

'System.Random' sollte nie zum Generieren von Passwörtern verwendet werden, ist es vorhersehbarer und ist nicht für diesen Zweck gedacht. Verwenden Sie stattdessen 'System.Security.Cryptography.RNGCryptoServiceProvider' Siehe http://StackOverflow.com/a/411985/1160036 und http://StackOverflow.com/a/8996788/1160036 – Despertar

+1

Ich würde nicht empfehlen, Roll-your-Own für Sicherheitsdesign. Durch die Verwendung eines integrierten Sicherheits-Frameworks wie dem .net-Programm erhalten Sie einen gründlich getesteten Code, der von Cryptogrophy-Experten durchdacht wurde. Es ist leicht, selbst viele Fehler zu machen. –

8

nicht sicher, wo ich das gefunden, aber hier ist eine Klasse hoher Entropie zu erzeugen, wirklich zufällige Zeichenfolgen, die als Passwörter verwendet werden können.

using System.Security.Cryptography; 
using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 

public class PasswordGenerator 
{ 
    public int MinimumLengthPassword { get; private set; } 
    public int MaximumLengthPassword { get; private set; } 
    public int MinimumLowerCaseChars { get; private set; } 
    public int MinimumUpperCaseChars { get; private set; } 
    public int MinimumNumericChars { get; private set; } 
    public int MinimumSpecialChars { get; private set; } 

    public static string AllLowerCaseChars { get; private set; } 
    public static string AllUpperCaseChars { get; private set; } 
    public static string AllNumericChars { get; private set; } 
    public static string AllSpecialChars { get; private set; } 
    private readonly string _allAvailableChars; 

    private readonly RandomSecureVersion _randomSecure = new RandomSecureVersion(); 
    private int _minimumNumberOfChars; 

    static PasswordGenerator() 
    { 
     // Define characters that are valid and reject ambiguous characters such as ilo, IO and 1 or 0 
     AllLowerCaseChars = GetCharRange('a', 'z', exclusiveChars: "ilo"); 
     AllUpperCaseChars = GetCharRange('A', 'Z', exclusiveChars: "IO"); 
     AllNumericChars = GetCharRange('2', '9'); 
     AllSpecialChars = "[email protected]#%*()$?+-="; 

    } 

    public PasswordGenerator(
     int minimumLengthPassword = 15, 
     int maximumLengthPassword = 20, 
     int minimumLowerCaseChars = 2, 
     int minimumUpperCaseChars = 2, 
     int minimumNumericChars = 2, 
     int minimumSpecialChars = 2) 
    { 
     if (minimumLengthPassword < 15) 
     { 
      throw new ArgumentException("The minimumlength is smaller than 15.", 
       "minimumLengthPassword"); 
     } 

     if (minimumLengthPassword > maximumLengthPassword) 
     { 
      throw new ArgumentException("The minimumLength is bigger than the maximum length.", 
       "minimumLengthPassword"); 
     } 

     if (minimumLowerCaseChars < 2) 
     { 
      throw new ArgumentException("The minimumLowerCase is smaller than 2.", 
       "minimumLowerCaseChars"); 
     } 

     if (minimumUpperCaseChars < 2) 
     { 
      throw new ArgumentException("The minimumUpperCase is smaller than 2.", 
       "minimumUpperCaseChars"); 
     } 

     if (minimumNumericChars < 2) 
     { 
      throw new ArgumentException("The minimumNumeric is smaller than 2.", 
       "minimumNumericChars"); 
     } 

     if (minimumSpecialChars < 2) 
     { 
      throw new ArgumentException("The minimumSpecial is smaller than 2.", 
       "minimumSpecialChars"); 
     } 

     _minimumNumberOfChars = minimumLowerCaseChars + minimumUpperCaseChars + 
           minimumNumericChars + minimumSpecialChars; 

     if (minimumLengthPassword < _minimumNumberOfChars) 
     { 
      throw new ArgumentException(
       "The minimum length of the password is smaller than the sum " + 
       "of the minimum characters of all catagories.", 
       "maximumLengthPassword"); 
     } 

     MinimumLengthPassword = minimumLengthPassword; 
     MaximumLengthPassword = maximumLengthPassword; 

     MinimumLowerCaseChars = minimumLowerCaseChars; 
     MinimumUpperCaseChars = minimumUpperCaseChars; 
     MinimumNumericChars = minimumNumericChars; 
     MinimumSpecialChars = minimumSpecialChars; 

     _allAvailableChars = 
      OnlyIfOneCharIsRequired(minimumLowerCaseChars, AllLowerCaseChars) + 
      OnlyIfOneCharIsRequired(minimumUpperCaseChars, AllUpperCaseChars) + 
      OnlyIfOneCharIsRequired(minimumNumericChars, AllNumericChars) + 
      OnlyIfOneCharIsRequired(minimumSpecialChars, AllSpecialChars); 
    } 

    private string OnlyIfOneCharIsRequired(int minimum, string allChars) 
    { 
     return minimum > 0 || _minimumNumberOfChars == 0 ? allChars : string.Empty; 
    } 

    public string Generate() 
    { 
     var lengthOfPassword = _randomSecure.Next(MinimumLengthPassword, MaximumLengthPassword); 

     // Get the required number of characters of each catagory and 
     // add random charactes of all catagories 
     var minimumChars = GetRandomString(AllLowerCaseChars, MinimumLowerCaseChars) + 
         GetRandomString(AllUpperCaseChars, MinimumUpperCaseChars) + 
         GetRandomString(AllNumericChars, MinimumNumericChars) + 
         GetRandomString(AllSpecialChars, MinimumSpecialChars); 
     var rest = GetRandomString(_allAvailableChars, lengthOfPassword - minimumChars.Length); 
     var unshuffeledResult = minimumChars + rest; 

     // Shuffle the result so the order of the characters are unpredictable 
     var result = unshuffeledResult.ShuffleTextSecure(); 
     return result; 
    } 

    private string GetRandomString(string possibleChars, int lenght) 
    { 
     var result = string.Empty; 
     for (var position = 0; position < lenght; position++) 
     { 
      var index = _randomSecure.Next(possibleChars.Length); 
      result += possibleChars[index]; 
     } 
     return result; 
    } 

    private static string GetCharRange(char minimum, char maximum, string exclusiveChars = "") 
    { 
     var result = string.Empty; 
     for (char value = minimum; value <= maximum; value++) 
     { 
      result += value; 
     } 
     if (!string.IsNullOrEmpty(exclusiveChars)) 
     { 
      var inclusiveChars = result.Except(exclusiveChars).ToArray(); 
      result = new string(inclusiveChars); 
     } 
     return result; 
    } 
} 

internal static class Extensions 
{ 
    private static readonly Lazy<RandomSecureVersion> RandomSecure = 
     new Lazy<RandomSecureVersion>(() => new RandomSecureVersion()); 
    public static IEnumerable<T> ShuffleSecure<T>(this IEnumerable<T> source) 
    { 
     var sourceArray = source.ToArray(); 
     for (int counter = 0; counter < sourceArray.Length; counter++) 
     { 
      int randomIndex = RandomSecure.Value.Next(counter, sourceArray.Length); 
      yield return sourceArray[randomIndex]; 

      sourceArray[randomIndex] = sourceArray[counter]; 
     } 
    } 

    public static string ShuffleTextSecure(this string source) 
    { 
     var shuffeldChars = source.ShuffleSecure().ToArray(); 
     return new string(shuffeldChars); 
    } 
} 

internal class RandomSecureVersion 
{ 
    //Never ever ever never use Random() in the generation of anything that requires true security/randomness 
    //and high entropy or I will hunt you down with a pitchfork!! Only RNGCryptoServiceProvider() is safe. 
    private readonly RNGCryptoServiceProvider _rngProvider = new RNGCryptoServiceProvider(); 

    public int Next() 
    { 
     var randomBuffer = new byte[4]; 
     _rngProvider.GetBytes(randomBuffer); 
     var result = BitConverter.ToInt32(randomBuffer, 0); 
     return result; 
    } 

    public int Next(int maximumValue) 
    { 
     // Do not use Next() % maximumValue because the distribution is not OK 
     return Next(0, maximumValue); 
    } 

    public int Next(int minimumValue, int maximumValue) 
    { 
     var seed = Next(); 

     // Generate uniformly distributed random integers within a given range. 
     return new Random(seed).Next(minimumValue, maximumValue); 
    } 
} 

Verbrauchen im Code thusly:

var generator = new PasswordGenerator(); 
string password = generator.Generate(); 
Console.WriteLine(password); 
+0

Das hat ein bisschen massiert, aber ist ein solider Start. – im1dermike

+0

Danke dafür, tolle Arbeit. – fkerrigan

+0

Dieser ist wirklich gut. Danke! – MovGP0

Verwandte Themen