def permutation(arr, index):
return [arr[i - 1] for i in index]
def exp_permutation(arr, index):
return [arr[i - 1] for i in index]
def split(arr):
mid = len(arr) // 2
return arr[:mid], arr[mid:]
def bin2dec(arr):
return int("".join(map(str, arr)), 2)
def dec2bin(val, bits):
return list(map(int, format(val, f"0{bits}b")))
def combine(arr1, arr2):
return arr1 + arr2
def s_box(a, b):
S0 = [[1, 0, 3, 2], [3, 2, 1, 0], [0, 2, 1, 3], [3, 1, 3, 2]]
S1 = [[0, 1, 2, 3], [2, 0, 1, 3], [3, 0, 1, 0], [2, 1, 0, 3]]
rowS0 = bin2dec([a[0], a[3]])
colS0 = bin2dec([a[1], a[2]])
rowS1 = bin2dec([b[0], b[3]])
colS1 = bin2dec([b[1], b[2]])
opS0 = dec2bin(S0[rowS0][colS0], 2)
opS1 = dec2bin(S1[rowS1][colS1], 2)
return opS0 + opS1
def swap(left, right):
return right[:], left[:]
def xor(arr1, arr2):
return [a ^ b for a, b in zip(arr1, arr2)]
def left_rotate(arr, d):
return arr[d:] + arr[:d]
def key_generation(master_key):
P10_rule = [3, 5, 2, 7, 4, 10, 1, 9, 8, 6]
P8_rule = [6, 3, 7, 4, 8, 5, 10, 9]
key_p10 = permutation(master_key, P10_rule)
left, right = split(key_p10)
left1 = left_rotate(left, 1)
right1 = left_rotate(right, 1)
combined1 = combine(left1, right1)
k1 = permutation(combined1, P8_rule)
left2 = left_rotate(left1, 2)
right2 = left_rotate(right1, 2)
combined2 = combine(left2, right2)
k2 = permutation(combined2, P8_rule)
return k1, k2
def round_function(key, left, right):
EP_rule = [4, 1, 2, 3, 2, 3, 4, 1]
P4_rule = [2, 4, 3, 1]
right_ep = exp_permutation(right, EP_rule)
xor_result = xor(key, right_ep)
a, b = split(xor_result)
sbox_result = s_box(a, b)
p4_result = permutation(sbox_result, P4_rule)
left_result = xor(left, p4_result)
return left_result, right
def encrypt(plain_text, k1, k2):
IP_rule = [2, 6, 3, 1, 4, 8, 5, 7]
IP_inv_rule = [4, 1, 3, 5, 7, 2, 8, 6]
pt = permutation(plain_text, IP_rule)
left, right = split(pt)
left, right = round_function(k1, left, right)
left, right = swap(left, right)
left, right = round_function(k2, left, right)
combined = combine(left, right)
cipher = permutation(combined, IP_inv_rule)
return cipher
def decrypt(cipher_text, k1, k2):
return encrypt(cipher_text, k2, k1)
def str2bitlist(s):
return [int(c) for c in s]
def bitlist2str(b):
return ''.join(map(str, b))
# ---- Driver code ----
if __name__ == "__main__":
key = "1010000010"
plain_text = "11010111"
key_bits = str2bitlist(key)
pt_bits = str2bitlist(plain_text)
k1, k2 = key_generation(key_bits)
encrypted_bits = encrypt(pt_bits, k1, k2)
decrypted_bits = decrypt(encrypted_bits, k1, k2)
print("Original Text :", plain_text)
print("Encrypted Text:", bitlist2str(encrypted_bits))
print("Decrypted Text:", bitlist2str(decrypted_bits))