I got interested in the story of the Enigma machines and Bletchly Park and ended up writing this, just for kicks 🙂

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

To report this post you need to login first.