pythonencryptioncryptographydes

DES Encryption using Python


Error on DES Encryption using Python

this code is to encrypt/decrypt the plain text(Base64)/ciphertext respectively using DES[Data Encryption Standard], giving plain text and Key as input while executing the code. And the coding is done in Python programming language.

    mp = {'A': "000000",
          'B': "000001",
          'C': "000010",
          'D': "000011",
          'E': "000100",
          'F': "000101",
          'G': "000110",
          'H': "000111",
          'I': "001000",
          'J': "001001",
          'K': "001010",
          'L': "001011",
          'M': "001100",
          'N': "001101",
          'O': "001110",
          'P': "001111",
          'Q': "010000",
          'R': "010001",
          'S': "010010",
          'T': "010011",
          'U': "010100",
          'V': "010101",
          'W': "010110",
          'X': "010111",
          'Y': "011000",
          'Z': "011001",
          'a': "011010",
          'b': "011011",
          'c': "011100",
          'd': "011101",
          'e': "011110",
          'f': "011111",
          'g': "100000",
          'h': "100001",
          'i': "100010",
          'j': "100011",
          'k': "100100",
          'l': "100101",
          'm': "100110",
          'n': "100111",
          'o': "101000",
          'p': "101001",
          'q': "101010",
          'r': "101011",
          's': "101100",
          't': "101101",
          'u': "101110",
          'v': "101111",
          'w': "110000",
          'x': "110001",
          'y': "110010",
          'z': "110011",
          '0': "110100",
          '1': "110101",
          '2': "110110",
          '3': "110111",
          '4': "111000",
          '5': "111001",
          '6': "111010",
          '7': "111011",
          '8': "111100",
          '9': "111101",
          '+': "111110",
          '/': "111111"}
    bin = ""
    for i in range(0,len(s)):
        bin = bin + mp[s[i]]
    return bin

def bintobase64(s):
    mp = {  "000000": 'A',
        "000001": 'B',
        "000010": 'C',
        "000011": 'D',
        "000100": 'E',
        "000101": 'F',
        "000110": 'G',
        "000111": 'H',
        "001000": 'I',
        "001001": 'J',
        "001010": 'K',
        "001011": 'L',
        "001100": 'M',
        "001101": 'N',
        "001110": 'O',
        "001111": 'P',
        "010000": 'Q',
        "010001": 'R',
        "010010": 'S',
    "010011": 'T',
        "010100": 'U',
        "010101": 'V',
        "010110": 'W',
        "010111": 'X',
        "011000": 'Y',
        "011001": 'Z',
        "011010": 'a',
        "011011": 'b',
        "011100": 'c',
        "011101": 'd',
        "011110": 'e',
        "011111": 'f',
        "100000": 'g',
        "100001": 'h',
        "100010": 'i',
        "100011": 'j',
    "100100": 'k',
        "100101": 'l',
        "100110": 'm',
        "100111": 'n',
        "101000": 'o',
        "101001": 'p',
        "101010": 'q',
        "101011": 'r',
        "101100": 's',
        "101101": 't',
        "101110": 'u',
        "101111": 'v',
        "110000": 'w',
        "110001": 'x',
        "110010": 'y',
        "110011": 'z',
        "110100": '0',
        "110101": '1',
        "110110": '2',
        "110111": '3',
        "111000": '4',
        "111001": '5',
        "111010": '6',
        "111011": '7',
        "111100": '8',
        "111101": '9',
        "111110": '+',
        "111111": '/'}
    base64 = ""
    for i in range(0, len(s), 6):
        ch = ""
        ch = ch + s[i]
        ch = ch + s[i + 1]
        ch = ch + s[i + 2]
        ch = ch + s[i + 3]
        ch = ch + s[i + 4]
        ch = ch + s[i + 5]
        base64 = base64 + mp[ch]
    return ch



# Binary to decimal conversion
def bin2dec(binary):
       
    binary1 = binary
    decimal, i, n = 0, 0, 0
    while(binary != 0):
        dec = binary % 10
        decimal = decimal + dec * pow(2, i)
        binary = binary//10
        i += 1
    return decimal
 
# Decimal to binary conversion
def dec2bin(num):
    res = bin(num).replace("0b", "")
    if(len(res)%4 != 0):
        div = len(res) / 4
        div = int(div)
        counter =(4 * (div + 1)) - len(res)
        for i in range(0, counter):
            res = '0' + res
    return res
 
# Permute function to rearrange the bits
def permute(k, arr, n):
    permutation = ""
    for i in range(0, n):
        permutation = permutation + k[arr[i] - 1]
    return permutation
 
# shifting the bits towards left by nth shifts
def shift_left(k, nth_shifts):
    s = ""
    for i in range(nth_shifts):
        for j in range(1,len(k)):
            s = s + k[j]
        s = s + k[0]
        k = s
        s = ""
    return k   
 
# calculating xow of two strings of binary number a and b
def xor(a, b):
    ans = ""
    for i in range(len(a)):
        if a[i] == b[i]:
            ans = ans + "0"
        else:
            ans = ans + "1"
    return ans
 
# Table of Position of 64 bits at initial level: Initial Permutation Table
initial_perm = [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]
 
