Merhabalar
Sürüm 7.seviyeye ulaştık, galiba olduğu gibi...
Şimdiye kadar ki sürümler :
C:\Users\TRWE_2012\Masaüstü\ENİGMA PROJESİ-SİLME-\Enigma Cipher_v1.0.ps1
C:\Users\TRWE_2012\Masaüstü\ENİGMA PROJESİ-SİLME-\Enigma Cipher_v2.0.ps1
C:\Users\TRWE_2012\Masaüstü\ENİGMA PROJESİ-SİLME-\Enigma Cipher_v3.0.ps1
C:\Users\TRWE_2012\Masaüstü\ENİGMA PROJESİ-SİLME-\Enigma Cipher_v4.0.ps1
C:\Users\TRWE_2012\Masaüstü\ENİGMA PROJESİ-SİLME-\Enigma Cipher_v5.0.ps1
C:\Users\TRWE_2012\Masaüstü\ENİGMA PROJESİ-SİLME-\Enigma Cipher_v6.0.ps1
Enigma Cipher_v7.0.ps1
Kod: Tümünü seç
<#
.SYNOPSIS
Historical Enigma machine simulator (encryption and decryption),
supporting both the 3-rotor Wehrmacht/M3 Enigma and the 4-rotor
Kriegsmarine Naval Enigma M4 used on U-boats from 1942 onward.
.DESCRIPTION
Implements the classic Enigma cipher: rotor wiring, ring settings
(Ringstellung), initial rotor positions (Grundstellung), a plugboard
(Steckerbrett), and a reflector, including the historical double-
stepping anomaly of the middle rotor.
M3 mode: 3 rotors chosen from I-V, wide reflector B or C.
M4 mode: 3 rotors chosen from I-VIII (naval rotors VI-VIII have two
turnover notches each), plus a static 4th "Greek" rotor (Beta or
Gamma) next to a thin reflector (B-THIN or C-THIN). The Greek rotor
never steps, exactly like the real U-boat machine.
Enigma is a reciprocal cipher: running the SAME configuration (model,
rotor order, ring settings, start position, Greek rotor if M4,
plugboard pairs, reflector) over ciphertext returns the original
plaintext.
.PARAMETER InputFile
Path to a .txt file containing the text to process. When supplied, the
script skips the interactive prompt entirely and processes the whole
file in one pass -- the reliable way to handle very large texts, since
pasting huge blocks into Read-Host can truncate or corrupt input.
.PARAMETER OutputFile
Path for the continuous ciphertext/plaintext result when -InputFile is
used. Two companion files are also written next to it automatically:
"<name>_prepared.txt" (cleaned input actually fed to the rotors) and
"<name>_grouped.txt" (same result split into 5-letter radio groups).
If omitted, defaults to "<InputFile-name>_enigma.txt" in the same folder.
.NOTES
The alphabet is restricted to A-Z (26 letters), matching the physical
machine. Input is uppercased; spaces and punctuation are stripped;
accented letters are folded to their closest plain A-Z equivalent;
digits are converted to spoken German radio words (2 -> ZWO, 5 -> FUENF)
instead of being dropped. Wrap a code in [BRACKETS] to spell it out
fully using the Kriegsmarine spelling alphabet, e.g. [HX-2E] becomes
HEINRICH XANTHIPPE ZWO EMIL before encryption.
.EXAMPLE
.\Enigma-Cipher.ps1
Interactive mode: configure the machine, then type/paste messages one
at a time.
.EXAMPLE
.\Enigma-Cipher.ps1 -InputFile "C:\Messages\report.txt" -OutputFile "C:\Messages\report_out.txt"
Batch mode: configure the machine once, then the entire file is
processed in a single pass -- recommended for very large texts.
#>
[CmdletBinding()]
param(
[string]$InputFile,
[string]$OutputFile
)
$ErrorActionPreference = "Stop"
# Force UTF-8 for both directions so Turkish characters (c-cedilla, g-breve,
# dotless-i, o/u-umlaut, s-cedilla) are read from and written to the console
# correctly, regardless of the system's active codepage.
try {
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
} catch {
# Some hosts (e.g. the PowerShell ISE) don't allow changing console
# encoding; safe to ignore, the trap below still protects the session.
}
# Safety net: if ANYTHING unexpected goes wrong anywhere below, show the
# error instead of letting the console window vanish silently.
trap {
Write-Host ""
Write-Host "=== UNEXPECTED ERROR ==="
Write-Host $_.Exception.Message
Write-Host ""
Write-Host "The window is being kept open so you can read this message."
Read-Host "`nPress ENTER to exit."
exit 1
}
# --- Historical rotor wirings (Wehrmacht Enigma I + Kriegsmarine naval rotors) ---
# Rotors VI, VII, VIII (naval only) each have TWO turnover notches instead of one.
$RotorDefs = @{
"I" = @{ Wiring = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"; Notches = @("Q") }
"II" = @{ Wiring = "AJDKSIRUXBLHWTMCQGZNPYFVOE"; Notches = @("E") }
"III" = @{ Wiring = "BDFHJLCPRTXVZNYEIWGAKMUSQO"; Notches = @("V") }
"IV" = @{ Wiring = "ESOVPZJAYQUIRHXLNFTGKDCMWB"; Notches = @("J") }
"V" = @{ Wiring = "VZBRGITYUPSDNHLXAWMJQOFECK"; Notches = @("Z") }
"VI" = @{ Wiring = "JPGVOUMFYQBENHZRDKASXLICTW"; Notches = @("Z", "M") }
"VII" = @{ Wiring = "NZJHGRCXMYSWBOUFAIVLPEKQDT"; Notches = @("Z", "M") }
"VIII" = @{ Wiring = "FKQHTLXOCBJSPDZRAMEWNIUYGV"; Notches = @("Z", "M") }
}
# Beta and Gamma: the non-stepping 4th ("Greek") rotor used only on the naval
# M4 machine. It sits next to the reflector, has a ring setting like a normal
# rotor, but is never advanced by the stepping mechanism.
$GreekDefs = @{
"BETA" = "LEYJVCNIXWPBQMDRTAKZGFUHOS"
"GAMMA" = "FSOKANUERHMBTIYCWLQPZXVGJD"
}
$ReflectorDefs = @{
"B" = "YRUHQSLDPXNGOKMIEBFZCWVJAT"
"C" = "FVPJIAOYEDRZXWGCTKUQSBNMHL"
"B-THIN" = "ENKQAUYWJICOPBLMDXZVFTHRGS"
"C-THIN" = "RDOBJNTKVEHMLFCWZAXGYIPSUQ"
}
$Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# Turkish-to-plain character folding table, built from Unicode code points
# to avoid embedding accented characters directly in this source file.
$FoldMap = @{
[char]0x00E7 = "C"; [char]0x00C7 = "C" # c with cedilla
[char]0x011F = "G"; [char]0x011E = "G" # g with breve
[char]0x0131 = "I"; [char]0x0130 = "I" # dotless / dotted i
[char]0x00F6 = "O"; [char]0x00D6 = "O" # o with diaeresis
[char]0x015F = "S"; [char]0x015E = "S" # s with cedilla
[char]0x00FC = "U"; [char]0x00DC = "U" # u with diaeresis
}
# German military radio digit words. "2" is spoken "ZWO" instead of "ZWEI",
# the real historical convention used to avoid confusion with "DREI" (3)
# over noisy radio traffic.
$DigitWords = @{
'0' = "NULL"; '1' = "EINS"; '2' = "ZWO"; '3' = "DREI"; '4' = "VIER"
'5' = "FUENF"; '6' = "SECHS"; '7' = "SIEBEN"; '8' = "ACHT"; '9' = "NEUN"
}
# Kriegsmarine spelling alphabet (Buchstabiertafel), used to unambiguously
# spell out call signs, grid references and convoy designators letter by
# letter over the radio.
$SpellingAlphabet = @{
'A' = "ANTON"; 'B' = "BERTA"; 'C' = "CAESAR"; 'D' = "DORA"
'E' = "EMIL"; 'F' = "FRIEDRICH"; 'G' = "GUSTAV"; 'H' = "HEINRICH"
'I' = "IDA"; 'J' = "JULIUS"; 'K' = "KAUFMANN"; 'L' = "LUDWIG"
'M' = "MARTHA"; 'N' = "NORDPOL"; 'O' = "OTTO"; 'P' = "PAULA"
'Q' = "QUELLE"; 'R' = "RICHARD"; 'S' = "SAMUEL"; 'T' = "TONI"
'U' = "ULRICH"; 'V' = "VIKTOR"; 'W' = "WILHELM"; 'X' = "XANTHIPPE"
'Y' = "YPSILON"; 'Z' = "ZEPPELIN"
}
function ConvertTo-EnigmaAlphabet {
param([string]$Text)
$sb = New-Object System.Text.StringBuilder
foreach ($ch in $Text.ToUpperInvariant().ToCharArray()) {
if ($FoldMap.ContainsKey($ch)) {
[void]$sb.Append($FoldMap[$ch])
} elseif ($ch -ge 'A' -and $ch -le 'Z') {
[void]$sb.Append($ch)
}
# anything else (spaces, digits, punctuation) is dropped
}
return $sb.ToString()
}
function ConvertTo-RadioDigits {
# Replaces every digit character anywhere in the text with its spoken
# German radio word, so numbers survive instead of being silently
# dropped (the real Enigma keyboard had no digit keys).
param([string]$Text)
$sb = New-Object System.Text.StringBuilder
foreach ($ch in $Text.ToCharArray()) {
$key = [string]$ch
if ($DigitWords.ContainsKey($key)) {
[void]$sb.Append(" ")
[void]$sb.Append($DigitWords[$key])
[void]$sb.Append(" ")
} else {
[void]$sb.Append($ch)
}
}
return $sb.ToString()
}
function Expand-SpellingBrackets {
# Any [BRACKETED] segment is expanded letter-by-letter and digit-by-
# digit using the Kriegsmarine spelling alphabet, e.g. [HX-2E] becomes
# "HEINRICH XANTHIPPE ZWO EMIL". Use this around call signs, convoy
# codes or grid references you want spelled out unambiguously.
param([string]$Text)
$pattern = '\[([^\]]+)\]'
$evaluator = {
param($match)
$inner = $match.Groups[1].Value.ToUpperInvariant()
$words = @()
foreach ($ch in $inner.ToCharArray()) {
$key = [string]$ch
if ($Script:DigitWords.ContainsKey($key)) {
$words += $Script:DigitWords[$key]
} elseif ($ch -ge 'A' -and $ch -le 'Z') {
$words += $Script:SpellingAlphabet[$key]
}
}
return " " + ($words -join " ") + " "
}
return [regex]::Replace($Text, $pattern, $evaluator)
}
function Format-Grouped {
# Splits ciphertext/plaintext into historical 5-letter radio groups.
param([string]$Text, [int]$GroupSize = 5)
if ([string]::IsNullOrEmpty($Text)) { return "" }
$groups = New-Object System.Collections.Generic.List[string]
for ($i = 0; $i -lt $Text.Length; $i += $GroupSize) {
$len = [Math]::Min($GroupSize, $Text.Length - $i)
$groups.Add($Text.Substring($i, $len))
}
return ($groups -join " ")
}
function New-Rotor {
param([string]$Name, [int]$RingSetting, [char]$StartPosition)
$def = $RotorDefs[$Name]
return [PSCustomObject]@{
Name = $Name
Wiring = $def.Wiring
Notches = $def.Notches
Ring = $RingSetting
Position = [int][char]$StartPosition - [int][char]'A'
}
}
function New-GreekRotor {
# The 4th M4 rotor: has wiring and a ring setting like a normal rotor,
# but no notches and is never stepped.
param([string]$Name, [int]$RingSetting, [char]$StartPosition)
return [PSCustomObject]@{
Name = $Name
Wiring = $GreekDefs[$Name]
Notches = @()
Ring = $RingSetting
Position = [int][char]$StartPosition - [int][char]'A'
}
}
function Step-Rotor {
param($Rotor)
$Rotor.Position = ($Rotor.Position + 1) % 26
}
function Test-AtNotch {
param($Rotor)
foreach ($notch in $Rotor.Notches) {
$notchIndex = [int][char]$notch - [int][char]'A'
if ($Rotor.Position -eq $notchIndex) { return $true }
}
return $false
}
function Step-Rotors {
param($Left, $Middle, $Right)
$middleAtNotch = Test-AtNotch -Rotor $Middle
$rightAtNotch = Test-AtNotch -Rotor $Right
if ($middleAtNotch) {
Step-Rotor -Rotor $Left
Step-Rotor -Rotor $Middle
} elseif ($rightAtNotch) {
Step-Rotor -Rotor $Middle
}
Step-Rotor -Rotor $Right
}
function Invoke-RotorForward {
param($Rotor, [int]$Index)
$offset = $Rotor.Position - ($Rotor.Ring - 1)
$shifted = (($Index + $offset) % 26 + 26) % 26
$mapped = [int][char]$Rotor.Wiring[$shifted] - [int][char]'A'
return (($mapped - $offset) % 26 + 26) % 26
}
function Invoke-RotorBackward {
param($Rotor, [int]$Index)
$offset = $Rotor.Position - ($Rotor.Ring - 1)
$shifted = (($Index + $offset) % 26 + 26) % 26
$mapped = $Rotor.Wiring.IndexOf([char]([int][char]'A' + $shifted))
return (($mapped - $offset) % 26 + 26) % 26
}
function Invoke-Plugboard {
param([hashtable]$Plugboard, [int]$Index)
$letter = $Alphabet[$Index]
if ($Plugboard.ContainsKey($letter)) {
return [int][char]$Plugboard[$letter] - [int][char]'A'
}
return $Index
}
function Invoke-EnigmaChar {
param($Left, $Middle, $Right, $Greek, [string]$ReflectorWiring, [hashtable]$Plugboard, [char]$Char)
Step-Rotors -Left $Left -Middle $Middle -Right $Right
$idx = [int][char]$Char - [int][char]'A'
$idx = Invoke-Plugboard -Plugboard $Plugboard -Index $idx
$idx = Invoke-RotorForward -Rotor $Right -Index $idx
$idx = Invoke-RotorForward -Rotor $Middle -Index $idx
$idx = Invoke-RotorForward -Rotor $Left -Index $idx
if ($Greek) { $idx = Invoke-RotorForward -Rotor $Greek -Index $idx }
$idx = [int][char]$ReflectorWiring[$idx] - [int][char]'A'
if ($Greek) { $idx = Invoke-RotorBackward -Rotor $Greek -Index $idx }
$idx = Invoke-RotorBackward -Rotor $Left -Index $idx
$idx = Invoke-RotorBackward -Rotor $Middle -Index $idx
$idx = Invoke-RotorBackward -Rotor $Right -Index $idx
$idx = Invoke-Plugboard -Plugboard $Plugboard -Index $idx
return $Alphabet[$idx]
}
function Invoke-EnigmaText {
param($Left, $Middle, $Right, $Greek, [string]$ReflectorWiring, [hashtable]$Plugboard, [string]$Text, [switch]$ShowProgress)
$expanded = Expand-SpellingBrackets -Text $Text
$radioized = ConvertTo-RadioDigits -Text $expanded
$clean = ConvertTo-EnigmaAlphabet -Text $radioized
$total = $clean.Length
$sb = New-Object System.Text.StringBuilder($total)
$i = 0
foreach ($ch in $clean.ToCharArray()) {
[void]$sb.Append((Invoke-EnigmaChar -Left $Left -Middle $Middle -Right $Right -Greek $Greek -ReflectorWiring $ReflectorWiring -Plugboard $Plugboard -Char $ch))
$i++
if ($ShowProgress -and $total -gt 0 -and ($i % 500 -eq 0 -or $i -eq $total)) {
$pct = [Math]::Min(100, [int](($i / $total) * 100))
Write-Progress -Activity "Processing through Enigma" -Status "$i / $total letters" -PercentComplete $pct
}
}
if ($ShowProgress) { Write-Progress -Activity "Processing through Enigma" -Completed }
return [PSCustomObject]@{
Clean = $clean
Output = $sb.ToString()
}
}
function Read-RotorChoice {
param([string]$Label, [string[]]$ValidNames, [string[]]$Exclude)
$choice = $null
$optionsText = $ValidNames -join " / "
do {
$raw = (Read-Host "$Label rotor ($optionsText)").ToUpperInvariant()
if ($Exclude -contains $raw) {
Write-Host "That rotor is already used, pick a different one."
} elseif ($ValidNames -notcontains $raw) {
Write-Host "Invalid rotor name."
} else {
$choice = $raw
}
} while (-not $choice)
return $choice
}
function Read-GreekChoice {
$choice = $null
do {
$raw = (Read-Host "Greek (4th) rotor (BETA / GAMMA)").ToUpperInvariant()
if ($GreekDefs.ContainsKey($raw)) { $choice = $raw }
else { Write-Host "Invalid choice, enter BETA or GAMMA." }
} while (-not $choice)
return $choice
}
function Read-RingSetting {
param([string]$Label)
$result = $null
do {
$raw = Read-Host "$Label ring setting (1-26)"
$parsed = 0
$ok = [int]::TryParse($raw, [ref]$parsed) -and ($parsed -ge 1) -and ($parsed -le 26)
if (-not $ok) {
Write-Host "Enter a number between 1 and 26."
} else {
$result = $parsed
}
} while (-not $result)
return $result
}
function Read-StartPosition {
param([string]$Label)
$result = $null
do {
$raw = (Read-Host "$Label start position (A-Z)").ToUpperInvariant()
$ok = ($raw.Length -eq 1) -and ($raw[0] -ge 'A') -and ($raw[0] -le 'Z')
if (-not $ok) {
Write-Host "Enter a single letter A-Z."
} else {
$result = $raw[0]
}
} while (-not $result)
return [char]$result
}
function Read-Plugboard {
$plugboard = @{}
Write-Host ""
Write-Host "Plugboard setup (Steckerbrett): enter letter pairs, e.g. AB then CD."
Write-Host "Leave blank and press ENTER when done (max 10 pairs)."
$count = 0
while ($count -lt 10) {
$raw = (Read-Host "Pair $($count + 1)").ToUpperInvariant().Trim()
if ([string]::IsNullOrEmpty($raw)) { break }
if ($raw.Length -ne 2 -or $raw[0] -eq $raw[1]) {
Write-Host "Invalid pair, must be two different letters. Try again."
continue
}
$a = $raw[0]; $b = $raw[1]
if ($plugboard.ContainsKey($a) -or $plugboard.ContainsKey($b)) {
Write-Host "One of these letters is already plugged. Try again."
continue
}
$plugboard[$a] = $b
$plugboard[$b] = $a
$count++
}
return $plugboard
}
function Save-SessionSettings {
param(
[string]$Path, [string]$Model,
[string]$LeftName, [string]$MiddleName, [string]$RightName,
[int]$LeftRing, [int]$MiddleRing, [int]$RightRing,
[char]$LeftStart, [char]$MiddleStart, [char]$RightStart,
[string]$GreekName, $GreekRing, $GreekStart,
[string]$Reflector, [hashtable]$Plugboard
)
$lines = New-Object System.Collections.Generic.List[string]
$lines.Add("=== ENIGMA SESSION ===")
$lines.Add("Model: $Model")
$lines.Add("LeftRotor: $LeftName")
$lines.Add("MiddleRotor: $MiddleName")
$lines.Add("RightRotor: $RightName")
$lines.Add("LeftRing: $LeftRing")
$lines.Add("MiddleRing: $MiddleRing")
$lines.Add("RightRing: $RightRing")
$lines.Add("LeftStart: $LeftStart")
$lines.Add("MiddleStart: $MiddleStart")
$lines.Add("RightStart: $RightStart")
if ($Model -eq "M4") {
$lines.Add("GreekRotor: $GreekName")
$lines.Add("GreekRing: $GreekRing")
$lines.Add("GreekStart: $GreekStart")
}
$lines.Add("Reflector: $Reflector")
$plugText = "(none)"
if ($Plugboard.Count -gt 0) {
$pairs = $Plugboard.GetEnumerator() | Where-Object { $_.Key -lt $_.Value } | ForEach-Object { "$($_.Key)$($_.Value)" }
$plugText = $pairs -join " "
}
$lines.Add("Plugboard: $plugText")
$lines.Add("=== MESSAGES ===")
Set-Content -Path $Path -Value $lines -Encoding UTF8
}
function Add-SessionMessage {
param([string]$Path, [string]$Prepared, [string]$Output, [string]$Grouped)
$stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$lines = @(
"[$stamp] PREPARED: $Prepared",
"[$stamp] OUTPUT : $Output",
"[$stamp] GROUPED : $Grouped",
""
)
Add-Content -Path $Path -Value $lines -Encoding UTF8
}
function Read-SessionFile {
param([string]$Path)
$content = Get-Content -Path $Path -Encoding UTF8
$settings = @{}
$messages = New-Object System.Collections.Generic.List[string]
$inMessages = $false
foreach ($line in $content) {
if ($line -eq "=== MESSAGES ===") { $inMessages = $true; continue }
if ($line -eq "=== ENIGMA SESSION ===") { continue }
if ($inMessages) {
if (-not [string]::IsNullOrWhiteSpace($line)) { $messages.Add($line) }
} elseif ($line -match "^([A-Za-z]+):\s*(.*)$") {
$settings[$Matches[1]] = $Matches[2].Trim()
}
}
return [PSCustomObject]@{
Settings = $settings
Messages = $messages
}
}
# --- Main ---
Write-Host "=== Enigma Machine Simulator ==="
Write-Host "(Wehrmacht Enigma I / M3, or 4-rotor Kriegsmarine Naval Enigma M4)"
Write-Host ""
$ScriptDir = $PSScriptRoot
if ([string]::IsNullOrEmpty($ScriptDir) -and $MyInvocation.MyCommand.Path) {
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
}
if ([string]::IsNullOrEmpty($ScriptDir)) { $ScriptDir = (Get-Location).Path }
$SessionFilePath = Join-Path $ScriptDir "Encrypted Text Document.txt"
$resumed = $false
if (Test-Path $SessionFilePath) {
Write-Host "Found a previous session file next to the script:"
Write-Host " $SessionFilePath"
$answer = Read-Host "Load its settings and continue that session? (Y/N)"
if ($answer -eq "Y" -or $answer -eq "y") {
$session = Read-SessionFile -Path $SessionFilePath
$s = $session.Settings
$model = $s["Model"]
$leftName = $s["LeftRotor"]
$middleName = $s["MiddleRotor"]
$rightName = $s["RightRotor"]
$leftRing = [int]$s["LeftRing"]
$middleRing = [int]$s["MiddleRing"]
$rightRing = [int]$s["RightRing"]
$leftStart = [char]$s["LeftStart"]
$middleStart = [char]$s["MiddleStart"]
$rightStart = [char]$s["RightStart"]
$greekName = $null
$greekRing = $null
$greekStart = $null
if ($model -eq "M4") {
$greekName = $s["GreekRotor"]
$greekRing = [int]$s["GreekRing"]
$greekStart = [char]$s["GreekStart"]
}
$reflectorChoice = $s["Reflector"]
$plugboard = @{}
$plugRaw = $s["Plugboard"]
if ($plugRaw -and $plugRaw -ne "(none)") {
foreach ($pair in ($plugRaw -split '\s+')) {
if ($pair.Length -eq 2) {
$plugboard[$pair[0]] = $pair[1]
$plugboard[$pair[1]] = $pair[0]
}
}
}
$resumed = $true
Write-Host ""
Write-Host "Settings restored from the session file."
} else {
Write-Host "Starting a new session (the old file will be overwritten once configured)."
}
Write-Host ""
}
if (-not $resumed) {
$model = $null
do {
$raw = (Read-Host "Machine model (M3 = 3-rotor / M4 = 4-rotor naval)").ToUpperInvariant()
if ($raw -eq "M3" -or $raw -eq "M4") { $model = $raw }
else { Write-Host "Invalid choice, enter M3 or M4." }
} while (-not $model)
if ($model -eq "M4") {
$rotorPool = @("I", "II", "III", "IV", "V", "VI", "VII", "VIII")
} else {
$rotorPool = @("I", "II", "III", "IV", "V")
}
$leftName = Read-RotorChoice -Label "Left (slowest)" -ValidNames $rotorPool -Exclude @()
$middleName = Read-RotorChoice -Label "Middle" -ValidNames $rotorPool -Exclude @($leftName)
$rightName = Read-RotorChoice -Label "Right (fastest)" -ValidNames $rotorPool -Exclude @($leftName, $middleName)
$leftRing = Read-RingSetting -Label "Left rotor"
$middleRing = Read-RingSetting -Label "Middle rotor"
$rightRing = Read-RingSetting -Label "Right rotor"
$leftStart = Read-StartPosition -Label "Left rotor"
$middleStart = Read-StartPosition -Label "Middle rotor"
$rightStart = Read-StartPosition -Label "Right rotor"
$greekName = $null
$greekRing = $null
$greekStart = $null
if ($model -eq "M4") {
$greekName = Read-GreekChoice
$greekRing = Read-RingSetting -Label "Greek (4th) rotor"
$greekStart = Read-StartPosition -Label "Greek (4th) rotor"
}
$reflectorPool = @("B", "C")
if ($model -eq "M4") { $reflectorPool = @("B-THIN", "C-THIN") }
$reflectorChoice = $null
do {
$optionsText = $reflectorPool -join " / "
$raw = (Read-Host "Reflector ($optionsText)").ToUpperInvariant()
if ($reflectorPool -contains $raw) { $reflectorChoice = $raw }
else { Write-Host "Invalid reflector, choose $optionsText." }
} while (-not $reflectorChoice)
$plugboard = Read-Plugboard
}
Write-Host ""
Write-Host "--- Machine configuration ---"
Write-Host "Model : $model"
Write-Host "Rotors (L-M-R): $leftName-$middleName-$rightName"
Write-Host "Ring settings : $leftRing-$middleRing-$rightRing"
Write-Host "Start position: $leftStart$middleStart$rightStart"
if ($model -eq "M4") {
Write-Host "Greek rotor : $greekName (ring $greekRing, start $greekStart)"
}
Write-Host "Reflector : $reflectorChoice"
$plugText = "(none)"
if ($plugboard.Count -gt 0) {
$pairs = $plugboard.GetEnumerator() | Where-Object { $_.Key -lt $_.Value } | ForEach-Object { "$($_.Key)$($_.Value)" }
$plugText = $pairs -join " "
}
Write-Host "Plugboard : $plugText"
Write-Host ""
Write-Host "NOTE: to decrypt later, start a fresh run with the exact same"
Write-Host "model, rotor order, ring settings, start position, Greek rotor"
Write-Host "(if M4) and plugboard pairs, then feed it the ciphertext. Enigma"
Write-Host "is reciprocal: identical settings that encrypt will also decrypt."
Write-Host "Session file (settings + ciphertext log) is saved next to this"
Write-Host "script at: $SessionFilePath"
Write-Host ""
$Left = New-Rotor -Name $leftName -RingSetting $leftRing -StartPosition $leftStart
$Middle = New-Rotor -Name $middleName -RingSetting $middleRing -StartPosition $middleStart
$Right = New-Rotor -Name $rightName -RingSetting $rightRing -StartPosition $rightStart
$Greek = $null
if ($model -eq "M4") {
$Greek = New-GreekRotor -Name $greekName -RingSetting $greekRing -StartPosition $greekStart
}
if (-not $resumed) {
Save-SessionSettings -Path $SessionFilePath -Model $model `
-LeftName $leftName -MiddleName $middleName -RightName $rightName `
-LeftRing $leftRing -MiddleRing $middleRing -RightRing $rightRing `
-LeftStart $leftStart -MiddleStart $middleStart -RightStart $rightStart `
-GreekName $greekName -GreekRing $greekRing -GreekStart $greekStart `
-Reflector $reflectorChoice -Plugboard $plugboard
} elseif ($session.Messages.Count -gt 0) {
Write-Host "--- Ciphertext from the previous session ---"
foreach ($m in $session.Messages) { Write-Host $m }
Write-Host ""
}
if ($InputFile) {
if (-not (Test-Path $InputFile)) {
Write-Host "Input file not found: $InputFile"
Read-Host "`nPress ENTER to exit."
exit
}
if (-not $OutputFile) {
$dir = Split-Path -Parent $InputFile
$base = [System.IO.Path]::GetFileNameWithoutExtension($InputFile)
$OutputFile = Join-Path $dir "$base`_enigma.txt"
}
Write-Host "Reading input file: $InputFile"
$rawText = Get-Content -Path $InputFile -Raw -Encoding UTF8
Write-Host "Source length: $($rawText.Length) characters. Processing..."
Write-Host ""
$result = Invoke-EnigmaText -Left $Left -Middle $Middle -Right $Right -Greek $Greek -ReflectorWiring $ReflectorDefs[$reflectorChoice] -Plugboard $plugboard -Text $rawText -ShowProgress
$groupedOutput = Format-Grouped -Text $result.Output -GroupSize 5
$dir = Split-Path -Parent $OutputFile
$base = [System.IO.Path]::GetFileNameWithoutExtension($OutputFile)
$preparedPath = Join-Path $dir "$base`_prepared.txt"
$groupedPath = Join-Path $dir "$base`_grouped.txt"
Set-Content -Path $OutputFile -Value $result.Output -Encoding UTF8
Set-Content -Path $preparedPath -Value $result.Clean -Encoding UTF8
Set-Content -Path $groupedPath -Value $groupedOutput -Encoding UTF8
Add-SessionMessage -Path $SessionFilePath -Prepared $result.Clean -Output $result.Output -Grouped $groupedOutput
Write-Host "Done. $($result.Clean.Length) letters processed."
Write-Host "Continuous output : $OutputFile"
Write-Host "Prepared text : $preparedPath"
Write-Host "Grouped output : $groupedPath"
Write-Host ""
Read-Host "`nPress ENTER to exit."
exit
}
Write-Host "TIP: digits are auto-converted to spoken words (2 -> ZWO, 5 -> FUENF...)."
Write-Host "TIP: wrap codes in brackets to spell them out, e.g. [HX-2E] becomes"
Write-Host " HEINRICH XANTHIPPE ZWO EMIL before encryption."
Write-Host "TIP: for very large texts, re-run with -InputFile / -OutputFile"
Write-Host " instead of pasting into the console (avoids paste truncation)."
Write-Host ""
while ($true) {
Write-Host "Text to process - paste one or several lines (blank lines inside are fine)."
Write-Host "Type END on its own line when finished. Press ENTER on an empty first line to exit."
$firstLine = Read-Host
if ([string]::IsNullOrEmpty($firstLine)) { break }
# Read-Host only ever returns ONE line. A multi-line paste is delivered
# to the console as that many separate Enter-terminated lines, so we
# keep calling Read-Host until the user (or the pasted block itself)
# supplies the END sentinel. This is what lets a long, multi-paragraph
# message like a full Funkspruch be pasted safely without truncation.
#
# If the clipboard content has no trailing newline after its last line,
# the END you type afterward lands glued onto that same line (e.g.
# "Gluck ab! END") instead of on its own line. The regex below still
# recognizes END as a whole word at the end of the line in that case,
# keeps whatever text came before it, and stops waiting.
$lines = New-Object System.Collections.Generic.List[string]
$lines.Add($firstLine)
$stillReading = $true
while ($stillReading) {
$line = Read-Host
if ($line -eq "END") { break }
if ($line -match '^(?<content>.*?)\s*\bEND\b\s*$') {
$before = $Matches["content"]
if (-not [string]::IsNullOrEmpty($before)) { $lines.Add($before) }
$stillReading = $false
} else {
$lines.Add($line)
}
}
$text = $lines -join " "
try {
$result = Invoke-EnigmaText -Left $Left -Middle $Middle -Right $Right -Greek $Greek -ReflectorWiring $ReflectorDefs[$reflectorChoice] -Plugboard $plugboard -Text $text -ShowProgress:($text.Length -gt 2000)
$groupedResult = Format-Grouped -Text $result.Output -GroupSize 5
Write-Host "Prepared text : $($result.Clean)"
Write-Host "Result (continuous): $($result.Output)"
Write-Host "Result (grouped) : $groupedResult"
Write-Host ""
Add-SessionMessage -Path $SessionFilePath -Prepared $result.Clean -Output $result.Output -Grouped $groupedResult
} catch {
Write-Host ""
Write-Host "ERROR while processing this message: $($_.Exception.Message)"
Write-Host "Nothing was saved for this message. You can try again below."
Write-Host ""
}
}
Read-Host "`nPress ENTER to exit."
ÖRNEK BİR KOMUT ÇIKTISI YAPALIM (BASİT SEVİYE METİN OLSUN) :
METİN :
Bir zamanlar sordum forumda bir TRWE_2012 varmış...Çok aktif bir kullanıcıymış ...Forumda durmadan oradan oraya zıplar dururmuş tavşan misali...Bazen de forumdan yok olurmuş, nerede olduğu bilinmezmiş dengesiz...!
Şimdi betiği yönetici olarak çalıştıralım :
Machine model (M3 = 3-rotor / M4 = 4-rotor naval): (ROTOR=Dişli Çark Modelini belirliyoruz) = M3 (basit model)
Left (slowest) rotor (I / II / III / IV / V): (Sol Taraf Dişli Seviye , yani birim dakika kaç tık atacak?) = I
Middle rotor (I / II / III / IV / V): (Orta Dişli Seviye , yani birim dakika kaç tık atacak?) = II
Right (fastest) rotor (I / II / III / IV / V) : (Sağ Dişli Seviye, yani birim dakika kaç tık atacak?) = III
Left rotor ring setting (1-26): (Dişli dönüş seviyesi , yani tek seferde kaç dişliyi eş zamanlı döndürecek?) = 11
Middle rotor ring setting (1-26): 13
Right rotor ring setting (1-26): 15
Left rotor start position (A-Z): (Şifreleme yönü neresi? A-Z'ye , Z-A'ya? ) = A (A'dan Z'ye)
Middle rotor start position (A-Z):Z (A-Z'ye, ardından Z'den A'ya)
Right rotor start position (A-Z): A (A-Z'ye, ardından Z'den A'ya , tekrar A'dan Z'ye )
Reflector (B / C): (Yönlendirme Tablosu? ) = B
Plugboard setup (Steckerbrett): enter letter pairs, e.g. AB then CD.
Leave blank and press ENTER when done (max 10 pairs).
Pair 1: (BİLETLER) <BOŞ BIRAKIN> MAKİNE KENDİSİ OTOMATİK BELİRSİN...
--- Machine configuration ---
Model : M3
Rotors (L-M-R): I-II-III
Ring settings : 11-13-15
Start position: AZA
Reflector : B
Plugboard : (none)
NOTE: to decrypt later, start a fresh run with the exact same
model, rotor order, ring settings, start position, Greek rotor
(if M4) and plugboard pairs, then feed it the ciphertext. Enigma
is reciprocal: identical settings that encrypt will also decrypt.
Session file (settings + ciphertext log) is saved next to this
script at: C:\Users\TRWE_2012\Masaüstü\Encrypted Text Document.txt
TIP: digits are auto-converted to spoken words (2 -> ZWO, 5 -> FUENF...).
TIP: wrap codes in brackets to spell them out, e.g. [HX-2E] becomes
HEINRICH XANTHIPPE ZWO EMIL before encryption.
TIP: for very large texts, re-run with -InputFile / -OutputFile
instead of pasting into the console (avoids paste truncation).
Text to process - paste one or several lines (blank lines inside are fine).
Type END on its own line when finished. Press ENTER on an empty first line to exit. (ENTER) İLE ALT TARAFTAKİ BOŞLUĞA METNİ YAZIN
Bir zamanlar sordum forumda bir TRWE_2012 varmış...Çok aktif bir kullanıcıymış ...Forumda durmadan oradan oraya zıplar dururmuş tavşan misali...Bazen de forumdan yok olurmuş, nerede olduğu bilinmezmiş dengesiz...!
END (SONA END EKLİYORUZ VE KLAVYE'DEN ENTER TUŞUNA BASIYORUZ)
SONUÇ :
Prepared text : BIRZAMANLARSORDUMFORUMDABIRTRWEZWONULLEINSZWOVARMISCOKAKTIFBIRKULLANICIYMISFORUMDADURMADANORADANORAYAZIPLARDURURMUSTAVSANMISALIBAZENDEFORUMDANYOKOLURMUSNEREDEOLDUGUBILINMEZMISDENGESIZ
Result (continuous): UEGQWIHVGXLLGCPOHGCQONNMXXFFXVRELLEOKQAKWGAHXEKCXWQUZQWNBPNEKHMMTGQIJBKGNYVKSIHYJGLLMYWXOVYBNYIMWTCRGJFXYQSPHCTBFLCYSJBSWXLUNHAYDKYSOXKKEPCREZQTNIBZEJXCSKGRRIWQBPOLPUTJOGHAPPDRWFVAOLQ
Result (grouped) : UEGQW IHVGX LLGCP OHGCQ ONNMX XFFXV RELLE OKQAK WGAHX EKCXW QUZQW NBPNE KHMMT GQIJB KGNYV KSIHY JGLLM YWXOV YBNYI MWTCR GJFXY QSPHC TBFLC YSJBS WXLUN HAYDK YSOXK KEPCR EZQTN IBZEJ XCSKG RRIWQ BPOLP UTJOG HAPPD RWFVA OLQ
Text to process - paste one or several lines (blank lines inside are fine).
Type END on its own line when finished. Press ENTER on an empty first line to exit.
BURADA :
Result (continuous): ====>>ŞİFRELİ METİN
Result (grouped) : =====>>> 5'li GRUPLANDIRIMIŞ VERSİYON
Prepared text : YUKARIDAKİ METNİN BOŞLUKSUZ HALİ....
Hepsini toparlarsak :
Kod: Tümünü seç
=== Enigma Machine Simulator ===
(Wehrmacht Enigma I / M3, or 4-rotor Kriegsmarine Naval Enigma M4)
Machine model (M3 = 3-rotor / M4 = 4-rotor naval): M3
Left (slowest) rotor (I / II / III / IV / V): I
Middle rotor (I / II / III / IV / V): II
Right (fastest) rotor (I / II / III / IV / V): III
Left rotor ring setting (1-26): 11
Middle rotor ring setting (1-26): 13
Right rotor ring setting (1-26): 15
Left rotor start position (A-Z): A
Middle rotor start position (A-Z): Z
Right rotor start position (A-Z): A
Reflector (B / C): B
Plugboard setup (Steckerbrett): enter letter pairs, e.g. AB then CD.
Leave blank and press ENTER when done (max 10 pairs).
Pair 1:
--- Machine configuration ---
Model : M3
Rotors (L-M-R): I-II-III
Ring settings : 11-13-15
Start position: AZA
Reflector : B
Plugboard : (none)
NOTE: to decrypt later, start a fresh run with the exact same
model, rotor order, ring settings, start position, Greek rotor
(if M4) and plugboard pairs, then feed it the ciphertext. Enigma
is reciprocal: identical settings that encrypt will also decrypt.
Session file (settings + ciphertext log) is saved next to this
script at: C:\Users\TRWE_2012\Masaüstü\Encrypted Text Document.txt
TIP: digits are auto-converted to spoken words (2 -> ZWO, 5 -> FUENF...).
TIP: wrap codes in brackets to spell them out, e.g. [HX-2E] becomes
HEINRICH XANTHIPPE ZWO EMIL before encryption.
TIP: for very large texts, re-run with -InputFile / -OutputFile
instead of pasting into the console (avoids paste truncation).
Text to process - paste one or several lines (blank lines inside are fine).
Type END on its own line when finished. Press ENTER on an empty first line to exit.
Bir zamanlar sordum forumda bir TRWE_2012 varmış...Çok aktif bir kullanıcıymış ...Forumda durmadan oradan oraya zıplar dururmuş tavşan misali...Bazen de forumdan yok olurmuş, nerede olduğu bilinmezmiş dengesiz...!
END
Prepared text : BIRZAMANLARSORDUMFORUMDABIRTRWEZWONULLEINSZWOVARMISCOKAKTIFBIRKULLANICIYMISFORUMDADURMADANORADANORAYAZIPLARDURURMUSTAVSANMISALIBAZENDEFORUMDANYOKOLURMUSNEREDEOLDUGUBILINMEZMISDENGESIZ
Result (continuous): UEGQWIHVGXLLGCPOHGCQONNMXXFFXVRELLEOKQAKWGAHXEKCXWQUZQWNBPNEKHMMTGQIJBKGNYVKSIHYJGLLMYWXOVYBNYIMWTCRGJFXYQSPHCTBFLCYSJBSWXLUNHAYDKYSOXKKEPCREZQTNIBZEJXCSKGRRIWQBPOLPUTJOGHAPPDRWFVAOLQ
Result (grouped) : UEGQW IHVGX LLGCP OHGCQ ONNMX XFFXV RELLE OKQAK WGAHX EKCXW QUZQW NBPNE KHMMT GQIJB KGNYV KSIHY JGLLM YWXOV YBNYI MWTCR GJFXY QSPHC TBFLC YSJBS WXLUN HAYDK YSOXK KEPCR EZQTN IBZEJ XCSKG RRIWQ BPOLP UTJOG HAPPD RWFVA OLQ
Text to process - paste one or several lines (blank lines inside are fine).
Type END on its own line when finished. Press ENTER on an empty first line to exit.
Betiğin çalıştırıldığı konumda "C:\Users\TRWE_2012\Masaüstü\Encrypted Text Document.txt" belgesi oluşuyor.Burada kullanıcının makine ayarları ve şifreli metni duruyor.
C:\Users\TRWE_2012\Masaüstü\Encrypted Text Document.txt İçeriği :
Kod: Tümünü seç
=== ENIGMA SESSION ===
Model: M3
LeftRotor: I
MiddleRotor: II
RightRotor: III
LeftRing: 11
MiddleRing: 13
RightRing: 15
LeftStart: A
MiddleStart: Z
RightStart: A
Reflector: B
Plugboard: (none)
=== MESSAGES ===
[2026-07-20 14:47:00] PREPARED: BIRZAMANLARSORDUMFORUMDABIRTRWEZWONULLEINSZWOVARMISCOKAKTIFBIRKULLANICIYMISFORUMDADURMADANORADANORAYAZIPLARDURURMUSTAVSANMISALIBAZENDEFORUMDANYOKOLURMUSNEREDEOLDUGUBILINMEZMISDENGESIZ
[2026-07-20 14:47:00] OUTPUT : UEGQWIHVGXLLGCPOHGCQONNMXXFFXVRELLEOKQAKWGAHXEKCXWQUZQWNBPNEKHMMTGQIJBKGNYVKSIHYJGLLMYWXOVYBNYIMWTCRGJFXYQSPHCTBFLCYSJBSWXLUNHAYDKYSOXKKEPCREZQTNIBZEJXCSKGRRIWQBPOLPUTJOGHAPPDRWFVAOLQ
[2026-07-20 14:47:00] GROUPED : UEGQW IHVGX LLGCP OHGCQ ONNMX XFFXV RELLE OKQAK WGAHX EKCXW QUZQW NBPNE KHMMT GQIJB KGNYV KSIHY JGLLM YWXOV YBNYI MWTCR GJFXY QSPHC TBFLC YSJBS WXLUN HAYDK YSOXK KEPCR EZQTN IBZEJ XCSKG RRIWQ BPOLP UTJOG HAPPD RWFVA OLQ
Betiği ikinci kez çalıştırısanız...
=== Enigma Machine Simulator ===
(Wehrmacht Enigma I / M3, or 4-rotor Kriegsmarine Naval Enigma M4)
Found a previous session file next to the script:
C:\Users\TRWE_2012\Masaüstü\Encrypted Text Document.txt
Load its settings and continue that session? (Y/N): Y (YANİ DOSYAYI BULDUM AÇAYIM DİYOR BETİK SİZE, SİZDE AÇ DİYORSUNUZ)
SONUÇ :
Kod: Tümünü seç
=== Enigma Machine Simulator ===
(Wehrmacht Enigma I / M3, or 4-rotor Kriegsmarine Naval Enigma M4)
Found a previous session file next to the script:
C:\Users\TRWE_2012\Masaüstü\Encrypted Text Document.txt
Load its settings and continue that session? (Y/N): Y
Settings restored from the session file.
--- Machine configuration ---
Model : M3
Rotors (L-M-R): I-II-III
Ring settings : 11-13-15
Start position: AZA
Reflector : B
Plugboard : (none)
NOTE: to decrypt later, start a fresh run with the exact same
model, rotor order, ring settings, start position, Greek rotor
(if M4) and plugboard pairs, then feed it the ciphertext. Enigma
is reciprocal: identical settings that encrypt will also decrypt.
Session file (settings + ciphertext log) is saved next to this
script at: C:\Users\TRWE_2012\Masaüstü\Encrypted Text Document.txt
--- Ciphertext from the previous session ---
[2026-07-20 14:47:00] PREPARED: BIRZAMANLARSORDUMFORUMDABIRTRWEZWONULLEINSZWOVARMISCOKAKTIFBIRKULLANICIYMISFORUMDADURMADANORADANORAYAZIPLARDURURMUSTAVSANMISALIBAZENDEFORUMDANYOKOLURMUSNEREDEOLDUGUBILINMEZMISDENGESIZ
[2026-07-20 14:47:00] OUTPUT : UEGQWIHVGXLLGCPOHGCQONNMXXFFXVRELLEOKQAKWGAHXEKCXWQUZQWNBPNEKHMMTGQIJBKGNYVKSIHYJGLLMYWXOVYBNYIMWTCRGJFXYQSPHCTBFLCYSJBSWXLUNHAYDKYSOXKKEPCREZQTNIBZEJXCSKGRRIWQBPOLPUTJOGHAPPDRWFVAOLQ
[2026-07-20 14:47:00] GROUPED : UEGQW IHVGX LLGCP OHGCQ ONNMX XFFXV RELLE OKQAK WGAHX EKCXW QUZQW NBPNE KHMMT GQIJB KGNYV KSIHY JGLLM YWXOV YBNYI MWTCR GJFXY QSPHC TBFLC YSJBS WXLUN HAYDK YSOXK KEPCR EZQTN IBZEJ XCSKG RRIWQ BPOLP UTJOG HAPPD RWFVA OLQ
TIP: digits are auto-converted to spoken words (2 -> ZWO, 5 -> FUENF...).
TIP: wrap codes in brackets to spell them out, e.g. [HX-2E] becomes
HEINRICH XANTHIPPE ZWO EMIL before encryption.
TIP: for very large texts, re-run with -InputFile / -OutputFile
instead of pasting into the console (avoids paste truncation).
Text to process - paste one or several lines (blank lines inside are fine).
Type END on its own line when finished. Press ENTER on an empty first line to exit.
Ancak bu kadar benzetebildim gerçek Enigmaya....
Bu Video'yu da İzleyin Mantığını Anlamak İçin: