Batch Password Generator?

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

heute habe ich nicht mehr viel Lust zu erklären:

@echo off
chcp 65001 >nu
setlocal enabledelayedexpansion
  rem alle möglichen Zeichen
set "StringOfChars=_@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
  rem Zeichen in StringOfChars...
set "countOfChars=64"


  rem Länge von Key:20 (kann auch kürzer oder länger sein), bei 1.000.000 mio zufallsstrings gab es keine  Duplikate
call :createKey Key 20
  rem Key anzeigen
echo das ist ein 20 Zeichen langer Key:
echo %Key%
echo:
  rem Länge von Key:128
call :createKey Key 128
echo das ist ein 20 Zeichen langer Key:
echo %Key%

pause
exit /b

:: ========== Unterprogramme ==========
:createKey %1= VariableName  um den  Key aufzunehmen %2=Länge des Keys 
setlocal
    rem generiere Key
  for /l %%a in (1,1,%~2) do (
      rem Zufallszahl zwischen 0 und (Anzahl der Zeichen im String)-1 würfeln
    call :getNewRandom newRandom %countOfChars%
      rem Zeichen Nummer ZufallsZahl aus %StringOfChars% ermitteln
    call set "this.Char=%%StringOfChars:~!newRandom!,1%%"
      rem Zeichen zu Variable key hinzufügen
    set "this.Key=!this.Key!!this.Char!"
  )
endlocal & set "%1=%this.Key%"
exit /b 

:getNewRandom  %1=VarName  %2=RandomFactor
  set /a "%1=!random! %% %2"
    rem Dafür  sorgen das nicht 2 mal die gleiche  Zahl aufeinander folgt... 
  if "!%1!"=="!%1.old!" goto :getNewRandom 
  set "%1.old=!%1!" 
exit /b

Die etwas ausgefeiltere Variante.

Eigentlich musst Du nur die Variable keyLength= anpassen. Neue Keys /Passwörter werden zur Datei keys.txt hinzugefügt...

@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
  rem alle möglichen Zeichen
set "StringOfChars=_@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
  rem Zeichen in StringOfChars zählen  und  in der variable countOfChars
call :getStringLength countOfChars "%StringOfChars%"
  rem Länge von Key
set "keyLength=8"

set "outputFile=keys.txt"
:::::::::::::::: ein wenig Interaktivität ;p :::::::::::::
call :askSettings ||exit /b
echo ...erzeuge %numberOfKeys% Keys:
call :getTimeStamp loopStart

  rem Zählschleife: führe %numberOfKeys% mal das Unterprogramm :createKey aus
for /l %%i in (1,1,%numberOfKeys%) do (
    rem erzeuge Ergebnis in der Variable __Key
  call :createKey __Key
    rem Key anzeigen
  echo !__Key!  %%i
    rem wenn in Datei gepeichert werden soll...
  if "%save%"=="true" (
      rem  ...Key in Datei schreiben
    echo !__Key!>>"%outputFile%"
) )
:::::::::::::::   Ende  der Schleife ::::::::::::::::::::::::::::::::::::::::::::::::::::
echo Es wurden %numberOfKeys% Keys erzeugt.
echo:

  rem mit geschriebenen Daten arbeiten
if "%save%"=="true" (
  if exist "%outputFile%" (
    call :showSorted
    call :findDuplcates
    timeout 2 >nul
      rem .txt-Datei mit Standard-Anwendung öffnen  
    start "" "%outputFile%"
) )
pause
exit /b
:::::::::::::::::::: Programm Ende :::::::::::::::::::::


:: ========== Unterprogramme ==========
:createKey %1= VariableName  um den  Key aufzunehmen
setlocal
    rem generiere Key
  for /l %%a in (1,1,%keyLength%) do (
      rem Zufallszahl zwischen 0 und (Anzahl der Zeichen im String)-1 würfeln
    call :getNewRandom newRandom %countOfChars%
      rem Zeichen Nummer ZufallsZahl aus %StringOfChars% ermitteln
    call set "this.Char=%%StringOfChars:~!newRandom!,1%%"
      rem Zeichen zu Variable key hinzufügen
    set "this.Key=!this.Key!!this.Char!"
  )
endlocal & set "%1=%this.Key%"
exit /b 