# Expansion D-box Table
exp_d = [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 ]
 
# Straight Permutation Table
per = [ 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 ]
 
# S-box Table
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] ] ]
   
# Final Permutation Table
final_perm = [ 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 ]
 
def encrypt(pt, rkb, rk):
    pt = base64tobin(pt)
     
    # Initial Permutation
    pt = permute(pt, initial_perm, 64)
    print("After initial permutation", bintobase64(pt))
     
    # Splitting
    left = pt[0:32]
    right = pt[32:64]
    for i in range(0, 16):
        #  Expansion D-box: Expanding the 32 bits data into 48 bits
        right_expanded = permute(right, exp_d, 48)
         
        # XOR RoundKey[i] and right_expanded
        xor_x = xor(right_expanded, rkb[i])
 
        # S-boxex: substituting the value from s-box table by calculating row and column
        sbox_str = ""
        for j in range(0, 8):
            row = bin2dec(int(xor_x[j * 6] + xor_x[j * 6 + 5]))
            col = bin2dec(int(xor_x[j * 6 + 1] + xor_x[j * 6 + 2] + xor_x[j * 6 + 3] + xor_x[j * 6 + 4]))
            val = sbox[j][row][col]
            sbox_str = sbox_str + dec2bin(val)
             
        # Straight D-box: After substituting rearranging the bits 
        sbox_str = permute(sbox_str, per, 32)
         
        # XOR left and sbox_str
        result = xor(left, sbox_str)
        left = result
         
        # Swapper
        if(i != 15):
            left, right = right, left
        print("Round ", i + 1, " ", bintobase64(left), " ", bintobase64(right), " ", rk[i])
     
    # Combination
    combine = left + right
     
    # Final permutation: final rearranging of bits to get cipher text
    cipher_text = permute(combine, final_perm, 64)
    return cipher_text
 
pt = input("give me the plain text:")
key = input("give me the key:")
 
# Key generation
# --hex to binary
key = base64tobin(key)
 
# --parity bit drop table
keyp = [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 ]
 
# getting 56 bit key from 64 bit using the parity bits
key = permute(key, keyp, 56)
 
# Number of bit shifts
shift_table = [1, 1, 2, 2,
                2, 2, 2, 2,
                1, 2, 2, 2,
                2, 2, 2, 1 ]
 
# Key- Compression Table : Compression of key from 56 bits to 48 bits
key_comp = [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 ]
 
# Splitting
left = key[0:28]    # rkb for RoundKeys in binary
right = key[28:56]  # rk for RoundKeys in hexadecimal
 
rkb = []
rk  = []
for i in range(0, 16):
    # Shifting the bits by nth shifts by checking from shift table
    left = shift_left(left, shift_table[i])
    right = shift_left(right, shift_table[i])
     
    # Combination of left and right string
    combine_str = left + right
     
    # Compression of key from 56 to 48 bits
    round_key = permute(combine_str, key_comp, 48)
  
    rkb.append(round_key)
    rk.append(bintobase64(round_key))
 
print("Encryption")
cipher_text = bintobase64(encrypt(pt, rkb, rk))
print("Cipher Text : ",cipher_text)
 
print("Decryption")
rkb_rev = rkb[::-1]
rk_rev = rk[::-1]
text = bintobase64(encrypt(cipher_text, rkb_rev, rk_rev))
print("Plain Text : ",text)

I have converted the hextobin code to base64tobin code I am getting errors, please help me with my encryption/decryption.

I found the hextobin code in geeks for geeks and I have tried to convert it to base64tobin code, It is hard for me to find my errors.


Solution

  • Your code is a bit confusing. the mp dictionary has wrong binary values.

    For example a = '01100001' # or '0b1100001' and not 011010. I don't know if you have a purpose by using this specific dictionary, but if it's not necessary, I would recommend to use the standard system python uses.

    Firstly let's make your code simpler...

    I guess the first mp dictionary is in a function that converts string to binary:

    def Str2Bin(c):
        return '{0:08b}'.format(int(c.encode().hex(),16))
    

    here is the way to convert a character to binary correctly. If you insist to make a dictionary (I don't think it's necessary), you can add this line in the code:

    from string import printable
    str2bin_dict = {Str2Bin(i):i for i in printable}
    

    Next, I think your bintobase64 function is false. When I try this bintobase64("111111") I get as response this '111111'.

    The correct way is this one:

    import base64
    def Bin2Base64(b):
        return base64.b64encode(chr(int(b,2)).encode())
    

    and if you insist to create the mp dictionary, you can do this: mp = = {Bin2Base64(i):i for i in str2bin_dict.keys()}

    But here is a confusion. Base64 is not like binary.

    'a' -> 'YQ=='
    'b' -> 'Yg=='
    'ab' -> 'YWI='
    

    I guess that you have created mp to convert every letter to it's base64 format. You can do it, but why? Just convert the whole text to base64 and vice versa:

    import base64
    base64.b64encode('Hello World'.encode()).decode() # 'SGVsbG8gV29ybGQ='
    base64.b64decode('SGVsbG8gV29ybGQ='.encode()).decode() # Hello World
    

    These are my hints. I think they are more than enough to figure out what's going on ;)