Jump to content

Enigma


Andreik
 Share

Recommended Posts

I made a simple Enigma machine like those used in WWII. It's made after a design of Enigma I with a set of 3 reflectors (A,B,C) and a set of 5 rotors (I,II,III,IV,V). How it works?

  • Set a reflector (by default is set Reflector A) from a set of 3 reflectors.
  • Set 3 rotors (by default are set I,II,III) from a set of 5 rotors. Since it's not a physical machine you can use the same rotor multiple times (ex. I,I,I).
  • Set a sequence of three letters (by default AAA) as starting position for each rotor.
  • Optionally you can set multiple sequences of pairings in the plug board. Each pair must be created from unique letters that are not used in another pair.
  • Use left mouse on the Enigma keyboard (2nd grid of letters) to press letter that you want to encrypt. For each press an encrypted letter will be produced and indicated in Enigma lamps matrix (first grid of letters). For the record in the right panels will be displayed the message and the encrypted message.

To decrypt a message you need to reset the machine and then set the machine with the settings used to encrypt the message and then press the letters of encrypted message.

To set reflector, rotors, keys, pairings or to reset the machine use the menu buttons from the left side.

#include-once
#include <AutoItObject.au3>
#include <GDIPlus.au3>

Global $sFont = 'Segoe UI'
Global $hMain, $PrevLampOn = Null, $cReflector, $cReflectorLabel, $cMessage, $cEncryptedMessage
Global $oEnigma, $oKeyboard, $oPlugboard, $oRightRotor, $oMiddleRotor, $oLeftRotor, $oReflector
Global $cSetReflector, $cSetRotors, $cSetKeys, $cSetPairs, $cReset
Global $aRotor[3], $aRotorLabel[3], $aLamp[26], $aKeyboard[26], $aPlugboard[26]
Global $aPlugboardPallete[13] = [0xFF004B23, 0xFF00DEAD, 0xFFFF4800, 0xFFFFAFCC, 0xFF9D0208, 0xFFD4A373, 0xFF6B705C, 0xFF8338EC, 0xFFEE6C4D, 0xFF219EBC, 0xFF8AC926, 0xFF723D46, 0xFFFFD500]
Global $sKeyLayout = 'QWERTZUIOASDFGHJKPYXCVBNML'

_AutoItObject_Startup()
_GDIPlus_Startup()
Global $hBitmap = _GDIPlus_BitmapCreateFromScan0(50, 50)
Global $hBitmap2 = _GDIPlus_BitmapCreateFromScan0(50, 90)
Global $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap)
Global $hGraphic2 = _GDIPlus_ImageGetGraphicsContext($hBitmap2)
Global $hFormat = _GDIPlus_StringFormatCreate()
Global $hFamily = _GDIPlus_FontFamilyCreate($sFont)
Global $hFont = _GDIPlus_FontCreate($hFamily, 18, 1)
Global $hBrush1 = _GDIPlus_BrushCreateSolid(0xFF404040)
Global $hBrush2 = _GDIPlus_BrushCreateSolid(0xFFC0C0C0)
Global $hBrush3 = _GDIPlus_BrushCreateSolid(0xFFA08000)
Global $hBrush4 = _GDIPlus_BrushCreateSolid(0xFF000000)
Global $tLayout = _GDIPlus_RectFCreate(10, 10, 30, 30)
Global $tLayout2 = _GDIPlus_RectFCreate(10, 10, 30, 70)
_GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2)
_GDIPlus_GraphicsSetInterpolationMode($hGraphic, 2)
_GDIPlus_GraphicsSetSmoothingMode($hGraphic2, 2)
_GDIPlus_GraphicsSetInterpolationMode($hGraphic2, 2)
_GDIPlus_StringFormatSetAlign($hFormat, 1)
_GDIPlus_StringFormatSetLineAlign($hFormat, 1)

$hMain = GUICreate('Enigma', 1500, 1000)
GUISetBkColor(0x404040, $hMain)
DrawMenu()
GUISetState(@SW_SHOW, $hMain)

ResetEnigma()