:::::: Abfragen
:askSettings
    rem  Abfrage wieviele Keys erzeugt werden sollen
  for /l %%a in (1,1,3) do (
    set /p "numberOfKeys=Wie viele Keys sollen generiert werden? :"
    rem prüfen ob eine Zahl eingegeben wurde,  wenn richtig Schleife  abbrechen
    call :isNumber !numberOfKeys! && goto :break
    echo ...eine Zahl eingeben ^^!^^!^^!
  )
  echo:
  echo 3 Mal keine Zahl eingegeben... o.O ich hau ab...
  timeout 5 >nul
    rem ... errorlevel 4712 setzen (sch*** egal ;p)
  exit /b 4712
  :break  
  if %numberOfKeys% equ 0 (
    echo:
    echo ...nichts zu tun...Tschuess
    timeout 2 >nul
    exit /b 99
  )
    rem Abfrage ob die erzeugten Keys in in eine Datei gespeichert werden sollen
  choice /c JN /m "Sollen diese in die Datei "%outputFile%" gespeichert werden? "
    rem wenn ja setze die Variable save=true
    if %errorlevel% equ 1 (set "save=true")
exit /b 0
:::::: ende Abfragen


:showSorted
  choice /c JN /m "Sortiert anzeigen? "
    if !errorlevel! equ 1 (
      echo:
      type "%outputFile%"|sort|more
    )
exit /b


:findDuplcates
  choice /c JN /m "Duplikate suchen? "
    if !errorlevel! equ 1 (
      echo:
      set "__D_Counter=0"
      for /f "tokens=*" %%a in ('type "%outputFile%"^|sort') do (
        if "!__last!"=="%%a" (
          echo Dulikat gefunden...: %%a
          set /a "__D_Counter+=1"
          pause
        )
          set "__last=%%a"
      )
      echo !__D_Counter! Duplikate gefunden
    )
exit /b


::-------------- Helperfunctions ---------------------------
:isNumber  %1=sollte Zahl sein
    rem wenn keine Zahl wird errorlevel 
  set /a "dummy=%1" 2>nul || exit /b 2 gesetzt
  if "%dummy%"=="%1"  exit /b 0
exit /b 1
 
:getStringLength %1=VarName  %2="String"
    rem länge eines String ermitteln
  echo:%~2 >"%temp%\length_4_%1.tmp"
  for %%f in ("%temp%\length_4_%1.tmp") do (set /a "%1=%%~zf-3" )
  exit /b


:getNewRandom  %1=VarName  %2=RandomFactor
  set /a "%1=!random! %% %2"
    rem Dafür  sorgen das nicht 2 mal die gleiche  Zahl aufeinander folgt... 
  if "!%1!"=="!%1.old!" goto :getNewRandom 
  set "%1.old=!%1!" 
exit /b


:getTimeStamp   param: %1=VariableName [%2=length] default=15 (yymmddHHMMSS3ms)
for /f "skip=2 tokens=2,3 delims=,.+" %%a in ('wmic os get localdatetime /format:csv') do (
    set "%~1=%%a%%b"
    if "%~2"=="" (set "%~1=!%~1:~2,15!") else (set "%~1=!%~1:~2,%~2!")
)
exit /b

...Der Generator ist ein Überbleibsel aus einem älteren Projekt, desshalb verwende ich Key statt Passwort. Im Prinzip ist es Wurst wie man das Kind nennt. Hauptsache wirklich sehr Zufällig.

Du kannst ja mal 10000 von den Keys 8 Zeichen langen Keys erzeugen und schauen wieviel Duplikate es gibt.

Eine entsprechende Routine ist enthalten...

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren
maxhat3beine 
Fragesteller
 07.04.2021, 13:06

wow, das klappt super, danke dir!

0
Erzesel  07.04.2021, 22:29
@maxhat3beine

Hier das Ganze in Powershell (zigmal schneller)

randomKeys.ps1

$StringOfChars='_@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$KeyLength=8;
$KeyFile='Keys.txt';
do {$NumberOfKeys = $(read-host 'Wieviele neue Passwoerter sollen erzeugt werden?') -as [uint32] } until ($NumberOfKeys)


  #bereits erzeugte Keys laden (um evtl. erzeugte Duplikate zu finden)
