I got interested in the story of the Enigma machines and Bletchly Park and ended up writing this, just for kicks :smile:
Now, is someone can write something in ABAP to decypher Enigma messages, please let me know.
*&---------------------------------------------------------------------*
* Report Z_ENIGMA
*
*&---------------------------------------------------------------------*
* This is a3 wheel Enigma coding machine emulator using genuine wheel settings.
* Sequence is this :-
* Input -> Plugboard -> Wheel 3,2,1 -> Reflector -> Wheel 1,2,3 -> Plugboard -> Output
*
* The plugboard is a set of connections between the wheel input and either
* the keyboard (i/P) or lightboard (o/p)
*
* An enigma wheel has a set of 26 i/p connections and 26 o/p connections
* It has a ring around the outside so these connections can be
* shifted relative to the characters that are displayed on its outer edge.
* It has a turnover point where the next wheel in the set moves 1 position
* (think how a car odometer works when it moves from 9 to 10)
*
* When in use, the initial settings have to be known by the receiving machine
* So the initial settings are encoded using some other method and transmitted
* to the receiver first. This is called public key encryption, because the key
* is known publicly (but not how to use it).
*&---------------------------------------------------------------------*
* Text symbols are defined as :
* 001 = "Enigma Settings: Wheel order, start positions and plugboard"
* 002 = "Text to be encrypted / decrypted. Characters A to Z only. No puncuation / numbers."
*
* Selection Texts are defined as :
* INIT1 = "Initial Position Wheel 1"
* INIT2 = "Initial Position Wheel 2"
* INIT3 = "Initial Position Wheel 3"
* P_PLUGB = "Use plugboard mapping?"
* W1 = "Wheel 1"
* W2 = "Wheel 2"
* W3 = "Wheel 3"
*&---------------------------------------------------------------------*
REPORT z_enigma .
CONSTANTS:
c_ref_b TYPE char26 VALUE 'YRUHQSLDPXNGOKMIEBFZCWVJAT',
c_plugb TYPE char26 VALUE 'ZBCDEFHGIJKLNMOPQRSTUVWXYA',
c_alpha TYPE char26 VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
c_wheel1 TYPE char26 VALUE 'EKMFLGDQVZNTOWYHXUSPAIBRCJ',
c_wheel2 TYPE char26 VALUE 'AJDKSIRUXBLHWTMCQGZNPYFVOE',
c_wheel3 TYPE char26 VALUE 'BDFHJLCPRTXVZNYEIWGAKMUSQO',
c_wheel4 TYPE char26 VALUE 'ESOVPZJAYQUIRHXLNFTGKDCMWB',
c_wheel5 TYPE char26 VALUE 'VZBRGITYUPSDNHLXAWMJQOFECK',
c_wheel6 TYPE char26 VALUE 'JPGVOUMFYQBENHZRDKASXLICTW',
c_wheel7 TYPE char26 VALUE 'NZJHGRCXMYSWBOUFAIVLPEKQDT',
c_wheel8 TYPE char26 VALUE 'FKQHTLXOCBJSPDZRAMEWNIUYGV',
c_turn1 TYPE char1 VALUE 'R',
c_turn2 TYPE char1 VALUE 'F',
c_turn3 TYPE char1 VALUE 'W',
c_turn4 TYPE char1 VALUE 'K',
c_turn5 TYPE char1 VALUE 'A',
c_turn6 TYPE char2 VALUE 'AN', "Getting sneaky by using 2 turnover positions
c_turn7 TYPE char2 VALUE 'AN',
c_turn8 TYPE char2 VALUE 'AN'.
DATA: v_output TYPE string,
v_source TYPE string,
v_temp TYPE string,
v_length TYPE i,
source TYPE string,
wheel3 TYPE char26,
wheel2 TYPE char26,
wheel1 TYPE char26,
alpha TYPE char26,
turn1 TYPE char1,
turn2 TYPE char1,
fname TYPE char8.
TYPES : BEGIN OF ty_wrd ,
text TYPE char80 ,
END OF ty_wrd .
DATA: char_in TYPE char1,
c1 TYPE char1,
idx TYPE i,
pos TYPE i,
char_out TYPE char1,
lt_text TYPE TABLE OF ty_wrd WITH HEADER LINE,
gc_docking TYPE REF TO cl_gui_docking_container,
gc_text_editor TYPE REF TO cl_gui_textedit,
gt_text TYPE TABLE OF tline-tdline,
gs_text TYPE tline-tdline.
FIELD-SYMBOLS <data> TYPE any.
*======================================================================*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.
* Choose 3 wheels
PARAMETERS: w1 TYPE ddtabind DEFAULT 1,
w2 TYPE ddtabind DEFAULT 2,
w3 TYPE ddtabind DEFAULT 3.
SELECTION-SCREEN SKIP 1.
* Set wheel start position
PARAMETERS: init1 TYPE sf_char1 DEFAULT 'M',
init2 TYPE sf_char1 DEFAULT 'C',
init3 TYPE sf_char1 DEFAULT 'K'.
SELECTION-SCREEN SKIP 1.
PARAMETERS: p_plugb AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b1.
SELECTION-SCREEN SKIP 2.
SELECTION-SCREEN COMMENT /1(82) text-002.
*======================================================================*
INITIALIZATION.
PERFORM initialization.
*======================================================================*
AT SELECTION-SCREEN OUTPUT.
TRANSLATE init1 TO UPPER CASE.
TRANSLATE init2 TO UPPER CASE.
TRANSLATE init3 TO UPPER CASE.
AT SELECTION-SCREEN ON BLOCK b1.
IF w1 IS INITIAL OR
w2 IS INITIAL OR
w3 IS INITIAL OR
w1 > 8 OR w2 > 8 OR w3 > 8.
MESSAGE s001(00) WITH 'Select 3 wheel numbers from 1 to 8'.
ENDIF.
IF w3 = w2 OR
w3 = w1 OR
w2 = w1.
MESSAGE s001(00) WITH 'Wheels cannot be used in more that 1 position'.
ENDIF.
IF init1 IS INITIAL OR
init1 NA sy-abcde.
MESSAGE s001(00) WITH 'Set start position wheel 1 A to Z'.
ENDIF.
IF init2 IS INITIAL OR
init2 NA sy-abcde.
MESSAGE s001(00) WITH 'Set start position wheel 2 A to Z'.
ENDIF.
IF init3 IS INITIAL OR
init3 NA sy-abcde.
MESSAGE s001(00) WITH 'Set start position wheel 3 A to Z'.
ENDIF.
*======================================================================*
START-OF-SELECTION.
* Load selected wheels into work areas
CONCATENATE 'C_WHEEL' w1 INTO fname.
ASSIGN (fname) TO <data>.
wheel1 = <data>.
CONCATENATE 'C_WHEEL' w2 INTO fname.
ASSIGN (fname) TO <data>.
wheel2 = <data>.
CONCATENATE 'C_TURN' w2 INTO fname.
ASSIGN (fname) TO <data>.
turn1 = <data>.
CONCATENATE 'C_WHEEL' w3 INTO fname.
ASSIGN (fname) TO <data>.
wheel3 = <data>.
CONCATENATE 'C_TURN' w3 INTO fname.
ASSIGN (fname) TO <data>.
turn2 = <data>.
PERFORM enigma.
*======================================================================*
FORM initialization.
* Add free text box to selection screen
CREATE OBJECT gc_docking
EXPORTING
repid = sy-repid
dynnr = sy-dynnr
side = gc_docking->dock_at_bottom
extension = 200.
CREATE OBJECT gc_text_editor
EXPORTING
parent = gc_docking.
IMPORT gt_text FROM MEMORY ID sy-repid.
* Put in sample text
IF gt_text IS INITIAL.
gs_text = 'ZKA NTCKV KOGZE WAO UPHZX HZSY YNI FKMB AFP'.
* Using wheels 123 at MCK with plugboard turned on
* this will decypher to "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG"
APPEND gs_text TO gt_text.
ENDIF.
CALL METHOD gc_text_editor->set_text_as_r3table
EXPORTING
table = gt_text
EXCEPTIONS
OTHERS = 1.
ENDFORM. " INITIALIZATION
*&---------------------------------------------------------------------*
*& Form enigma
*&---------------------------------------------------------------------*
FORM enigma.
* Get text from selection screen screen editor
REFRESH gt_text.
CALL METHOD gc_text_editor->get_text_as_r3table
IMPORTING
table = gt_text
EXCEPTIONS
OTHERS = 1.
CALL FUNCTION 'CONVERT_TABLE_TO_STRING'
EXPORTING
i_tabline_length = 132
IMPORTING
e_string = source
TABLES
it_table = gt_text.
* Shift to upper case and remove all spaces
TRANSLATE source TO UPPER CASE.
v_source = source.
CONDENSE source NO-GAPS.
v_length = strlen( source ).
* Order is this :-
* Input -> Plugboard -> Wheel 3,2,1 -> Reflector -> Wheel 1,2,3 -> Plugboard -> Output
CLEAR : v_temp, v_output.
DO v_length TIMES.
* get input character from keyboard
pos = sy-index - 1.
char_in = source+pos(1).
* Validate only alphabetic characters used
IF char_in NA sy-abcde.
MESSAGE s001(00) WITH 'Only letters A to Z allowed'.
LEAVE LIST-PROCESSING.
ENDIF.
* Plugboard mapping inbound
PERFORM plugboard USING 'I' CHANGING char_in.
* Wheel 3
* Wheel 3 always steps on 1 position before encoding starts
CLEAR pos.
SEARCH c_alpha FOR init3.
pos = sy-fdpos + 1. "11
PERFORM index_wrap CHANGING pos.
init3 = c_alpha+pos(1).
* Setup wheel
CONCATENATE 'C_WHEEL' w3 INTO fname.
ASSIGN (fname) TO <data>.
PERFORM set_wheel USING <data>
init3
CHANGING wheel3.
* Look for index of entered character
SEARCH c_alpha FOR char_in.
* Get wheel character.
c1 = wheel3+sy-fdpos(1).
* Look for index of o/p character
PERFORM set_wheel USING c_alpha
init3
CHANGING alpha.
SEARCH alpha FOR c1.
idx = sy-fdpos.
* Wheel 2 turnover
IF turn1 CA init3.
CLEAR pos.
SEARCH c_alpha FOR init2.
pos = sy-fdpos + 1.
PERFORM index_wrap CHANGING pos.
init2 = c_alpha+pos(1).
ENDIF.
* Wheel 2
* Setup wheel
CONCATENATE 'C_WHEEL' w2 INTO fname.
ASSIGN (fname) TO <data>.
PERFORM set_wheel USING <data>
init2
CHANGING wheel2.
c1 = wheel2+idx(1).
* Look for index of o/p character
PERFORM set_wheel USING c_alpha
init2
CHANGING wheel2.
SEARCH wheel2 FOR c1.
idx = sy-fdpos.
* Wheel 1 turnover
IF turn2 CA init2.
CLEAR pos.
SEARCH c_alpha FOR init1.
pos = sy-fdpos + 1.
PERFORM index_wrap CHANGING pos.
init1 = c_alpha+pos(1).
ENDIF.
* Wheel 1
* Setup wheel
CONCATENATE 'C_WHEEL' w1 INTO fname.
ASSIGN (fname) TO <data>.
PERFORM set_wheel USING <data>
init1
CHANGING wheel1.
c1 = wheel1+idx(1).
* Look for index of o/p character
PERFORM set_wheel USING c_alpha
init1
CHANGING wheel1.
SEARCH wheel1 FOR c1.
idx = sy-fdpos.
c1 = c_alpha+idx(1).
* Reflector
SEARCH c_ref_b FOR c1.
c1 = c_alpha+sy-fdpos(1).
idx = sy-fdpos.
* wheel 1 again
PERFORM set_wheel USING c_alpha
init1
CHANGING wheel1.
c1 = wheel1+idx(1).
CONCATENATE 'C_WHEEL' w1 INTO fname.
ASSIGN (fname) TO <data>.
PERFORM set_wheel USING <data>
init1
CHANGING wheel1.
SEARCH wheel1 FOR c1.
idx = sy-fdpos.
* wheel 2 again
PERFORM set_wheel USING c_alpha
init2
CHANGING wheel2.
c1 = wheel2+idx(1).
CONCATENATE 'C_WHEEL' w2 INTO fname.
ASSIGN (fname) TO <data>.
PERFORM set_wheel USING <data>
init2
CHANGING wheel2.
SEARCH wheel2 FOR c1.
idx = sy-fdpos.
* wheel 3 again
PERFORM set_wheel USING c_alpha
init3
CHANGING wheel3.
c1 = wheel3+idx(1).
CONCATENATE 'C_WHEEL' w3 INTO fname.
ASSIGN (fname) TO <data>.
PERFORM set_wheel USING <data>
init3
CHANGING wheel3.
SEARCH wheel3 FOR c1.
idx = sy-fdpos.
char_out = c_alpha+idx(1).
* Plugboard mapping outbound
PERFORM plugboard USING 'O' CHANGING char_out.
* Build output string
CONCATENATE v_temp char_out INTO v_temp.
ENDDO.
* Put spaces back in same place as in selection screen text
SHIFT v_source LEFT DELETING LEADING space.
v_length = strlen( v_source ).
CLEAR: pos, idx.
DO v_length TIMES.
* get selection screen character
c1 = v_source+pos(1).
IF c1 IS INITIAL.
CONCATENATE v_output ' ' INTO v_output RESPECTING BLANKS.
idx = idx + 1.
pos = pos + 1.
CONTINUE.
ELSE.
sy-fdpos = pos - idx.
c1 = v_temp+sy-fdpos(1).
CONCATENATE v_output c1 INTO v_output.
pos = pos + 1.
ENDIF.
ENDDO.
* Write source to result screen
REFRESH lt_text.
CALL FUNCTION 'CONVERT_STRING_TO_TABLE'
EXPORTING
i_string = v_source
i_tabline_length = 80
TABLES
et_table = lt_text.
FORMAT INTENSIFIED ON.
WRITE / 'Input text.'.
FORMAT INTENSIFIED OFF.
LOOP AT lt_text.
SHIFT lt_text-text LEFT DELETING LEADING space.
WRITE / lt_text-text.
ENDLOOP.
* Write result to result screen
REFRESH lt_text.
CALL FUNCTION 'CONVERT_STRING_TO_TABLE'
EXPORTING
i_string = v_output
i_tabline_length = 80
TABLES
et_table = lt_text.
WRITE /.
FORMAT INTENSIFIED ON.
WRITE / 'Output text.'.
FORMAT INTENSIFIED OFF.
LOOP AT lt_text.
SHIFT lt_text-text LEFT DELETING LEADING space.
WRITE / lt_text-text.
ENDLOOP.
WRITE /.
FORMAT INTENSIFIED ON.
WRITE / 'If you copy the output text and use that as the input text'.
WRITE / 'with the same initial setup on the selection screen.'.
WRITE / 'your output will be deciphered or enciphered as required'.
ENDFORM. "enigma
*&---------------------------------------------------------------------*
*& Form plugboard
*&---------------------------------------------------------------------*
FORM plugboard USING p_direction TYPE char1
CHANGING p_char TYPE char1.
* This is a simple x to y type mapping
* Not all charcaters have to be mapped
* EG. You could leave everything as it comes out of the wheels
* except, say, mapping A to G (and therefore G to A)
*
* The default in this pgm only map A/Z and G/H in the plugboard
* c_alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
* c_plugb = 'ZBCDEFHGIJKLNMOPQRSTUVWXYA',
* ^ ^^ ^
CHECK p_plugb = 'X'. " is plugboard mapping ON
IF p_direction = 'I'.
* Input from keyboard to wheels
SEARCH c_alpha FOR p_char.
p_char = c_plugb+sy-fdpos(1).
ELSE.
* Output from wheels to lightboard
SEARCH c_plugb FOR p_char.
p_char = c_alpha+sy-fdpos(1).
ENDIF.
ENDFORM. "plugboard
*&---------------------------------------------------------------------*
*& Form index_wrap
*&---------------------------------------------------------------------*
* This is used to correct the wheel index in case of wrap-around
* required to make the linear wheel string act like a circular wheel
FORM index_wrap CHANGING p_i TYPE i.
IF p_i > 25.
p_i = p_i - 25.
ELSEIF p_i < 0.
p_i = p_i + 25.
ENDIF.
ENDFORM. "index_wrap
*&---------------------------------------------------------------------*
*& Form set_wheel
*&---------------------------------------------------------------------*
* Set wheel characters so start position charcater is at position 1.
* EG :
* Wheel 1 with start position is, say, W
* EKMFLGDQVZNTOWYHXUSPAIBRCJ
* -------------^------------
* becomes:
* WYHXUSPAIBRCJEKMFLGDQVZNTO
FORM set_wheel USING p_wheel_in TYPE char26
p_start TYPE char1
CHANGING p_wheel_out TYPE char26.
DATA: l_index TYPE i,
l_char TYPE char1.
CLEAR p_wheel_out.
SEARCH c_alpha FOR p_start.
l_index = sy-fdpos.
DO 26 TIMES.
IF l_index > 25.
l_index = 0.
ENDIF.
l_char = p_wheel_in+l_index(1).
CONCATENATE p_wheel_out l_char
INTO p_wheel_out.
l_index = l_index + 1.
ENDDO.
ENDFORM. "set_wheel
User | Count |
---|---|
36 | |
7 | |
5 | |
5 | |
5 | |
4 | |
4 | |
4 | |
3 | |
3 |