While True
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $cSetReflector
            $sInput = InputBox('Set reflector', 'Select reflector:' & @CRLF & 'Type A for UKW-A' & @CRLF & 'Type B for UKW-B' & @CRLF & 'Type C for UKW-C', 'A')
            If $sInput = 'A' Or $sInput = 'B' Or $sInput = 'C' Then
                $oEnigma.Reflector.Set(StringUpper($sInput))
                GUICtrlSetData($cReflectorLabel, StringUpper($sInput))
            EndIf
        Case $cSetRotors
            $sInput = InputBox('Set rotors', 'Select rotors:' & @CRLF & 'There are five rotors indexed with roman numerals. You have to type a sequence of three indices delimited by comma.', 'I,II,III')
            If $sInput Then
                Local $aSplit = StringSplit($sInput, ',')
                If $aSplit[0] = 3 Then
                    If ValidRomanNumeral($aSplit[1]) And ValidRomanNumeral($aSplit[2]) And ValidRomanNumeral($aSplit[3]) Then
                        $oLeftRotor.Set(StringUpper($aSplit[1]))
                        $oMiddleRotor.Set(StringUpper($aSplit[2]))
                        $oRightRotor.Set(StringUpper($aSplit[3]))
                        GUICtrlSetData($aRotorLabel[0], StringUpper($aSplit[1]))
                        GUICtrlSetData($aRotorLabel[1], StringUpper($aSplit[2]))
                        GUICtrlSetData($aRotorLabel[2], StringUpper($aSplit[3]))
                    EndIf
                EndIf
            EndIf
        Case $cSetKeys
            $sInput = InputBox('Set keys', 'Select keys:' & @CRLF & 'Type a sequence of three letters as starting position for each rotor.', 'AAA')
            If StringLen($sInput) = 3 And StringRegExp($sInput, '[a-zA-Z]{3}', 0) Then
                $oEnigma.SetKey(StringUpper($sInput))
                GUICtrlSetData($aRotor[0], StringUpper(StringMid($sInput, 1, 1)))
                GUICtrlSetData($aRotor[1], StringUpper(StringMid($sInput, 2, 1)))
                GUICtrlSetData($aRotor[2], StringUpper(StringMid($sInput, 3, 1)))
            EndIf
        Case $cSetPairs
            $sInput = InputBox('Set pairs', 'Select plugboard pairs:' & @CRLF & 'Type sequences of two letters that will be connected to plugboard', 'AB CD EF')
            If StringLen($sInput) Then
                Local $aPairs = StringSplit($sInput, ' ')
                If ValidatePairs($aPairs) Then SetAndDrawPairs($aPairs)
            EndIf
        Case $cReset
            ResetEnigma()
        Case $aKeyboard[0] To $aKeyboard[25]
            $sLetter = StringMid($sKeyLayout, ($nMsg - $aKeyboard[0]) + 1, 1)
            $sEncrypted = $oEnigma.Encrypt($sLetter)
            GUICtrlSetData($cEncryptedMessage, GUICtrlRead($cEncryptedMessage) & $sEncrypted)
            GUICtrlSetData($cMessage, GUICtrlRead($cMessage) & $sLetter)
            LampOn($sEncrypted)
            GUICtrlSetData($aRotor[0], StringLeft($oEnigma.LeftRotor.Left, 1))
            GUICtrlSetData($aRotor[1], StringLeft($oEnigma.MiddleRotor.Left, 1))
            GUICtrlSetData($aRotor[2], StringLeft($oEnigma.RightRotor.Left, 1))
        Case -3
            ExitLoop
    EndSwitch
    Sleep(10)
WEnd

_GDIPlus_BrushDispose($hBrush1)
_GDIPlus_BrushDispose($hBrush2)
_GDIPlus_BrushDispose($hBrush3)
_GDIPlus_BrushDispose($hBrush4)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_GraphicsDispose($hGraphic2)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_BitmapDispose($hBitmap2)
_GDIPlus_Shutdown()
_AutoItObject_Shutdown()

Func ResetEnigma()
    GUICtrlSetData($cEncryptedMessage, '')
    GUICtrlSetData($cMessage, '')
    For $Index = 0 To 2
        GUICtrlDelete($aRotor[$Index])
        GUICtrlDelete($aRotorLabel[$Index])
    Next
    For $Index = 0 To 25
        GUICtrlDelete($aKeyboard[$Index])
        GUICtrlDelete($aLamp[$Index])
        GUICtrlDelete($aPlugboard[$Index])
    Next
    DrawRotors()
    DrawLKP('L')
    DrawLKP('K')
    DrawLKP('P')
    $oEnigma = Enigma()
    $oKeyboard = Keyboard()
    $oPlugboard = Plugboard()
    $oRightRotor = Rotor()
    $oMiddleRotor = Rotor()
    $oLeftRotor = Rotor()
    $oReflector = Reflector()
    $oLeftRotor.Set('I')
    $oMiddleRotor.Set('II')
    $oRightRotor.Set('III')
    $oReflector.Set('A')
    $oEnigma.Set($oKeyboard, $oPlugboard, $oRightRotor, $oMiddleRotor, $oLeftRotor, $oReflector)
    $oEnigma.SetKey('AAA')
    GUICtrlSetData($aRotor[0], 'A')
    GUICtrlSetData($aRotor[1], 'A')
    GUICtrlSetData($aRotor[2], 'A')
    GUICtrlSetData($aRotorLabel[0], 'I')
    GUICtrlSetData($aRotorLabel[1], 'II')
    GUICtrlSetData($aRotorLabel[2], 'III')
    GUICtrlSetData($cReflectorLabel, 'A')
    DrawRotors()
EndFunc

Func DrawMenu()
    $cEncryptedMessage = GUICtrlCreateEdit('', 1100, 150, 370, 200, 0x00200800)
    $cMessage = GUICtrlCreateEdit('', 1100, 420, 370, 200, 0x00200800)
    $cSetReflector = GUICtrlCreateButton('Reflector', 10, 10, 100, 40)
    $cSetRotors = GUICtrlCreateButton('Rotors', 10, 60, 100, 40)
    $cSetKeys = GUICtrlCreateButton('Keys', 10, 110, 100, 40)
    $cSetPairs = GUICtrlCreateButton('Pairs', 10, 160, 100, 40)
    $cReset = GUICtrlCreateButton('Reset', 10, 210, 100, 40)
    GUICtrlSetFont($cSetReflector, 12, 500, 0, $sFont)
    GUICtrlSetFont($cSetRotors, 12, 500, 0, $sFont)
    GUICtrlSetFont($cSetKeys, 12, 500, 0, $sFont)
    GUICtrlSetFont($cSetPairs, 12, 500, 0, $sFont)
    GUICtrlSetFont($cReset, 12, 500, 0, $sFont)
    GUICtrlSetFont($cEncryptedMessage, 14, 600, 0, $sFont)
    GUICtrlSetFont($cMessage, 14, 600, 0, $sFont)
    GUICtrlSetColor($cEncryptedMessage, 0xC0C0C0)
    GUICtrlSetBkColor($cEncryptedMessage, 0x404040)
    GUICtrlSetColor($cMessage, 0xC0C0C0)
    GUICtrlSetBkColor($cMessage, 0x404040)
EndFunc

Func DrawRotors()
    $cReflector = GUICtrlCreateLabel('Reflector', 320, 20, 200, 50, 0x201)
    $cReflectorLabel = GUICtrlCreateLabel('A', 320, 80, 200, 30, 0x201)
    GUICtrlSetBkColor($cReflector, 0xC0C0C0)
    GUICtrlSetColor($cReflector, 0x404040)
    GUICtrlSetFont($cReflector, 30, 600, 0, $sFont)
    GUICtrlSetColor($cReflectorLabel, 0xC0C0C0)
    GUICtrlSetFont($cReflectorLabel, 18, 600, 0, $sFont)
    For $Index = 0 To 2
        $aRotor[$Index] = GUICtrlCreateLabel('A', 540 + $Index * 120, 20, 100, 50, 0x201)
        $aRotorLabel[$Index] = GUICtrlCreateLabel(NumberToRoman($Index + 1), 540 + $Index * 120, 80, 100, 30, 0x201)
        GUICtrlSetBkColor($aRotor[$Index], 0xC0C0C0)
        GUICtrlSetColor($aRotor[$Index], 0x404040)
        GUICtrlSetFont($aRotor[$Index], 30, 600, 0, $sFont)
        GUICtrlSetColor($aRotorLabel[$Index], 0xC0C0C0)
        GUICtrlSetFont($aRotorLabel[$Index], 18, 600, 0, $sFont)
    Next
EndFunc

