krisarmstrong
Coder
I have an enigma machine that works for encoding; however, I'm lost on the decoding part. This was originally a C++ app that I have been converting to Python.
And here is the decode, which does not currently work.
The Rotors are here.
Below is the encoding and debugging output.
69641234567001 was the number encoded to 9061571597015527 however it does not decode 9061571597015527 back to 69641234567001.
Code:
from enigma_common import encode_rotor_10, encode_rotor_26
from enigma_common import n0, n9, nA, nZ
def encode_checksum_calc(in_string):
"""
Calculate the checksum for a given input string.
Args:
in_string (str): The input string to calculate the checksum for.
Returns:
None: The function directly calls another function to continue the process.
Raises:
ValueError: If the input string is not of the expected length.
"""
key_length = len(in_string)
# in_string is a str converting in_string to bytes in m_key_code
m_key_code = str.encode(in_string)
check_sum = 1
for idx, n in enumerate(m_key_code[2:], 2):
if n0 <= n <= n9:
temp_sum = n - n0
else:
temp_sum = n - nA
check_sum += idx + temp_sum + (idx * temp_sum)
check_sum = ((100 - check_sum) % 100)
dummy = [n0 + (check_sum % 10), n0 + ((check_sum // 10) % 10)]
m_key_code = bytes(dummy) + m_key_code[2:]
print("DEBUG: Calculated Checksum:", check_sum)
print("DEBUG: Modified Key Code with Checksum:", m_key_code)
return m_key_code
def encode_option_code_calc(m_key_code):
"""
Calculate the option code based on the modified key code.
Args:
m_key_code (bytes): The modified key code used for option code calculation.
Returns:
None: The function calls another function to print the option code.
Raises:
TypeError: If the input is not in bytes format.
"""
# Setting max check sum size to 26000
max_check_sum = 26000
# Encipher Key
option_key = []
checksum = 0
for idx, n in enumerate(m_key_code[:]):
print(f"DEBUG: Original Char: {n}")
if n0 <= n <= n9:
temp_sum = (n - n0)
m_key_code = (encode_rotor_10[(temp_sum + max_check_sum - checksum) % 10] + 0)
else:
temp_sum = n - nA
m_key_code = (encode_rotor_10[(temp_sum + max_check_sum - checksum) % 26] + nA)
checksum += idx + temp_sum + (idx * temp_sum)
option_key.append(int(m_key_code))
print(f"DEBUG: Transformed Char: {m_key_code}, Checksum: {checksum}")
print(f"DEBUG: Original Option Key: {option_key}")
return option_key
And here is the decode, which does not currently work.
Code:
# enigma_decode.py
from enigma_common import decode_rotor_10, decode_rotor_26
from enigma_common import n0, n9, nA, nZ
def decode(encoded_option_code):
# Convert the encoded option code to bytes
encoded_bytes = bytes(encoded_option_code, 'utf-8')
# Validate the checksum
if not decode_checksum_calc(encoded_bytes):
print("Invalid checksum.")
return None, None # Return a tuple of None values
# Continue with the decoding process...
decoded_data = decode_with_rotor_10(encoded_bytes)
original_key = decode_with_rotor_26(decoded_data)
# Return the decoded data and the original key
return decoded_data, original_key
def decode_with_rotor_10(encoded_data):
decoded_data = ''
checksum = 0
for idx, char in enumerate(encoded_data):
str_char = chr(char) # Convert byte to its character representation
if str_char.isdigit():
byte_val = ord(str_char) # Convert character to its ASCII value
adjusted_val = (byte_val - n0) % 10 # Reverse the transformation
decoded_val = decode_rotor_10[adjusted_val]
# Adjust for the checksum effect (if applicable)
temp_sum = decoded_val
checksum += idx + temp_sum + (idx * temp_sum)
print(f"DEBUG: idx={idx}, char={char}, byte_va{byte_val}, adjusted_val={adjusted_val}, decoded_val={decoded_val}, temp_sum={temp_sum}, checksum={checksum}")
# Add the decoded value to the decoded data
decoded_data += str(decoded_val)
else:
decoded_data += str_char # Non-digit characters are left as is
return decoded_data
def decode_with_rotor_26(encoded_data):
"""
Calculate the original key code based on the option key for rotor 26.
Args:
encoded_data (list): The encoded data used for original key code calculation.
Returns:
list: The original key code.
Raises:
TypeError: If the input is not in list format.
"""
# Setting max check sum size to 26000
max_check_sum = 26000
# Decipher Key
original_key = []
checksum = 0
for idx, n in enumerate(encoded_data[:]):
if nA <= n <= nZ:
temp_sum = n - nA
original_key_code = (decode_rotor_26[(temp_sum + max_check_sum - checksum) % 26] + nA)
checksum += idx + temp_sum + (idx * temp_sum)
original_key.append(int(original_key_code))
return original_key
def decode_checksum_calc(encoded_string):
"""
Validate the checksum for a given encoded string.
Args:
encoded_string (bytes): The encoded string to validate the checksum for.
Returns:
bool: True if the checksum is valid, False otherwise.
"""
# Extract the checksum from the encoded string
extracted_checksum = (encoded_string[1] - n0) * 10 + (encoded_string[0] - n0)
# Calculate the checksum for the remaining string
check_sum = 1
for idx, n in enumerate(encoded_string[2:], 2):
if n0 <= n <= n9:
temp_sum = n - n0 # Reverse the transformation
else:
temp_sum = n - nA
check_sum += idx + temp_sum + (idx * temp_sum)
print(f"DEBUG: idx={idx}, n={n}, temp_sum={temp_sum}, check_sum={check_sum}") # Debug statement
check_sum = ((100 - check_sum) % 100)
print("DEBUG: Extracted Checksum:", extracted_checksum)
print("DEBUG: Calculated Checksum:", check_sum)
# Return True if the calculated checksum matches the extracted checksum
return check_sum == extracted_checksum
The Rotors are here.
Code:
"""
This module contains global variables and lists used for encoding and decoding in the Enigma machine.
"""
n0, n9, nA, nZ = b'09A'
# Encode Enigma Rotors 10 & 26
encode_rotor_10 = [5, 4, 1, 8, 7, 3, 0, 2, 9, 6]
encode_rotor_26 = [16, 8, 25, 5, 23, 21, 18, 17, 2, 1, 7, 24, 15, 11, 9, 6, 3, 0, 19, 12, 22, 14, 10, 4, 20, 13]
# Decode Enigma Rotors 10 & 26 - Inverse of encode
decode_rotor_10 = [6, 2, 7, 5, 1, 0, 9, 4, 3, 8]
decode_rotor_26 = [17, 9, 8, 16, 23, 3, 15, 10, 1, 14, 22, 13, 19, 25, 21, 12, 0, 7, 6, 18, 24, 5, 20, 4, 11, 2]
Below is the encoding and debugging output.
Code:
DEBUG: Calculated Checksum: 48
DEBUG: Modified Key Code with Checksum: b'8469641234567001'
DEBUG: Original Char: 56
DEBUG: Transformed Char: 9, Checksum: 8
DEBUG: Original Option Key: [9]
DEBUG: Original Char: 52
DEBUG: Transformed Char: 0, Checksum: 17
DEBUG: Original Option Key: [9, 0]
DEBUG: Original Char: 54
DEBUG: Transformed Char: 6, Checksum: 37
DEBUG: Original Option Key: [9, 0, 6]
DEBUG: Original Char: 57
DEBUG: Transformed Char: 1, Checksum: 76
DEBUG: Original Option Key: [9, 0, 6, 1]
DEBUG: Original Char: 54
DEBUG: Transformed Char: 5, Checksum: 110
DEBUG: Original Option Key: [9, 0, 6, 1, 5]
DEBUG: Original Char: 52
DEBUG: Transformed Char: 7, Checksum: 139
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7]
DEBUG: Original Char: 49
DEBUG: Transformed Char: 1, Checksum: 152
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1]
DEBUG: Original Char: 50
DEBUG: Transformed Char: 5, Checksum: 175
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5]
DEBUG: Original Char: 51
DEBUG: Transformed Char: 9, Checksum: 210
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9]
DEBUG: Original Char: 52
DEBUG: Transformed Char: 7, Checksum: 259
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9, 7]
DEBUG: Original Char: 53
DEBUG: Transformed Char: 0, Checksum: 324
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9, 7, 0]
DEBUG: Original Char: 54
DEBUG: Transformed Char: 1, Checksum: 407
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9, 7, 0, 1]
DEBUG: Original Char: 55
DEBUG: Transformed Char: 5, Checksum: 510
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9, 7, 0, 1, 5]
DEBUG: Original Char: 48
DEBUG: Transformed Char: 5, Checksum: 523
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9, 7, 0, 1, 5, 5]
DEBUG: Original Char: 48
DEBUG: Transformed Char: 2, Checksum: 537
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9, 7, 0, 1, 5, 5, 2]
DEBUG: Original Char: 49
DEBUG: Transformed Char: 7, Checksum: 568
DEBUG: Original Option Key: [9, 0, 6, 1, 5, 7, 1, 5, 9, 7, 0, 1, 5, 5, 2, 7]
Option Code: 9061 5715 9701 5527
Would you like to generate another Option Code (Y/N): n
OK, goodbye! :-)
~/Dev/sr/P/Enigma_v3.5 on main !3 /usr/local/bin/python3 /Users/krisarmstrong/Developer/src/Python3/Enigma_v3.5/enigma_main.py
Enigma V3.5
Do you want to (E)ncode or (D)ecode? Enter E or D: d
Enter the option code to decode: 9061571597015527
DEBUG: idx=2, n=54, temp_sum=6, check_sum=21
DEBUG: idx=3, n=49, temp_sum=1, check_sum=28
DEBUG: idx=4, n=53, temp_sum=5, check_sum=57
DEBUG: idx=5, n=55, temp_sum=7, check_sum=104
DEBUG: idx=6, n=49, temp_sum=1, check_sum=117
DEBUG: idx=7, n=53, temp_sum=5, check_sum=164
DEBUG: idx=8, n=57, temp_sum=9, check_sum=253
DEBUG: idx=9, n=55, temp_sum=7, check_sum=332
DEBUG: idx=10, n=48, temp_sum=0, check_sum=342
DEBUG: idx=11, n=49, temp_sum=1, check_sum=365
DEBUG: idx=12, n=53, temp_sum=5, check_sum=442
DEBUG: idx=13, n=53, temp_sum=5, check_sum=525
DEBUG: idx=14, n=50, temp_sum=2, check_sum=569
DEBUG: idx=15, n=55, temp_sum=7, check_sum=696
DEBUG: Extracted Checksum: 9
DEBUG: Calculated Checksum: 4
Invalid checksum.
Decoding failed.
69641234567001 was the number encoded to 9061571597015527 however it does not decode 9061571597015527 back to 69641234567001.