'Lade Keys aus Datei...'


$AllKeys = Get-Content $KeyFile -erroraction SilentlyContinue -readcount 0;
'{0} Keys aus Datei geladen' -f $AllKeys.count;
  #wenn die  gewünschte größe des Keys die Anzahl der verfügbaren Zeichen übersteigt, vervielfache den String
while ($KeyLength -gt $StringOfChars.length ){$StringOfChars+=$StringOfChars};
$current = Get-Date
$NewKeys += 1..$NumberOfKeys|foreach{
      #erzeuge Zufallsstring
    $Key = -join([System.Text.Encoding]::Default.GetBytes($StringOfChars) |Get-Random -Count $KeyLength| %{[char]$_});
      #Fortschritt anzeigen, (aber  nicht an Sammelvariable übergeben)
      #wenn du die folgende Zeile  entfernst/auskommentierst verdreifacht sich die Geschwindigkeit!
    Write-Host ('{0}' -f $Key,$_) -fo green -n;Write-Host ('   {0}' -f $_)
      #Key an Sammelvariable übergeben
    $Key;
}
$end= Get-Date
Write-Host('Dauer: {0} Sekunden fuer {1} Keys' -f ((New-TimeSpan -Start $current -End $end).TotalSeconds),$NewKeys.count) -fo blue;
'{0} neue Keys ereugt' -f $NewKeys.count
  #neue Keys zu bestehenden hinzufügen
$AllKeys += $NewKeys
'Insgesammt {0} Keys vorhanden' -f $AllKeys.count
'suche Duplikate...'


$CleanedKeys = $AllKeys| sort |%{$old=$Null;$DuplicateCount=0;}{
    if ($_ -eq $old){
        Write-Host $_ -fo Red;
        $DuplicateCount+=1;
    } else {$_};
    $old=$_;
}
'{0} Duplikate  entfernt' -f ($DuplicateCount)
'schreibe {0} Keys in Datei' -f $CleanedKeys.count
  #superschnelle Methode um ein riesige Powershellarrays in einem Rutsch in eien Datei zu schreiben
$StreamWriter = New-Object System.IO.StreamWriter($KeyFile)
  #wandle ein Array in einen String (füge  als Trennzeichen eien Zeilenvorschub ein) ...und  schreibe diesen in die Datei
$StreamWriter.write(($CleanedKeys -join [Environment]::NewLine))
$StreamWriter.close()
'fertig...'
pause

Da sich Powershell nur über das Kontextmenü starten lässt, das ganze als Hybrdbatch:

randomKeys.cmd

<# : begin batchpart (don't change this line)
@echo off
  rem run appended Powershell/C#-script