Func DrawLKP($sLayout)
    Local $iOffsetX, $iOffsetY, $CurrentPos = 0
    For $Index = 0 To 25
        Switch $Index
            Case 0 To 8
                $iOffsetX = 200
                $iOffsetY = 150
            Case 9 To 16
                $iOffsetX = 250
                $iOffsetY = 220
            Case 17 To 25
                $iOffsetX = $sLayout = 'P' ? 200 : 180
                $iOffsetY = 290
        EndSwitch
        If $Index = 9 Then $CurrentPos = 0
        If $Index = 17 Then $CurrentPos = 0
        Switch $sLayout
            Case 'L'
                $aLamp[$Index] = GUICtrlCreatePic('', $iOffsetX + $CurrentPos * 100, $iOffsetY, 50, 50)
                CreateLamp($aLamp[$Index], StringMid($sKeyLayout, $Index + 1, 1))
            Case 'K'
                $aKeyboard[$Index] = GUICtrlCreatePic('', $iOffsetX + $CurrentPos * 100, $iOffsetY + 275, 50, 50)
                CreateKey($aKeyboard[$Index], StringMid($sKeyLayout, $Index + 1, 1))
            Case 'P'
                $aPlugboard[$Index] = GUICtrlCreatePic('', $iOffsetX + $CurrentPos * 100, $iOffsetY + 550, 50, 90)
                CreatePlugboardInput($aPlugboard[$Index], StringMid($sKeyLayout, $Index + 1, 1))
        EndSwitch
        $CurrentPos += 1
    Next
EndFunc

Func CreateLamp($cLamp, $sLetter)
    _GDIPlus_GraphicsClear($hGraphic, 0xFF404040)
    _GDIPlus_GraphicsFillEllipse($hGraphic, 2, 2, 46, 46, $hBrush2)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sLetter, $hFont, $tLayout, $hFormat, $hBrush1)
    Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _WinAPI_DeleteObject(GUICtrlSendMsg($cLamp, 0x0172, 0, $hHBITMAP))
    _WinAPI_DeleteObject($hHBITMAP)
EndFunc

Func CreateKey($cKey, $sLetter)
    _GDIPlus_GraphicsClear($hGraphic, 0xFF404040)
    _GDIPlus_GraphicsFillEllipse($hGraphic, 2, 2, 46, 46, $hBrush2)
    _GDIPlus_GraphicsFillEllipse($hGraphic, 4, 4, 42, 42, $hBrush1)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sLetter, $hFont, $tLayout, $hFormat, $hBrush2)
    Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _WinAPI_DeleteObject(GUICtrlSendMsg($cKey, 0x0172, 0, $hHBITMAP))
    _WinAPI_DeleteObject($hHBITMAP)
EndFunc

Func CreatePlugboardInput($cKey, $sLetter)
    _GDIPlus_GraphicsClear($hGraphic2, 0xFF404040)
    _GDIPlus_GraphicsFillRect($hGraphic2, 2, 2, 46, 86, $hBrush2)
    _GDIPlus_GraphicsFillRect($hGraphic2, 4, 4, 42, 82, $hBrush1)
    _GDIPlus_GraphicsDrawStringEx($hGraphic2, $sLetter, $hFont, $tLayout2, $hFormat, $hBrush2)
    Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap2)
    _WinAPI_DeleteObject(GUICtrlSendMsg($cKey, 0x0172, 0, $hHBITMAP))
    _WinAPI_DeleteObject($hHBITMAP)
EndFunc

Func LampOn($sKey)
    If $PrevLampOn <> Null Then LampOff()
    $PrevLampOn = __FindLetterInArray(StringSplit($sKeyLayout, '', 2), $sKey)
    _GDIPlus_GraphicsClear($hGraphic, 0xFF404040)
    _GDIPlus_GraphicsFillEllipse($hGraphic, 2, 2, 46, 46, $hBrush3)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sKey, $hFont, $tLayout, $hFormat, $hBrush1)
    Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _WinAPI_DeleteObject(GUICtrlSendMsg($aLamp[$PrevLampOn], 0x0172, 0, $hHBITMAP))
    _WinAPI_DeleteObject($hHBITMAP)
    AdlibRegister('LampOff', 500)
EndFunc

