296 lines
9.4 KiB
Python
296 lines
9.4 KiB
Python
# Miguel Muniz
|
|
# CS454
|
|
|
|
import argparse
|
|
|
|
#Constants/permutations
|
|
PC1 = [
|
|
57, 49, 41, 33, 25, 17, 9,
|
|
1, 58, 50, 42, 34, 26, 18,
|
|
10, 2, 59, 51, 43, 35, 27,
|
|
19, 11, 3, 60, 52, 44, 36,
|
|
63, 55, 47, 39, 31, 23, 15,
|
|
7, 62, 54, 46, 38, 30, 22,
|
|
14, 6, 61, 53, 45, 37, 29,
|
|
21, 13, 5, 28, 20, 12, 4
|
|
]
|
|
|
|
PC2 = [
|
|
14, 17, 11, 24, 1, 5, 3, 28,
|
|
15, 6, 21, 10, 23, 19, 12, 4,
|
|
26, 8, 16, 7, 27, 20, 13, 2,
|
|
41, 52, 31, 37, 47, 55, 30, 40,
|
|
51, 45, 33, 48, 44, 49, 39, 56,
|
|
34, 53, 46, 42, 50, 36, 29, 32
|
|
]
|
|
|
|
IP = [
|
|
58, 50, 42, 34, 26, 18, 10, 2,
|
|
60, 52, 44, 36, 28, 20, 12, 4,
|
|
62, 54, 46, 38, 30, 22, 14, 6,
|
|
64, 56, 48, 40, 32, 24, 16, 8,
|
|
57, 49, 41, 33, 25, 17, 9, 1,
|
|
59, 51, 43, 35, 27, 19, 11, 3,
|
|
61, 53, 45, 37, 29, 21, 13, 5,
|
|
63, 55, 47, 39, 31, 23, 15, 7
|
|
]
|
|
|
|
P = [
|
|
16, 7, 20, 21,
|
|
29, 12, 28, 17,
|
|
1, 15, 23, 26,
|
|
5, 18, 31, 10,
|
|
2, 8, 24, 14,
|
|
32, 27, 3, 9,
|
|
19, 13, 30, 6,
|
|
22, 11, 4, 25
|
|
]
|
|
|
|
FP = [
|
|
40, 8, 48, 16, 56, 24, 64, 32,
|
|
39, 7, 47, 15, 55, 23, 63, 31,
|
|
38, 6, 46, 14, 54, 22, 62, 30,
|
|
37, 5, 45, 13, 53, 21, 61, 29,
|
|
36, 4, 44, 12, 52, 20, 60, 28,
|
|
35, 3, 43, 11, 51, 19, 59, 27,
|
|
34, 2, 42, 10, 50, 18, 58, 26,
|
|
33, 1, 41, 9, 49, 17, 57, 25
|
|
]
|
|
|
|
E = [
|
|
32, 1, 2, 3, 4, 5,
|
|
4, 5, 6, 7, 8, 9,
|
|
8, 9, 10, 11, 12, 13,
|
|
12, 13, 14, 15, 16, 17,
|
|
16, 17, 18, 19, 20, 21,
|
|
20, 21, 22, 23, 24, 25,
|
|
24, 25, 26, 27, 28, 29,
|
|
28, 29, 30, 31, 32, 1
|
|
]
|
|
|
|
#S-Boxes
|
|
sbox = [[[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
|
|
[0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
|
|
[4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
|
|
[15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]],
|
|
|
|
[[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
|
|
[3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
|
|
[0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
|
|
[13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]],
|
|
|
|
[[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
|
|
[13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
|
|
[13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
|
|
[1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]],
|
|
|
|
[[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
|
|
[13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
|
|
[10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
|
|
[3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]],
|
|
|
|
[[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
|
|
[14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
|
|
[4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
|
|
[11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]],
|
|
|
|
[[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
|
|
[10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
|
|
[9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
|
|
[4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]],
|
|
|
|
[[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
|
|
[13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
|
|
[1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
|
|
[6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]],
|
|
|
|
[[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
|
|
[1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
|
|
[7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
|
|
[2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]]]
|
|
|
|
LEFT_SHIFT = [
|
|
1, 1, 2, 2, 2, 2, 2, 2,
|
|
1, 2, 2, 2, 2, 2, 2, 1
|
|
]
|
|
subkeys_left = []
|
|
subkeys_right = []
|
|
subkeys = []
|
|
|
|
left_half_f = []
|
|
right_half_f = []
|
|
|
|
data_block = ""
|
|
|
|
def hex_to_binary(hex):
|
|
return bin(int(hex, 16))[2:].zfill(64)
|
|
|
|
def binary_to_hex(binary):
|
|
return hex(int(binary, 2))[2:].zfill(16)
|
|
|
|
def DES_Encrypt(data_block, key):
|
|
|
|
data_block = hex_to_binary(data_block)
|
|
key = hex_to_binary(key)
|
|
|
|
#print ("binary key:", key)
|
|
|
|
key = permute(key, PC1)
|
|
#print ("permutated key:", key)
|
|
|
|
# generate 16 subkeys
|
|
left_key = key[:28]
|
|
right_key = key[28:]
|
|
subkeys_left.append(left_key)
|
|
subkeys_right.append(right_key)
|
|
|
|
# left shift
|
|
for i in range(16):
|
|
left_key = left_key[LEFT_SHIFT[i]:] + left_key[:LEFT_SHIFT[i]]
|
|
right_key = right_key[LEFT_SHIFT[i]:] + right_key[:LEFT_SHIFT[i]]
|
|
subkeys_left.append(left_key)
|
|
subkeys_right.append(right_key)
|
|
# print ("left key:",left_key)
|
|
# print ("right key:",right_key)
|
|
subkeys.append(permute(left_key + right_key, PC2))
|
|
|
|
|
|
# Initial Permutation
|
|
data_block = permute(data_block, IP)
|
|
#print ("Initial Permutation:", data_block)
|
|
|
|
# Split data_block into left and right halves
|
|
left_half = data_block[:32]
|
|
right_half = data_block[32:]
|
|
# left_half_f.append(left_half)
|
|
# right_half_f.append(right_half)
|
|
# print ("left half:", left_half)
|
|
# print ("right half:", right_half)
|
|
|
|
# 16 rounds of DES
|
|
for i in range(16):
|
|
# Expansion
|
|
expanded_right = permute(right_half, E)
|
|
#print ("expanded right half:", expanded_right)
|
|
|
|
# XOR with subkey
|
|
xor_result = int(''.join(expanded_right), 2) ^ int(''.join(subkeys[i]), 2)
|
|
xor_result = bin(xor_result)[2:].zfill(48)
|
|
#print ("XOR result:", xor_result)
|
|
|
|
# S-Box substitution
|
|
sbox_result = ""
|
|
for j in range(8):
|
|
row = int(xor_result[j*6] + xor_result[j*6 + 5], 2)
|
|
col = int(xor_result[j*6 + 1:j*6 + 5], 2)
|
|
sbox_result += bin(sbox[j][row][col])[2:].zfill(4)
|
|
#print ("S-Box result:", sbox_result)
|
|
|
|
# Permutation
|
|
permuted_result = permute(sbox_result, P)
|
|
#print ("Permutated result:", permuted_result)
|
|
|
|
# XOR with left half
|
|
xor_result = int(''.join(permuted_result), 2) ^ int(''.join(left_half), 2)
|
|
xor_result = bin(xor_result)[2:].zfill(32)
|
|
#print ("XOR result:", xor_result)
|
|
|
|
# Swap left and right halves
|
|
left_half = right_half
|
|
right_half = xor_result
|
|
|
|
left_half_f.append(left_half)
|
|
right_half_f.append(right_half)
|
|
|
|
print ("left half:", left_half)
|
|
print ("right half:", right_half)
|
|
|
|
# Final permutation
|
|
data_block = permute(right_half + left_half, FP)
|
|
data_block = str(data_block).replace("[","").replace("]","").replace(",","").replace(" ","").replace("'","")
|
|
#print ("Final Permutation:", data_block)
|
|
data_block = binary_to_hex(data_block)
|
|
print ("Encrypted:", data_block)
|
|
|
|
def permute(data_block, permutation):
|
|
return [data_block[i - 1] for i in permutation]
|
|
|
|
def DES_Decrypt(data_block, key):
|
|
pass
|
|
|
|
|
|
def parse_variables(file_path):
|
|
variables = {}
|
|
try:
|
|
with open(file_path, 'r') as file:
|
|
for line in file:
|
|
# Remove any extra spaces and ignore empty lines
|
|
line = line.strip()
|
|
if ':' in line and line:
|
|
key, value = line.split(':', 1)
|
|
variables[key.strip()] = value.strip()
|
|
except FileNotFoundError:
|
|
print(f"Error: The file {file_path} was not found.")
|
|
return variables
|
|
|
|
def output_file(output_file, data_block):
|
|
with open(output_file, 'w') as file:
|
|
# write all the sub keys to the file remove brackets quotations and commas
|
|
for i in range(17):
|
|
file.write(f"C{i}=")
|
|
file.write(str(subkeys_left[i]).replace("[","").replace("]","").replace(",","").replace(" ","").replace("'",""))
|
|
file.write("\n")
|
|
file.write(f"D{i}=")
|
|
file.write(str(subkeys_right[i]).replace("[","").replace("]","").replace(",","").replace(" ","").replace("'",""))
|
|
file.write("\n")
|
|
file.write("\n")
|
|
|
|
for i in range(16):
|
|
file.write(f"K{i+1}=")
|
|
file.write(str(subkeys[i]).replace("[","").replace("]","").replace(",","").replace(" ","").replace("'",""))
|
|
file.write("\n")
|
|
|
|
for i in range(17):
|
|
file.write(f"L{i}=")
|
|
file.write(str(left_half_f).replace("[","").replace("]","").replace(",","").replace(" ","").replace("'",""))
|
|
file.write("\n")
|
|
file.write(f"R{i}=")
|
|
file.write(str(right_half_f).replace("[","").replace("]","").replace(",","").replace(" ","").replace("'",""))
|
|
|
|
file.write("\n")
|
|
file.write(data_block)
|
|
|
|
|
|
def main():
|
|
# Set up command-line argument parsing
|
|
parser = argparse.ArgumentParser(description='Parse variables for encryption or decryption.')
|
|
parser.add_argument('input_file', type=str, help='Path to the text file containing the variables.')
|
|
parser.add_argument('output_file', type=str, help='Path to the text file containing the output.')
|
|
|
|
# Parse the arguments
|
|
args = parser.parse_args()
|
|
|
|
# Parse the file and retrieve variables
|
|
variables = parse_variables(args.input_file)
|
|
|
|
# Get data_block and key from the parsed variables
|
|
data_block = variables.get('data_block', '')
|
|
key = variables.get('key', '')
|
|
operation = variables.get('operation','')
|
|
|
|
# Print the variables
|
|
print(f"Data Block: {data_block}")
|
|
print(f"Key: {key}")
|
|
print(f"Operation: {operation}")
|
|
if operation == 'encryption' :
|
|
|
|
DES_Encrypt(data_block, key)
|
|
|
|
else :
|
|
DES_Decrypt(data_block, key)
|
|
|
|
# path to output file
|
|
output_file(args.output_file, data_block)
|
|
|
|
if __name__ == "__main__":
|
|
main() |