start "" powershell "iex (${%~f0}|out-string)"
exit /b
::end batchpart (don't change this line)#>
$StringOfChars='_@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$KeyLength=8;
$KeyFile='Keys.txt';
do {$NumberOfKeys = $(read-host 'Wieviele neue Passwoerter sollen erzeugt werden?') -as [uint32] } until ($NumberOfKeys)
'Lade Keys aus Datei...'
$AllKeys = Get-Content $KeyFile -erroraction SilentlyContinue -readcount 0;
'{0} Keys aus Datei geladen' -f $AllKeys.count;
while ($KeyLength -gt $StringOfChars.length ){$StringOfChars+=$StringOfChars};
$current = Get-Date
$NewKeys += 1..$NumberOfKeys|foreach{
    $Key = -join([System.Text.Encoding]::Default.GetBytes($StringOfChars) |Get-Random -Count $KeyLength| %{[char]$_});
      #wenn du die folgende Zeile  entfernst/auskommentierst verdreifacht sich die Geschwindigkeit!
    Write-Host ('{0}' -f $Key,$_) -fo green -n;Write-Host ('   {0}' -f $_);
    $Key;
}
$end= Get-Date
Write-Host('Dauer: {0} Sekunden fuer {1} Keys' -f ((New-TimeSpan -Start $current -End $end).TotalSeconds),$NewKeys.count) -fo blue;
'{0} neue Keys ereugt' -f $NewKeys.count
$AllKeys += $NewKeys
'Insgesammt {0} Keys vorhanden' -f $AllKeys.count
'suche Duplikate...'
$CleanedKeys = $AllKeys| sort |%{$old=$Null;$DuplicateCount=0;}{
    if ($_ -eq $old){
        Write-Host $_ -fo Red;
        $DuplicateCount+=1;
    } else {$_};
    $old=$_;
}
'{0} Duplikate  entfernt' -f ($DuplicateCount)
'schreibe {0} Keys in Datei' -f $CleanedKeys.count
$StreamWriter = New-Object System.IO.StreamWriter($KeyFile)
$StreamWriter.write(($CleanedKeys -join [Environment]::NewLine))
$StreamWriter.close()
'fertig...'
pause

10000 Keys in 13 Sekunden (@ 4,3GHz)

4 Sekunden, wenn die Zeile:

    Write-Host ('{0}' -f $Key,$_) -fo green -n;Write-Host ('   {0}' -f $_)

...entfernt wird.

0
daCypher  19.04.2022, 13:56

Hut ab, dass du sowas in Batch gebaut kriegst

0
daCypher  19.04.2022, 15:27
@daCypher

Wenn man nur ein einzelnes Passwort haben will und nicht geprüft werden soll, ob das Passwort schon mal erstellt wurde, kann man auch in Batch den Umweg über PowerShell nehmen:

powershell -ex bypass -c "[string]::Join('',{$r=[Random]::new();0..(Read-Host -P 'Länge')|%{[char]$r.Next(33,126)}}.Invoke())"

(PS: ich kann es leider nicht in cmd testen, weil der Windows Defender neuerdings meint, gleich Warnmeldungen per E-Mail wegen "suspicious powershell script" zu verschicken, wenn ich einen powershell-Befehl in cmd ausführe, aber im Prinzip sollte das so laufen)

0
Erzesel  19.04.2022, 19:45
@daCypher

Warum Dein Defender rebelliert kann ich nicht nachvollziehen. 🤔(da ist bei mir die Heuristik schon Zuviel gewöhnt?) ...könnte aber durchaus sein , das er sich am Scriptblock.Invoke() gestoßen hat. Scriptblöcke kann man auch zur Codeinjektion zur Laufzeit nutzen 😲 . Powershell ist da nicht ganz "ohne"!

 #scriptinjection zur Laufzeit ...tippe  mal get-random  ein
$scriptBlock = [Scriptblock]::Create((Read-host -p 'enter Code:'))
$scriptBlock.Invoke()

Du hast es etwas zu "gut" gemeint. (Kanonen auf Spatzen)

  • Für ein "commandlinescript" brauchst du keine Ex.Policy zu setzen.
  • etwas weniger .Net und der Scriptblock (...und dessen .Invoke) wären überflüssig
  • für Get-Random braucht man auch nicht explizit ein Random-Objekt initialisieren
  • mit %-Zeichen in cmd sollte man behutsam Umgehen, diese kennzeichnen Variablen und müssten in einer Batch verdoppelt werden, Mit dem alias foreach umschifft man dies.

Ich denke mal mit Folgendem dürfte auch der Defender zufrieden sein:

powershell -c "(1..(Read-Host -P 'Laenge')|foreach{[char](Get-Random -min 33 -max 126)})-join ''"

mit Powershell 7 wird es noch billiger:

pwsh.exe -c "[char[]]( Get-Random -count (Read-Host -P 'Länge') -min 33 -max 126) -join ''"

...auf Speed braucht man bei beiden nicht zu schauen, da ist der Anlaufoverhead von PowerShell einfach zu gewaltig.

0

Also theoretisch auch wenn Zufall nicht wirklich existiert man kann ja eigentlich den Zufall berechnen aber du könntest nur ein bsp auch wenn ich nicht verstehe warum batch und nicht Python oder so.

Du könntest ganz einfach mit random eine Zahl raus picken indem du sagen wir in der variabel die du setzen kannst gewisse Zahlen zu ersetzen

Super_passwort = %Random%%Random%%Random%
Set Super_passwort=%Super_passwort:eine zahl=Buchstabe%
Rem so könntest du quasi gewisse zufallszahlen ersetzen wie lange du das jetzt ziehst und welchen Buchstaben du durch welche Zahl ersetzt bleibt dir überlassen natürlich wird es da schnell an seinem Limit kommen aber es ist ja nur ein batch script