Func LampOff()
    AdlibUnRegister('LampOff')
    If $PrevLampOn = Null Then Return
    _GDIPlus_GraphicsClear($hGraphic, 0xFF404040)
    _GDIPlus_GraphicsFillEllipse($hGraphic, 2, 2, 46, 46, $hBrush2)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, StringMid($sKeyLayout, $PrevLampOn + 1, 1), $hFont, $tLayout, $hFormat, $hBrush1)
    Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _WinAPI_DeleteObject(GUICtrlSendMsg($aLamp[$PrevLampOn], 0x0172, 0, $hHBITMAP))
    _WinAPI_DeleteObject($hHBITMAP)
    $PrevLampOn = Null
EndFunc

Func SetAndDrawPairs($aPairs)
    Local $hHBITMAP
    Local $aKBLayout = StringSplit($sKeyLayout, '', 2)
    For $Index = 1 To $aPairs[0]
        $oEnigma.Plugboard.SetPair($aPairs[$Index])
        Local $iIndex1 = __FindLetterInArray($aKBLayout, StringLeft($aPairs[$Index], 1))
        Local $iIndex2 = __FindLetterInArray($aKBLayout, StringRight($aPairs[$Index], 1))
        _GDIPlus_BrushSetSolidColor($hBrush4, $aPlugboardPallete[$Index - 1])
        _GDIPlus_GraphicsClear($hGraphic2, $aPlugboardPallete[$Index - 1])
        _GDIPlus_GraphicsFillRect($hGraphic2, 2, 2, 46, 86, $hBrush4)
        _GDIPlus_GraphicsFillRect($hGraphic2, 4, 4, 42, 82, $hBrush1)
        _GDIPlus_GraphicsDrawStringEx($hGraphic2, StringLeft($aPairs[$Index], 1), $hFont, $tLayout2, $hFormat, $hBrush2)
        $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap2)
        _WinAPI_DeleteObject(GUICtrlSendMsg($aPlugboard[$iIndex1], 0x0172, 0, $hHBITMAP))
        _WinAPI_DeleteObject($hHBITMAP)
        _GDIPlus_GraphicsClear($hGraphic2, $aPlugboardPallete[$Index - 1])
        _GDIPlus_GraphicsFillRect($hGraphic2, 2, 2, 46, 86, $hBrush4)
        _GDIPlus_GraphicsFillRect($hGraphic2, 4, 4, 42, 82, $hBrush1)
        _GDIPlus_GraphicsDrawStringEx($hGraphic2, StringRight($aPairs[$Index], 1), $hFont, $tLayout2, $hFormat, $hBrush2)
        $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap2)
        _WinAPI_DeleteObject(GUICtrlSendMsg($aPlugboard[$iIndex2], 0x0172, 0, $hHBITMAP))
        _WinAPI_DeleteObject($hHBITMAP)
    Next
EndFunc

Func ValidatePairs($aPairs)
    Local $sAlreadyPlugged, $aSplit
    For $Index = 1 To $aPairs[0]
        If StringLen($aPairs[$Index]) <> 2 Then Return False
        $aSplit = StringSplit($aPairs[$Index], '')
        If StringInStr($sAlreadyPlugged, $aSplit[1]) Or StringInStr($sAlreadyPlugged, $aSplit[2]) Then Return False
        If $aSplit[1] = $aSplit[2] Then Return False
        $sAlreadyPlugged &= $aPairs[$Index]
    Next
    Return True
EndFunc

Func NumberToRoman($iNumber)
    Switch $iNumber
        Case 1
            Return 'I'
        Case 2
            Return 'II'
        Case 3
            Return 'III'
        Case 4
            Return 'IV'
        Case 5
            Return 'V'
    EndSwitch
EndFunc

Func ValidRomanNumeral($sNumber)
    Switch $sNumber
        Case 'I', 'II', 'III', 'IV', 'V'
            Return True
        Case Else
            Return False
    EndSwitch
EndFunc

#Region Enigma
Func Enigma()
    Local $oClass = _AutoItObject_Class()
    With $oClass
        .AddMethod('Set', '__EnigmaSet')
        .AddMethod('SetKey', '__EnigmaSetKey')
        .AddMethod('SetRings', '__EnigmaSetRings')
        .AddMethod('Encrypt', '__EnigmaEncypt')
        .AddProperty('Keyboard', $ELSCOPE_READONLY, Null)
        .AddProperty('Plugboard', $ELSCOPE_READONLY, Null)
        .AddProperty('RightRotor', $ELSCOPE_READONLY, Null)
        .AddProperty('MiddleRotor', $ELSCOPE_READONLY, Null)
        .AddProperty('LeftRotor', $ELSCOPE_READONLY, Null)
        .AddProperty('Reflector', $ELSCOPE_READONLY, Null)
    EndWith
    Return $oClass.Object
