Advertisement
Guest User

Eugene Tan

a guest
Sep 7th, 2009
201
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.19 KB | None | 0 0
  1. """
  2. DES cipher module
  3.  
  4. Usage:
  5. >>> plaintext = 0x0123456789abcdef
  6. >>> key = 0x3b3898371520f75e
  7.  
  8. Encryption:
  9. >>> ciphertext = bin_array_to_int(des(plaintext, key, debug=False))
  10. >>> hex(ciphertext)
  11. '0xaa39b9777efc3c14L'
  12.  
  13. Decryption:
  14. >>> decrypted = des(ciphertext, key, decrypt=True, debug=False)
  15. >>> hex(bin_array_to_int(decrypted))
  16. '0x123456789abcdefL'
  17.  
  18. Note that python removes zeros in front
  19. """
  20.  
  21. # initial permutation
  22. IP = [
  23.     58, 50, 42, 34, 26, 18, 10, 2,
  24.     60, 52, 44, 36, 28, 20, 12, 4,
  25.     62, 54, 46, 38, 30, 22, 14, 6,
  26.     64, 56, 48, 40, 32, 24, 16, 8,
  27.     57, 49, 41, 33, 25, 17,  9, 1,
  28.     59, 51, 43, 35, 27, 19, 11, 3,
  29.     61, 53, 45, 37, 29, 21, 13, 5,
  30.     63, 55, 47, 39, 31, 23, 15, 7
  31. ]
  32.  
  33. # final permutation IP^-1
  34. FP = [
  35.     40, 8, 48, 16, 56, 24, 64, 32,
  36.     39, 7, 47, 15, 55, 23, 63, 31,
  37.     38, 6, 46, 14, 54, 22, 62, 30,
  38.     37, 5, 45, 13, 53, 21, 61, 29,
  39.     36, 4, 44, 12, 52, 20, 60, 28,
  40.     35, 3, 43, 11, 51, 19, 59, 27,
  41.     34, 2, 42, 10, 50, 18, 58, 26,
  42.     33, 1, 41,  9, 49, 17, 57, 25
  43. ]
  44.  
  45. # expansion
  46. E = [
  47.     32,  1,  2,  3,  4,  5,
  48.      4,  5,  6,  7,  8,  9,
  49.      8,  9, 10, 11, 12, 13,
  50.     12, 13, 14, 15, 16, 17,
  51.     16, 17, 18, 19, 20, 21,
  52.     20, 21, 22, 23, 24, 25,
  53.     24, 25, 26, 27, 28, 29,
  54.     28, 29, 30, 31, 32, 1
  55. ]
  56.  
  57. # permutation choice 1
  58. PC1 = [
  59.     57, 49, 41, 33, 25, 17,  9,
  60.      1, 58, 50, 42, 34, 26, 18,
  61.     10,  2, 59, 51, 43, 35, 27,
  62.     19, 11,  3, 60, 52, 44, 36,
  63.     63, 55, 47, 39, 31, 23, 15,
  64.      7, 62, 54, 46, 38, 30, 22,
  65.     14,  6, 61, 53, 45, 37, 29,
  66.     21, 13,  5, 28, 20, 12,  4
  67. ]
  68.  
  69. # permutation choice 2
  70. PC2 = [
  71.     14, 17, 11, 24,  1,  5,
  72.      3, 28, 15,  6, 21, 10,
  73.     23, 19, 12,  4, 26,  8,
  74.     16,  7, 27, 20, 13,  2,
  75.     41, 52, 31, 37, 47, 55,
  76.     30, 40, 51, 45, 33, 48,
  77.     44, 49, 39, 56, 34, 53,
  78.     46, 42, 50, 36, 29, 32
  79. ]
  80.  
  81. ###########
  82. # S-Boxes #
  83. ###########
  84. S1 = [
  85.     [14,  4, 13, 1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9, 0,  7],
  86.      [0, 15,  7, 4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5, 3,  8],
  87.      [4,  1, 14, 8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10, 5,  0],
  88.     [15, 12,  8, 2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0, 6, 13]
  89. ]
  90.  
  91. S2 = [
  92.     [15,  1,  8, 14,  6, 11,  3,  4,  9, 7,  2, 13, 12, 0,  5, 10],
  93.      [3, 13,  4,  7, 15,  2,  8, 14, 12, 0,  1, 10,  6, 9, 11,  5],
  94.      [0, 14,  7, 11, 10,  4, 13,  1,  5, 8, 12,  6,  9, 3,  2, 15],
  95.     [13,  8, 10,  1,  3, 15,  4,  2, 11, 6,  7, 12,  0, 5, 14,  9]
  96. ]
  97.  
  98. S3 = [
  99.     [10,  0,  9, 14, 6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8],
  100.     [13,  7,  0,  9, 3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1],
  101.     [13,  6,  4,  9, 8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7],
  102.      [1, 10, 13,  0, 6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12]
  103. ]
  104.  
  105. S4 = [
  106.      [7, 13, 14, 3,  0,  6,  9, 10,  1, 2, 8,  5, 11, 12,  4, 15],
  107.     [13,  8, 11, 5,  6, 15,  0,  3,  4, 7, 2, 12,  1, 10, 14,  9],
  108.     [10,  6,  9, 0, 12, 11,  7, 13, 15, 1, 3, 14,  5,  2,  8,  4],
  109.      [3, 15,  0, 6, 10,  1, 13,  8,  9, 4, 5, 11, 12,  7,  2, 14]
  110. ]
  111.  
  112. S5 = [
  113.      [2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13, 0, 14,  9],
  114.     [14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3, 9,  8,  6],
  115.      [4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6, 3,  0, 14],
  116.     [11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10, 4,  5,  3]
  117. ]
  118.  
  119. S6 = [
  120.     [12,  1, 10, 15, 9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11],
  121.     [10, 15,  4,  2, 7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8],
  122.      [9, 14, 15,  5, 2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6],
  123.      [4,  3,  2, 12, 9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13]
  124. ]
  125.  
  126. S7 = [
  127.      [4, 11,  2, 14, 15, 0,  8, 13,  3, 12, 9,  7,  5, 10, 6,  1],
  128.     [13,  0, 11,  7,  4, 9,  1, 10, 14,  3, 5, 12,  2, 15, 8,  6],
  129.      [1,  4, 11, 13, 12, 3,  7, 14, 10, 15, 6,  8,  0,  5, 9,  2],
  130.      [6, 11, 13,  8,  1, 4, 10,  7,  9,  5, 0, 15, 14,  2, 3, 12]
  131. ]
  132.  
  133. S8 = [
  134.     [13,  2,  8, 4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7],
  135.      [1, 15, 13, 8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2],
  136.      [7, 11,  4, 1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8],
  137.      [2,  1, 14, 7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11]
  138. ]
  139.  
  140. SBOX = [S1, S2, S3, S4, S5, S6, S7, S8]
  141.  
  142. # P-Box
  143. P = [
  144.     16,  7, 20, 21,
  145.     29, 12, 28, 17,
  146.      1, 15, 23, 26,
  147.      5, 18, 31, 10,
  148.      2,  8, 24, 14,
  149.     32, 27,  3,  9,
  150.     19, 13, 30,  6,
  151.     22, 11,  4, 25
  152. ]
  153.  
  154. def s(input):
  155.     """Run sboxes on input, returning the result
  156.  
  157.     >>> input = pad(int_to_bin_array(0b001001100001110100011001001011111001101000011010), 48)
  158.     >>> pprint(s(input), 4)
  159.     '1110 1101 0010 0001 0111 0110 1100 0000'
  160.     """
  161.     buf = input
  162.     sbox_result = []
  163.     for i in range(len(SBOX)):
  164.         s_input, buf = split(buf, 6)
  165.         s_val = sbox(s_input, SBOX[i])
  166.         sbox_result += pad(int_to_bin_array(s_val), 4)
  167.     return sbox_result
  168.  
  169. def sbox(input, s_table):
  170.     """Substitute block according to given sbox
  171.  
  172.     >>> sbox(list('111001'), S8)
  173.     3
  174.     """
  175.     col = bin_array_to_int(input[1:5])
  176.     row = bin_array_to_int(input[0] + input[-1])
  177.     return s_table[row][col]
  178.  
  179. def permutate(bits, perm_table):
  180.     """Permutate block according to given table
  181.  
  182.     Uses perm tables which start from index 1
  183.  
  184.     >>> val = pad(int_to_bin_array(0x675a69675e5a6b5a), 64)
  185.     >>> hex(bin_array_to_int(permutate(val, IP)))
  186.     '0xffb2194d004df6fbL'
  187.     """
  188.     #init y
  189.     y = []
  190.     for i in range(len(perm_table)):
  191.         y.append(0)
  192.  
  193.     # permutate
  194.     for i in range(len(perm_table)):
  195.         index = perm_table[i]
  196.         y[i] = bits[index - 1]
  197.     return y
  198.  
  199. def bin_array_to_int(bits):
  200.     """Converts a bit array to an integer
  201.    
  202.     >>> bin_array_to_int(list('1011'))
  203.     11
  204.     """
  205.     return int(''.join(bits), 2)
  206.  
  207. def int_to_bin_array(x):
  208.     """Converts an integer to a bit array
  209.  
  210.     >>> int_to_bin_array(11)
  211.     ['1', '0', '1', '1']
  212.     """
  213.     return list(bin(x))[2:]
  214.  
  215. def split(bits, pos):
  216.     """Convenience method for splitting a list
  217.    
  218.     >>> split([1, 2, 3, 4, 5, 6], 3)
  219.     [[1, 2, 3], [4, 5, 6]]
  220.     """
  221.     return [bits[0:pos], bits[pos:]]
  222.  
  223. def c_left_shift(bits, val):
  224.     """Circular left shift by given value
  225.    
  226.     >>> pprint(c_left_shift(list('0100010011000000011010111101'), 1), 7)
  227.     '1000100 1100000 0011010 1111010'
  228.     >>> pprint(c_left_shift(list('0001001100000001101011110101'), 2), 7)
  229.     '0100110 0000001 1010111 1010100'
  230.     >>> pprint(c_left_shift(list('0010011101100010000111111111'), 2), 7)
  231.     '1001110 1100010 0001111 1111100'
  232.     """
  233.     start = len(bits) - 1
  234.     for i in range(val):
  235.         temp = bits[0]
  236.         for i in range(start):
  237.             bits[i] = bits[i + 1]
  238.         bits[-1] = temp
  239.     return bits
  240.  
  241. def c_right_shift(bits, val):
  242.     """Circular right shift by given value
  243.    
  244.     >>> c_right_shift(list('011001'), 1)
  245.     ['1', '0', '1', '1', '0', '0']
  246.     >>> c_right_shift(list('011001'), 2)
  247.     ['0', '1', '0', '1', '1', '0']
  248.     """
  249.     start = len(bits) - 1
  250.     for i in range(val):
  251.         temp = []
  252.         for i in range(start, 0, -1):
  253.             if i > start - 1:
  254.                 temp.append(bits[i])
  255.             bits[i] = bits[i - 1]
  256.         for i in range(len(temp)):
  257.             bits[i] = temp[i]
  258.     return bits
  259.  
  260. def pad(x, num, val='0'):
  261.     """Left-pad bit array to desired number of bits
  262.    
  263.     >>> pad(list('0110'), 5)
  264.     ['0', '0', '1', '1', '0']
  265.     >>> pad(list('0110'), 5, '1')
  266.     ['1', '0', '1', '1', '0']
  267.     """
  268.     return ([val] * (num - len(x))) + x
  269.  
  270. def xor(a, b):
  271.     """Takes in two binary arrays and XORs them
  272.    
  273.     >>> xor(list('0110'), list('1100'))
  274.     ['1', '0', '1', '0']
  275.     """
  276.     xor_result = bin_array_to_int(a) ^ bin_array_to_int(b)
  277.     return int_to_bin_array(xor_result)
  278.  
  279. def pprint(x, val=8):
  280.     """Returns formatted string from bit array, split by val
  281.    
  282.     >>> pprint(list('00001111'), 4)
  283.     '0000 1111'
  284.     """
  285.     formatted_string = ''
  286.     for i in range(len(x)):
  287.         if i != 0 and i % val == 0:
  288.             formatted_string += " "
  289.         formatted_string += x[i]
  290.     return formatted_string
  291.  
  292. def f(right, key, debug=True):
  293.     """f-function for DES
  294.    
  295.     >>> right = int_to_bin_array(0b11110000101010101111000010101010)
  296.     >>> key = int_to_bin_array(0b010111000000100001001100010101011000111101001111)
  297.     >>> pprint(f(right, key, False))
  298.     '10100000 10111100 11000010 10011101'
  299.     """
  300.     # expansion step
  301.     e = permutate(right, E)
  302.     if debug:
  303.         print "expansion        : ", pprint(e, 6), 'bits', len(e)
  304.  
  305.     # key mixing
  306.     xor_key_and_e = pad(xor(e, key), 48)
  307.     if debug:
  308.         print "xor_key_and_e    : ", pprint(xor_key_and_e, 6), 'bits', len(xor_key_and_e)
  309.  
  310.     # round substitution
  311.     sbox_result = s(xor_key_and_e)
  312.     if debug:
  313.         print "sbox_result      : ", pprint(sbox_result, 4), 'bits', len(sbox_result)
  314.  
  315.     # round permutation
  316.     pbox_result = permutate(sbox_result, P)
  317.     if debug:
  318.         print "pbox_result      : ", hex(bin_array_to_int(pbox_result)), 'bits', len(pbox_result)
  319.     return pbox_result
  320.  
  321. def key_schedule(c, d, round_index, shift_function, debug=True):
  322.     """Shift according to shift-function and permutate key schedule.
  323.    
  324.     Returns PC2, C and D in an array
  325.  
  326.     >>> c = pad(int_to_bin_array(0b0001001100000001101011110101), 28)
  327.     >>> d = pad(int_to_bin_array(0b0010011101100010000111111111), 28)
  328.     >>> round_index = 2
  329.     >>> ary = key_schedule(c, d, round_index, c_left_shift, False)
  330.     >>> pprint(ary[0], 6)
  331.     '110101 001110 010010 000101 110110 001011 010011 101111'
  332.     >>> pprint(ary[1] + ary[2], 7)
  333.     '0100110 0000001 1010111 1010100 1001110 1100010 0001111 1111100'
  334.     """
  335.     shift_val = 0
  336.     rot_one = [0, 1, 8, 15]
  337.     if round_index in rot_one:
  338.         shift_val = 1
  339.     if shift_val == 0:
  340.         shift_val = 2
  341.  
  342.     c = shift_function(c, shift_val)
  343.     d = shift_function(d, shift_val)
  344.     pc2 = permutate(c + d, PC2)
  345.     if debug:
  346.         print "pc2              : ", pprint(pc2, 6), 'bits', len(pc2)
  347.     return [pc2, c, d]
  348.  
  349. def subkeys(key, debug=True):
  350.     # permuted choice 1
  351.     pc1 = permutate(key, PC1)
  352.     if debug:
  353.         print "pc1              : ", pprint(pc1, 7), 'bits', len(pc1)
  354.     c, d = split(pc1, 28)
  355.     keys = []
  356.     for i in range(16):
  357.         pc2, c, d = key_schedule(c, d, i, c_left_shift, debug=debug)
  358.         keys.append(pc2)
  359.     return keys
  360.  
  361. def des(input, key, decrypt=False, debug=True):
  362.     """Encrypts/decrypts an input integer using DES
  363.  
  364.     >>> plaintext = 0x0123456789abcdef
  365.     >>> key = 0x3b3898371520f75e
  366.     >>> ciphertext = bin_array_to_int(des(plaintext, key, debug=False))
  367.     >>> hex(ciphertext)
  368.     '0xaa39b9777efc3c14L'
  369.     >>> decrypted = des(ciphertext, key, decrypt=True, debug=False)
  370.     >>> hex(bin_array_to_int(decrypted))
  371.     '0x123456789abcdefL'
  372.     """
  373.     # convert input and key to bit arrays
  374.     p = pad(int_to_bin_array(input), 64)
  375.     k = pad(int_to_bin_array(key), 64)
  376.     if debug:
  377.         print "padded p         : ", pprint(p)
  378.         print "padded k         : ", pprint(k)
  379.  
  380.     # generate round keys
  381.     round_keys = subkeys(k, debug)
  382.     if decrypt:
  383.         round_keys.reverse()
  384.  
  385.     # initial permutation
  386.     ip = permutate(list(p), IP)
  387.     if debug:
  388.         print "ip               : ", hex(bin_array_to_int(ip))
  389.  
  390.     # permuted choice 1
  391.     pc1 = permutate(k, PC1)
  392.     if debug:
  393.         print "pc1              : ", pprint(pc1, 7), 'bits', len(pc1)
  394.  
  395.     c, d = split(pc1, 28)
  396.     l, r = split(ip, 32)
  397.  
  398.     for i in range(16):
  399.         if debug:
  400.             print "\nround ", i
  401.             print "l                : ", pprint(l), 'bits', len(l)
  402.             print "r                : ", pprint(r), 'bits', len(r)
  403.             print "cd               : ", pprint(c+d, 7), 'bits', len(c+d)
  404.         f_result = f(r, round_keys[i], debug=debug)
  405.         xor_fresult_and_l = pad(xor(f_result, l), 32)
  406.         if debug:
  407.             print "xor_fresult_and_l    : ", hex(bin_array_to_int(xor_fresult_and_l)), 'bits', len(xor_fresult_and_l)
  408.         l = r
  409.         r = xor_fresult_and_l
  410.  
  411.     # swap l and r
  412.     l, r = r, l
  413.  
  414.     # final permutation
  415.     inv_ip = permutate(l + r, FP)
  416.     if debug:
  417.         print "inv ip           : ", hex(bin_array_to_int(inv_ip))
  418.     return inv_ip
  419.  
  420. if __name__ == '__main__':
  421.     import doctest
  422.     doctest.testmod()
  423.  
  424.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement