Andreik Posted June 20, 2023 Share Posted June 20, 2023 (edited) 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. expandcollapse popup#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.zip Edited June 20, 2023 by Andreik typo marcoauto 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now