EndFunc

Func __EnigmaSet($oSelf, $oKeyboard, $oPlugboard, $oRightRotor, $oMiddleRotor, $oLeftRotor, $oReflector)
    $oSelf.Keyboard = $oKeyboard
    $oSelf.Plugboard = $oPlugboard
    $oSelf.RightRotor = $oRightRotor
    $oSelf.MiddleRotor = $oMiddleRotor
    $oSelf.LeftRotor = $oLeftRotor
    $oSelf.Reflector = $oReflector
EndFunc

Func __EnigmaSetKey($oSelf, $sKey)
    If StringLen($sKey) <> 3 Then Return
    $oSelf.LeftRotor.RotateToLetter(StringMid($sKey, 1, 1))
    $oSelf.MiddleRotor.RotateToLetter(StringMid($sKey, 2, 1))
    $oSelf.RightRotor.RotateToLetter(StringMid($sKey, 3, 1))
EndFunc

Func __EnigmaSetRings($oSelf, $iLeftRing, $iMiddleRing, $iRightRing)
    $oSelf.LeftRotor.SetRing($iLeftRing)
    $oSelf.MiddleRotor.SetRing($iMiddleRing)
    $oSelf.RightRotor.SetRing($iRightRing)
EndFunc

Func __EnigmaEncypt($oSelf, $sLetter)
    Local $iSignal
    If (StringLeft($oSelf.MiddleRotor.Left, 1) = $oSelf.MiddleRotor.Notch) And (StringLeft($oSelf.RightRotor.Left, 1) = $oSelf.RightRotor.Notch) Then
        $oSelf.LeftRotor.Rotate()
        $oSelf.MiddleRotor.Rotate()
        $oSelf.RightRotor.Rotate()
    ElseIf (StringLeft($oSelf.MiddleRotor.Left, 1) = $oSelf.MiddleRotor.Notch) Then
        $oSelf.LeftRotor.Rotate()
        $oSelf.MiddleRotor.Rotate()
        $oSelf.RightRotor.Rotate()
    ElseIf (StringLeft($oSelf.RightRotor.Left, 1) = $oSelf.RightRotor.Notch) Then
        $oSelf.MiddleRotor.Rotate()
        $oSelf.RightRotor.Rotate()
    Else
        $oSelf.RightRotor.Rotate()
    EndIf
    $iSignal = $oSelf.Keyboard.Forward($sLetter)
    $iSignal = $oSelf.Plugboard.Forward($iSignal)
    $iSignal = $oSelf.RightRotor.Forward($iSignal)
    $iSignal = $oSelf.MiddleRotor.Forward($iSignal)
    $iSignal = $oSelf.LeftRotor.Forward($iSignal)
    $iSignal = $oSelf.Reflector.Reflect($iSignal)
    $iSignal = $oSelf.LeftRotor.Backward($iSignal)
    $iSignal = $oSelf.MiddleRotor.Backward($iSignal)
    $iSignal = $oSelf.RightRotor.Backward($iSignal)
    $iSignal = $oSelf.Plugboard.Backward($iSignal)
    Return $oSelf.Keyboard.Backward($iSignal)
EndFunc
#EndRegion Enigma

#Region Keyboard
Func Keyboard()
    Local $oClass = _AutoItObject_Class()
    With $oClass
        .AddMethod('Forward', '__KeyboardForward')
        .AddMethod('Backward', '__KeyboardBackward')
    EndWith
    Return $oClass.Object
EndFunc

Func __KeyboardForward($oSelf, $sLetter)
    Return __FindLetterInArray(StringSplit('ABCDEFGHIJKLMNOPQRSTUVWXYZ', '', 2), $sLetter)
EndFunc

Func __KeyboardBackward($oSelf, $iSignal)
    Return StringSplit('ABCDEFGHIJKLMNOPQRSTUVWXYZ', '', 2)[$iSignal]
EndFunc
#EndRegion Keyboard

