.NET Quirks: GeneratePassword() und die Sonderzeichen

(Es gibt eine englische Version dieses Posts hier )

Beim letzten Meetup der PowerShell User Group Berlin hat einer der Teilnehmer zum Thema „Generierung von komplexen Passwörtern“ auf die .NET-Methode [System.Web.Security.Membership]::GeneratePassword() hingewiesen. Auf den ersten Blick sah das Ergebnis von

Add-Type -AssemblyName System.Web
$pwlen = 12
$nachars = 4
[System.Web.Security.Membership]::GeneratePassword($pwlen, $nachars)

durchaus amtlich aus.

Der schreckliche Fund

Es fiel uns allerdings sehr schnell auf, dass die vorgegebene Anzahl nicht-alphanumerischer Zeichen (zweiter Parameter) nicht immer respektiert wird. Meistens wurden mehr Sonderzeichen als angegeben generiert. Wenn die beiden Werte gleich sind, wird das Kennwort erwartungsgemäß nur aus Sonderzeichen erzeugt.

Die Untersuchung

Ich habe das im Nachgang noch einmal über das gesamte Spektrum der möglichen Parameterwerte (die Kennwort-Länge kann maximal 128 betragen, und die Anzahl Sonderzeichen kann zwischen 0 und der Kennwortlänge variieren) untersucht, und folgendes ist herausgekommen:

  • je mehr Sonderzeichen (relativ zur Gesamtlänge) wir also anfordern, desto höher die Wahrscheinlichkeit, dass wir genau diese Anzahl erhalten werden.
  • in vielen Kombinationen, insbesondere mit einer geringen Anzahl an Sonderzeichen, wurden nahezu alle Kennwörter abweichend von der Anforderung erzeugt (gerundet auf zwei Stellen, landet die Metrik der Abweichung bei 1, also bei 100%).

Die konkreten tabellarischen Daten könnt ihr hier herunterladen: pwd-nonalpha . Farblich visualisiert, sieht das Ergebnis wie folgt aus (Reihen: Kennwortlänge von 1 bis 128):

Die Methodik

Das Skript, mit dem die Untersuchung durchgeführt wurde, ist wie folgt. Für jede Kombination aus Kennwortlänge $plen von 1 bis 128 und Anzahl Sonderzeichen $nnan von 0 bis $plen werden 1000 ($nloops) Kennwörter berechnet und für jedes die Sonderzeichen gezählt. Die Zahl der Fälle, in denen die tatsächliche Anzahl Sonderzeichen von $nnan abweicht, geteilt durch $nloops, ist unsere Metrik für die Beachtung der Angabe.

Add-Type -AssemblyName System.Web
function Count-NonAlphaNum {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)][string]$InString
    )
    return (Select-String '[^A-Za-z0-9]' -Input $InString -AllMatches).Matches.Count
}
$outfile = "c:\temp\pwd-nonalpha.csv"
$nloops = 1000
$maxplen = 128
'"PwdLen";"{0}"' -f ((0..$maxplen)-join '";"') | Set-Content $outfile -Force
for ($plen = 1; $plen -le $maxplen; $plen++) {
    $line = @($plen)
    for ($nnan = 0; $nnan -le $plen; $nnan ++) {
        $ndiff = 0
        for ($i = 1;$i -le $nloops; $i++) {
            $pwd = [System.Web.Security.Membership]::GeneratePassword($plen,$nnan)
            $nnac = Count-NonAlphaNum -InString $pwd
            if ($nnac -ne $nnan) { $ndiff++ }
        }
        $line += [Math]::Round($ndiff / $nloops,2)
    }
    for ($nnan = $plen + 1; $nnan -le $maxplen; $nnan++) {
        $line += ''
    }
    '"{0}"' -f ($line -join '";"') | Add-Content $outfile
}

Das Fazit

Für einen typischen Fall des Initialkennworts (relativ langes Kennwort mit 1-2 Sonderzeichen) ist die .NET-Methode ungeeignet, und man muss sich deterministischer Mittel bedienen, auch wenn sie vielleicht etwas weniger performant sind (was noch zu untersuchen wäre).

Happy password generating!

 

Ersten Kommentar schreiben

Antworten

Deine E-Mail-Adresse wird nicht veröffentlicht.


*


Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.