Python Forum
Where is problem in decrypting ADFGVX cipher
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Where is problem in decrypting ADFGVX cipher
#1
Hello, when I want to encrypt a character that has 5 characters, but the key has only 4 characters (which is one character less), decryption doesn't work. If the key has the same number of characters or two characters less, then it works

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget, QMessageBox, QTableWidget, QTableWidgetItem, QGridLayout, QPlainTextEdit
from PyQt6.uic import loadUi
from random import shuffle, choice
from itertools import product, accumulate
from numpy import floor, sqrt
 
class ADFGVXCipherApp(QMainWindow):
    def __init__(self):
        super().__init__()
        loadUi("gui.ui", self# Load the UI from the XML file
 
 
        self.encrypt_button.clicked.connect(self.encrypt_message)
        self.decrypt_button.clicked.connect(self.decrypt_message)
        self.alphabet_entry.textChanged.connect(self.update_alphabet_table)
        self.alphabet_entry.textChanged.connect(self.check_alphabet)
 
        self.display_adfgvx_pairs_button.clicked.connect(self.display_adfgvx_pairs)
        self.update_key_button.clicked.connect(self.update_key_table)
        self.display_decrypt_pairs_button.clicked.connect(self.display_decryption_adfgvx_pairs)
 
        self.decrypt_key_table_button.clicked.connect(self.decrypt_key_table)
 
        self.generate_alphabet_button.clicked.connect(self.generate_random_alphabet)
 
        self.alphabet_entry.textChanged.connect(self.validate_alphabet)
 
    ALLOWED_CHARACTERS = {
        'ADFGVX': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
        'ADFGX_CZ': 'ABCDEFGHIKLMNOPQRSTUVWXYZ',
        'ADFGX_EN': 'ABCDEFGHIJKLMNOPQRSTUVXYZ',
    }
 
    def prepare_input_message(self, input_message, mode):
        # PĹ™eveÄŹte vstupnĂ­ zprávu na velká pĂ­smena
        input_message = input_message.upper()
 
        # Pro reĹľim ADFGX_CZ: NahraÄŹte 'J' za 'I'
        if mode == 'ADFGX_CZ':
            input_message = input_message.replace('J', 'I')
 
        # Pro reĹľim ADFGX_EN: NahraÄŹte 'W' za 'V'
        if mode == 'ADFGX_EN':
            input_message = input_message.replace('W', 'V')
 
        input_message = input_message.replace(' ', 'QXQ')
 
        return input_message
 
    def validate_alphabet(self, text):
        # Get the current text from alphabet_entry
        current_text = self.alphabet_entry.text().upper()
 
        # Ensure that each character in the current text is allowed
        allowed_chars = self.ALLOWED_CHARACTERS[self.alphabet_mode_combobox.currentText()]
        valid_text = ''.join(char for char in current_text if char in allowed_chars)
 
        # Update the text in alphabet_entry with only valid characters
        self.alphabet_entry.setText(valid_text)
 
 
    def decrypt_key_table(self):
        try:
            # ZĂ­skánĂ­ klĂ­ÄŤe pro dešifrovánĂ­ z pole vstupnĂ­ho klĂ­ÄŤe
            decryption_key_text = self.decryption_key.text().upper()
 
            # ZĂ­skánĂ­ zašifrovanĂ©ho textu z pole zašifrovanĂ©ho vstupu
            ciphertext = self.ciphertext_entry2.text().upper()
 
            # SeĹ™azenĂ­ klĂ­ÄŤe abecednÄ›
            sorted_decryption_key = ''.join(sorted(decryption_key_text))
 
            # NastavenĂ­ seĹ™azenĂ©ho klĂ­ÄŤe v prvnĂ­m řádku tabulky
            decrypt_key_table = self.findChild(QTableWidget, 'decrypt_table')
            decrypt_key_table.setRowCount(1)
            decrypt_key_table.setColumnCount(len(sorted_decryption_key))
            for i, char in enumerate(sorted_decryption_key):
                item = QTableWidgetItem(char)
                decrypt_key_table.setItem(0, i, item)
 
            # SpoÄŤĂ­táme poÄŤet řádkĹŻ na základÄ› dĂ©lky šifrovanĂ©ho textu a dĂ©lky klĂ­ÄŤe
            num_rows = (len(ciphertext) + len(sorted_decryption_key) - 1) // len(sorted_decryption_key)
            decrypt_key_table.setRowCount(num_rows)
 
            # NaplnĂ­me tabulku podle sloupcĹŻ, ne řádkĹŻ, pouĹľijeme seĹ™azenĂ˝ klĂ­ÄŤ
            for i, char in enumerate(ciphertext):
                row = i % num_rows
                col = i // num_rows
                item = QTableWidgetItem(char)
                decrypt_key_table.setItem(row, col, item)
 
            # Upravit šířku sloupcĹŻ, aby se vešlo obsah
            decrypt_key_table.resizeColumnsToContents()
        except Exception as e:
            # ZachycenĂ­ a zpracovánĂ­ vĂ˝jimky (chyby)
            error_message = str(e)  # ZĂ­skánĂ­ textovĂ©ho popisu chyby
            self.show_error("Error", f"An error occurred: {error_message}")
 
    def display_decryption_adfgvx_pairs(self):
        encrypted_message = self.decrypted_message_entry.toPlainText().upper()
        key = self.encryption_key.text().upper()
        alphabet = self.alphabet_entry.text().upper()
        adfgvx_pairs = []
 
        for char in encrypted_message:
            if char in alphabet:
                encoded_char = self.encrypt_ADFGVX(char, key)
                adfgvx_pairs.append(encoded_char)
 
        # Reverse each character in adfgvx_pairs for the second row
        adfgvx_pairs_second_row = [pair[::-1] for pair in adfgvx_pairs]
 
        # Create a new QTableWidget with 2 rows and the same number of columns as the encrypted message length
        num_columns = len(adfgvx_pairs)  # Use the length of adfgvx_pairs
        self.decrypt_pairs_table.setColumnCount(num_columns)
        self.decrypt_pairs_table.setRowCount(2)
 
        # Set the encrypted_message in the first row
        for i, char in enumerate(encrypted_message):
            item = QTableWidgetItem(char)
            self.decrypt_pairs_table.setItem(0, i, item)
 
        # Set the reversed ADFGVX pairs in the second row
        for i, pair in enumerate(adfgvx_pairs_second_row):
            item = QTableWidgetItem(pair)
            self.decrypt_pairs_table.setItem(1, i, item)
 
        # Adjust column widths to fit the content
        self.decrypt_pairs_table.resizeColumnsToContents()
 
    def update_key_table(self):
        message_pairs_table = self.findChild(QTableWidget, 'message_pairs_table')
        if not message_pairs_table.item(0, 0):
            self.show_error("Error", "Please display ADFGVX pairs first.")
            return
 
        encryption_key_text = self.encryption_key.text().upper()
        message_pairs_table = self.findChild(QTableWidget, 'message_pairs_table')
        key_table = self.findChild(QTableWidget, 'key_table')
 
        num_columns = message_pairs_table.columnCount()
        encryption_key_length = len(encryption_key_text)
 
        # Create a dictionary to map characters to their position in the key
        char_to_position = {}
        char_count = {}  # PoÄŤet vĂ˝skytĹŻ kaĹľdĂ©ho znaku v klĂ­ÄŤi
 
        # PoÄŤĂ­tánĂ­ vĂ˝skytĹŻ znakĹŻ v klĂ­ÄŤi
        for char in encryption_key_text:
            if char in char_count:
                char_count[char] += 1
            else:
                char_count[char] = 1
 
        # Calculate the number of rows needed to display the entire message
        num_rows = (num_columns + encryption_key_length - 1) // encryption_key_length
 
        # Create the key table with the appropriate number of rows and columns
        key_table.setRowCount(num_rows)
        key_table.setColumnCount(encryption_key_length)
 
        # Replace characters with their position in the key for matching characters
        for i in range(encryption_key_length):
            char = encryption_key_text[i]
            if char_count[char] > 1:
                if char in char_to_position:
                    char_to_position[char] += 1
                else:
                    char_to_position[char] = 1
                item = QTableWidgetItem(f"{char_to_position[char]}")
            else:
                item = QTableWidgetItem(char)
            key_table.setItem(0, i, item)
 
        # Get the text from the second row of the message_pairs_table
        adfgvx_text = [message_pairs_table.item(1, i).text() for i in range(num_columns)]
 
        # Split the pairs into individual characters
        individual_characters = [char for pair in adfgvx_text for char in pair]
 
        # Populate the key table with the individual characters from message_pairs_table
        for i, char in enumerate(individual_characters):
            row = (i // encryption_key_length) + 1
            col = i % encryption_key_length
            if char_count.get(char, 0) > 1:
                if char in char_to_position:
                    item = QTableWidgetItem(f"{char_to_position[char]}")
                else:
                    item = QTableWidgetItem(char)
            else:
                item = QTableWidgetItem(char)
            # If the row doesn't exist, create it
            while row >= key_table.rowCount():
                key_table.insertRow(key_table.rowCount())
            key_table.setItem(row, col, item)
 
        # Adjust column widths to fit the content
        key_table.resizeColumnsToContents()
 
    def display_adfgvx_pairs(self):
        input_message = self.input_message.text().upper()
        key = self.encryption_key.text().upper()
        alphabet = self.alphabet_entry.text().upper()
        adfgvx_pairs = []
 
        for char in input_message:
            if char in alphabet:
                encoded_char = self.encrypt_ADFGVX(char, key)
                adfgvx_pairs.append(encoded_char)  # Append only the encoded character
 
        # Reverse each character in adfgvx_pairs for the second row
        adfgvx_pairs_second_row = [pair[::-1] for pair in adfgvx_pairs]
 
        # Create a new QTableWidget with 2 rows and the same number of columns as the input message length
        num_columns = len(adfgvx_pairs)  # Use the length of adfgvx_pairs
        self.message_pairs_table.setColumnCount(num_columns)
        self.message_pairs_table.setRowCount(2)
 
        # Set the input_message in the first row
        for i, char in enumerate(input_message):
            item = QTableWidgetItem(char)
            self.message_pairs_table.setItem(0, i, item)
 
        # Set the reversed ADFGVX pairs in the second row
        for i, pair in enumerate(adfgvx_pairs_second_row):
            item = QTableWidgetItem(pair)
            self.message_pairs_table.setItem(1, i, item)
 
        # Adjust column widths to fit the content
        self.message_pairs_table.resizeColumnsToContents()
 
    def check_alphabet(self, text):
        # ZĂ­skáme aktuálnĂ­ text z alphabet_entry
        current_text = self.alphabet_entry.text().upper()
 
        # OdstranĂ­me duplicity znakĹŻ
        unique_characters = ''.join(sorted(set(current_text), key=current_text.index))
 
        # Aktualizujeme text v alphabet_entry
        self.alphabet_entry.setText(unique_characters)
 
    def update_alphabet_table(self):
        alphabet = self.alphabet_entry.text().upper()
        alphabet_table = self.findChild(QTableWidget, 'alphabet_table')
 
        num_rows = 0
        num_columns = 0
        custom_row_headers = []
        custom_col_headers = []
        missing_characters = set()
 
        # Determine the dimensions, headers, and missing characters based on the selected mode
        mode_index = self.alphabet_mode_combobox.currentIndex()
        if mode_index == 0# ADFGVX
            num_rows = 6
            num_columns = 6
            custom_row_headers = ['A', 'D', 'F', 'G', 'V', 'X']
            custom_col_headers = ['A', 'D', 'F', 'G', 'V', 'X']
            missing_characters = set("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") - set(alphabet)
        elif mode_index == 1# ADFGX_CZ
            num_rows = 5
            num_columns = 5
            custom_row_headers = ['A', 'D', 'F', 'G', 'V', 'X']
            custom_col_headers = ['A', 'D', 'F', 'G', 'X']
            missing_characters = set("ABCDEFGHIKLMNOPQRSTUVWXYZ") - set(alphabet)
        elif mode_index == 2# ADFGX_EN
            num_rows = 5
            num_columns = 5
            custom_row_headers = ['A', 'D', 'F', 'G', 'V', 'X']
            custom_col_headers = ['A', 'D', 'F', 'G', 'X']
            missing_characters = set("ABCDEFGHIJKLMNOPQRSTUVXYZ") - set(alphabet)
 
        alphabet_table.setRowCount(num_rows)
        alphabet_table.setColumnCount(num_columns)
 
        used_characters = set()
 
        for row in range(num_rows):
            for col in range(num_columns):
                index = row * num_columns + col
                if index < len(alphabet):
                    char = alphabet[index]
                    item = QTableWidgetItem(char)
                    alphabet_table.setItem(row, col, item)
                    used_characters.add(char)
                else:
                    item = QTableWidgetItem('')
                    alphabet_table.setItem(row, col, item)
 
        missing_characters_text = ", ".join(sorted(missing_characters))
        self.missing_characters_label.setText(f"ChybÄ›jĂ­cĂ­ znaky: {missing_characters_text}")
 
        # Set the custom row headers
        for row, header in enumerate(custom_row_headers):
            alphabet_table.setVerticalHeaderItem(row, QTableWidgetItem(header))
 
        # Set the custom column headers
        for col, header in enumerate(custom_col_headers):
            alphabet_table.setHorizontalHeaderItem(col, QTableWidgetItem(header))
 
    def generate_random_alphabet(self):
        mode_index = self.alphabet_mode_combobox.currentIndex()
        modes = ['ADFGVX', 'ADFGX_CZ', 'ADFGX_EN'# Add more modes as needed
        selected_mode = modes[mode_index] if 0 <= mode_index < len(modes) else 'ADFGVX'
 
        if selected_mode == 'ADFGVX':
            alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
        elif selected_mode == 'ADFGX_CZ':
            alphabet = 'ABCDEFGHIKLMNOPQRSTUVWXYZ'
        elif selected_mode == 'ADFGX_EN':
            alphabet = 'ABCDEFGHIJKLMNOPQRSTUVXYZ'
        else:
            # Default to ADFGVX alphabet if the mode is not recognized
            alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
 
        custom_dictionary = [alphabet[i:i + 6] for i in range(0, len(alphabet), 6)]
        shuffle(custom_dictionary)
        self.alphabet_entry.setText(''.join(custom_dictionary))
        self.update_alphabet_table()
 
    # Add a function to handle mode selection
    def select_alphabet_mode(self, index):
        modes = ['ADFGVX', 'ADFGX_CZ', 'ADFGX_EN'# Add more modes as needed
        selected_mode = modes[index] if 0 <= index < len(modes) else 'ADFGVX'
        self.generate_random_alphabet(selected_mode)
 
    def create_encode_dict(self):
        """ Create the ADFGVX encoding dictionary. """
        matrices = list('ADFGVX')
        pairs = [p[0] + p[1] for p in product(matrices, matrices)]
        return dict(zip(self.alphabet_entry.text().upper(), pairs))
 
    def encrypt_ADFGVX(self, msg, key):
        """ Encrypt with the ADFGVX cipher. """
        alphabet = list(self.alphabet_entry.text().upper())
        key = list(key.upper())
        pdim = int(floor(sqrt(len(alphabet))))
        encode = self.create_encode_dict()
 
        chars = list(''.join([encode[c] for c in msg.upper() if c in alphabet]))
        colvecs = [(lett, chars[i:len(chars):len(key)]) for (i, lett) in enumerate(key)]
        colvecs.sort(key=lambda x: x[0])
        return ''.join([''.join(a[1]) for a in colvecs])
 
    def decrypt_ADFGVX(self, cod, key):
        """ Decrypt with the ADFGVX cipher. Does not depend on spacing of encoded text """
        matrices = list('ADFGVX')
        chars = [c for c in cod if c in matrices]
        key = list(key.upper())
        sortedkey = sorted(key)
        order = [key.index(ch) for ch in sortedkey]
        originalorder = [sortedkey.index(ch) for ch in key]
        base, extra = divmod(len(chars), len(key))
        strides = [base + (1 if extra > i else 0) for i in order]
        starts = list(accumulate(strides[:-1], lambda x, y: x + y))
        starts = [0] + starts
        ends = [starts[i] + strides[i] for i in range(len(key))]
        cols = [chars[starts[i]:ends[i]] for i in originalorder]
        pairs = []
        for i in range((len(chars) - 1) // len(key) + 1):
            for j in range(len(key)):
                if i * len(key) + j < len(chars):
                    pairs.append(cols[j][i])
 
        decode = dict((v, k) for (k, v) in self.create_encode_dict().items())
        return ''.join([decode[pairs[i] + pairs[i + 1]] for i in range(0, len(pairs), 2)])
 
    def generate_alphabet(self):
        self.generate_random_alphabet()
        self.update_alphabet_table()
 
    def handle_alphabet_mode_change(self, index):
        self.generate_random_alphabet()
 
    def encrypt_message(self):
        input_message = self.input_message.text()
        key = self.encryption_key.text()
        mode = self.alphabet_mode_combobox.currentText()
 
        # PĹ™edzpracujte vstupnĂ­ zprávu podle reĹľimu
        processed_input_message = self.prepare_input_message(input_message, mode)
 
        if not processed_input_message or not key or not self.alphabet_entry.text():
            self.show_error("Error", "Please enter message, key, and alphabet")
            return
 
        ciphertext = self.encrypt_ADFGVX(processed_input_message, key)
        self.ciphertext_entry.setPlainText(ciphertext)
 
    def decrypt_message(self):
        ciphertext = self.ciphertext_entry2.text()
        key = self.decryption_key.text()
 
        if not ciphertext or not key or not self.alphabet_entry.text():
            self.show_error("Error", "Please enter ciphertext, key, and alphabet")
            return
 
 
        decrypted_message = self.decrypt_ADFGVX(ciphertext, key)
 
        decrypted_message = decrypted_message.replace('QXQ', ' ')
 
 
        self.decrypted_message_entry.setPlainText(decrypted_message)
 
 
    def show_error(self, title, message):
        msg_box = QMessageBox(self)
        msg_box.setIcon(QMessageBox.Icon.Critical)
        msg_box.setWindowTitle(title)
        msg_box.setText(message)
        msg_box.exec()
 
def main():
    app = QApplication(sys.argv)
    ex = ADFGVXCipherApp()
    ex.show()
    sys.exit(app.exec())
 
if __name__ == '__main__':
    main()
Reply
#2
I'm not sure, but the error you are getting is likely because you are trying to decrypt a message that is longer than the key. The ADFGVX cipher is a polyalphabetic substitution cipher, which means that it uses multiple alphabets to encrypt and decrypt messages. The key determines which alphabet is used for each character in the message.

If the key is shorter than the message, then the cipher will start using the same alphabets again for the later characters in the message. This means that the decryption will not be accurate.
Reply
#3
(Nov-06-2023, 08:02 AM)armamos Wrote: I'm not sure, but the error you are getting is likely because you are trying to decrypt a message that is longer than the key. The ADFGVX cipher is a polyalphabetic substitution cipher, which means that it uses multiple alphabets to encrypt and decrypt messages. The key determines which alphabet is used for each character in the message.

If the key is shorter than the message, then the cipher will start using the same alphabets again for the later characters in the message. This means that the decryption will not be accurate.
I've already fixed the code; now, the only issue is with the key. If it's one character shorter than the input text to be encrypted, decryption doesn't work. However, if it's shorter by more characters, it works
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Cesar Cipher ForsakenDusk 5 2,282 Apr-07-2024, 04:30 PM
Last Post: Pedroski55
Question Rsa Cipher Paragoon2 3 1,588 Nov-27-2023, 12:30 PM
Last Post: snippsat
  RSA Cipher with blocks Paragoon2 0 1,226 Nov-26-2023, 04:35 PM
Last Post: Paragoon2
  Transposition Cipher Issues beginner_geek07 0 1,774 Apr-08-2022, 07:44 PM
Last Post: beginner_geek07
  Caesar Cipher Help pbrowne 2 3,148 Jun-30-2021, 02:36 PM
Last Post: deanhystad
  Coding caesar's cipher drewbty 3 4,121 May-16-2020, 10:05 AM
Last Post: DPaul
  cipher decryption tool nightfox82 0 1,899 Mar-25-2020, 06:36 AM
Last Post: nightfox82
  Alternate solutions to cipher problem? Mark17 3 3,385 Oct-08-2019, 01:32 PM
Last Post: jefsummers
  Problem with caesar cipher lucaron 2 3,769 Feb-05-2018, 05:17 PM
Last Post: lucaron
  Decrypt Caesar Cipher WantToImprove 22 23,096 Jan-30-2018, 08:43 AM
Last Post: WantToImprove

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020