#Region Plugboard
Func Plugboard()
    Local $oClass = _AutoItObject_Class()
    With $oClass
        .AddMethod('SetPair', '__PlugboardSetPair')
        .AddMethod('Forward', '__PlugboardForward')
        .AddMethod('Backward', '__PlugboardBackward')
        .AddProperty('Left', $ELSCOPE_READONLY, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
        .AddProperty('Right', $ELSCOPE_READONLY, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    EndWith
    Return $oClass.Object
EndFunc

Func __PlugboardSetPair($oSelf, $sPair)
    Local $aChars = StringSplit($sPair, '', 2)
    Local $aLeft = StringSplit($oSelf.Left, '', 2)
    Local $PosA = __FindLetterInArray($aLeft, $aChars[0])
    Local $PosB = __FindLetterInArray($aLeft, $aChars[1])
    $aLeft[$PosA] = $aChars[1]
    $aLeft[$PosB] = $aChars[0]
    $oSelf.Left = __ArrayToString($aLeft)
EndFunc

Func __PlugboardForward($oSelf, $iSignal)
    Local $sLetter = StringSplit($oSelf.Right, '', 2)[$iSignal]
    Return __FindLetterInArray(StringSplit($oSelf.Left, '', 2), $sLetter)
EndFunc

Func __PlugboardBackward($oSelf, $iSignal)
    Local $sLetter = StringSplit($oSelf.Left, '', 2)[$iSignal]
    Return __FindLetterInArray(StringSplit($oSelf.Right, '', 2), $sLetter)
EndFunc
#EndRegion Plugboard

#Region Rotor
Func Rotor()
    Local $oClass = _AutoItObject_Class()
    With $oClass
        .AddMethod('Set', '__RotorSet')
        .AddMethod('Forward', '__RotorForward')
        .AddMethod('Backward', '__RotorBackward')
        .AddMethod('SetRing', '__RotorSetRing')
        .AddMethod('Rotate', '__RotorRotate')
        .AddMethod('RotateToLetter', '__RotorRotateToLetter')
        .AddProperty('Left', $ELSCOPE_READONLY, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
        .AddProperty('Right', $ELSCOPE_READONLY, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
        .AddProperty('Notch', $ELSCOPE_READONLY, Null)
        .AddProperty('RotorI', $ELSCOPE_PRIVATE, 'EKMFLGDQVZNTOWYHXUSPAIBRCJ')
        .AddProperty('RotorII', $ELSCOPE_PRIVATE, 'AJDKSIRUXBLHWTMCQGZNPYFVOE')
        .AddProperty('RotorIII', $ELSCOPE_PRIVATE, 'BDFHJLCPRTXVZNYEIWGAKMUSQO')
        .AddProperty('RotorIV', $ELSCOPE_PRIVATE, 'ESOVPZJAYQUIRHXLNFTGKDCMWB')
        .AddProperty('RotorV', $ELSCOPE_PRIVATE, 'VZBRGITYUPSDNHLXAWMJQOFECK')
        .AddProperty('RotorI_Notch', $ELSCOPE_PRIVATE, 'Q')
        .AddProperty('RotorII_Notch', $ELSCOPE_PRIVATE, 'E')
        .AddProperty('RotorIII_Notch', $ELSCOPE_PRIVATE, 'V')
        .AddProperty('RotorIV_Notch', $ELSCOPE_PRIVATE, 'J')
        .AddProperty('RotorV_Notch', $ELSCOPE_PRIVATE, 'Z')
    EndWith
    Return $oClass.Object
EndFunc

Func __RotorSet($oSelf, $vRotor)
    Switch $vRotor
        Case 'I', 1
            $oSelf.Right = $oSelf.RotorI
            $oSelf.Notch = $oSelf.RotorI_Notch
        Case 'II', 2
            $oSelf.Right = $oSelf.RotorII
            $oSelf.Notch = $oSelf.RotorII_Notch
        Case 'III', 3
            $oSelf.Right = $oSelf.RotorIII
            $oSelf.Notch = $oSelf.RotorIII_Notch
        Case 'IV', 4
            $oSelf.Right = $oSelf.RotorIV
            $oSelf.Notch = $oSelf.RotorIV_Notch
        Case 'V', 5
            $oSelf.Right = $oSelf.RotorV
            $oSelf.Notch = $oSelf.RotorV_Notch
    EndSwitch
EndFunc

Func __RotorForward($oSelf, $iSignal)
    Local $sLetter = StringSplit($oSelf.Right, '', 2)[$iSignal]
    Return __FindLetterInArray(StringSplit($oSelf.Left, '', 2), $sLetter)
EndFunc

Func __RotorBackward($oSelf, $iSignal)
    Local $sLetter = StringSplit($oSelf.Left, '', 2)[$iSignal]
    Return __FindLetterInArray(StringSplit($oSelf.Right, '', 2), $sLetter)
EndFunc

Func __RotorSetRing($oSelf, $iRing)
    $oSelf.Rotate($iRing - 1, False)
    Local $iAdjust = __FindLetterInArray(StringSplit('ABCDEFGHIJKLMNOPQRSTUVWXYZ', '', 2), $oSelf.Notch)
    $oSelf.Notch = StringSplit('ABCDEFGHIJKLMNOPQRSTUVWXYZ', '', 2)[Mod(Abs($iAdjust - $iRing), 26)]
EndFunc

Func __RotorRotate($oSelf, $nIterations = 1, $bDirection = True)
    For $Index = 1 To $nIterations
        If $bDirection Then
            $oSelf.Left = StringTrimLeft($oSelf.Left, 1) & StringLeft($oSelf.Left, 1)
            $oSelf.Right = StringTrimLeft($oSelf.Right, 1) & StringLeft($oSelf.Right, 1)
        Else
            $oSelf.Left = StringRight($oSelf.Left, 1) & StringTrimRight($oSelf.Left, 1)
            $oSelf.Right = StringRight($oSelf.Right, 1) & StringTrimRight($oSelf.Right, 1)
        EndIf
    Next
EndFunc

Func __RotorRotateToLetter($oSelf, $sLetter)
    $oSelf.Rotate(__FindLetterInArray(StringSplit('ABCDEFGHIJKLMNOPQRSTUVWXYZ', '', 2), $sLetter))
EndFunc

Func __RotorDisplay($oSelf)
    ConsoleWrite($oSelf.Left & @CRLF)
    ConsoleWrite($oSelf.Right & @CRLF & @CRLF)
EndFunc
#EndRegion Rotor

#Region Reflector
Func Reflector()
    Local $oClass = _AutoItObject_Class()
    With $oClass
        .AddMethod('Set', '__ReflectorSet')
        .AddMethod('Reflect', '__Reflect')
        .AddProperty('Left', $ELSCOPE_READONLY, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
        .AddProperty('Right', $ELSCOPE_READONLY, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
        .AddProperty('ReflectorA', $ELSCOPE_PRIVATE, 'EJMZALYXVBWFCRQUONTSPIKHGD')
        .AddProperty('ReflectorB', $ELSCOPE_PRIVATE, 'YRUHQSLDPXNGOKMIEBFZCWVJAT')
        .AddProperty('ReflectorC', $ELSCOPE_PRIVATE, 'FVPJIAOYEDRZXWGCTKUQSBNMHL')
    EndWith
    Return $oClass.Object
EndFunc

Func __ReflectorSet($oSelf, $vReflector)
    Switch $vReflector
        Case 'A'
            $oSelf.Right = $oSelf.ReflectorA
        Case 'B'
            $oSelf.Right = $oSelf.ReflectorB
        Case 'C'
            $oSelf.Right = $oSelf.ReflectorC
    EndSwitch
EndFunc

Func __Reflect($oSelf, $iSignal)
    Local $sLetter = StringSplit($oSelf.Left, '', 2)[$iSignal]
    Return __FindLetterInArray(StringSplit($oSelf.Right, '', 2), $sLetter)
EndFunc
#EndRegion Reflector

Func __FindLetterInArray($aArray, $sLetter)
    For $Index = 0 To UBound($aArray) - 1
        If $aArray[$Index] = $sLetter Then Return $Index
    Next
EndFunc

Func __ArrayToString($aArray)
    Local $sString
    For $Index = 0 To UBound($aArray) - 1
        $sString &= $aArray[$Index]
    Next
    Return $sString
EndFunc

Since all the logic of Enigma is created with objects you need AutoItObject UDF to run the script. All required headers and an executable are included in the zip file.

Enjoy!

Enigma.jpg

Enigma.zip

Edited by Andreik
typo

When the words fail... music speaks.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...