Advertisement
Guest User

Untitled

a guest
Nov 22nd, 2019
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.92 KB | None | 0 0
  1. import pyDes
  2. import random
  3.  
  4. # Compute the Hamming weight of a byte
  5. def hw(b):
  6.     w = 0
  7.     # For each bit in a byte, shift one to the
  8.     # right and add 1 if the least significant
  9.     # bit is set.
  10.     for i in range(8):
  11.         w += (b >> i) & 1
  12.     return w
  13.  
  14. # Sets the key parity bit of a DES key byte
  15. def set_parity(b):
  16.     # If Hamming weight is even,
  17.     # flip least-significant bit
  18.     if hw(b) % 2 == 0:
  19.         return b ^ 0x01
  20.     # Else, return b as-is.
  21.     return b
  22.  
  23. # Take a 20-bit number and generate a DES key with
  24. # parity bits in significant bytes, followed by
  25. # zero-padding.
  26. def get_key(n):
  27.     # 20 = 2*8+4. Subtracting parity bits gives
  28.     # effective key bits: 2*7+6, so we shift
  29.     # each whole byte by 7 * the number of less
  30.     # significant bytes + effective length of least
  31.     # significant byte, take modulo 2^7 = 128 and
  32.     # finally shift one to the left to make space
  33.     # for the parity bit.
  34.  
  35.     # Byte 3 (least-significant byte): take modulo
  36.     # 2^l, where l is the size of the partial byte
  37.     # in bits, and shift by 8-l. This gives 8-6=2.
  38.     b3 = set_parity((n % 64) << 2)
  39.     # Byte 2: Shift by combined length of less
  40.     # signficiant bytes: 6
  41.     b2 = set_parity(((n >> 6) % 128) << 1)
  42.     # Byte 3: Shift by combined length of less
  43.     # signficiant bytes: 7+6=13
  44.     b1 = set_parity(((n >> 13) % 128) << 1)
  45.    
  46.     # Assemble the generated bytes into a
  47.     # bytearray object.
  48.     key = bytearray([b1, b2, b3, 0, 0, 0, 0, 0])
  49.  
  50.     # Return the key as a bytes object for DES
  51.     # library compatibility.
  52.     return bytes(key)
  53.  
  54. # Wrapper function for single DES encryption.
  55. def des_enc(data, key):
  56.     # Initialize DES cipher object using the
  57.     # provided key and use it to encrypt the
  58.     # provided data.
  59.     return pyDes.des(key).encrypt(data)
  60.  
  61. # Wrapper function for single DES decryption.
  62. def des_dec(data, key):
  63.     # Initialize DES cipher object using the
  64.     # provided key and use it to decrypt the
  65.     # provided data.
  66.     return pyDes.des(key).decrypt(data)
  67.  
  68. # This is the heart of the operation. This
  69. # function takes a plaintext-ciphertext pair,
  70. # along with a key size (in bits), and performs
  71. # a meet-in-the-middle attack.
  72. def hack_double_des(plaintext, ciphertext, key_size=56):
  73.     # Initialize two dictionary objects, one for
  74.     # each side of the attack. These will contain
  75.     # the keys already tested, indexed by the
  76.     # values resulting from encryption and
  77.     # decryption, respectively.
  78.     key_dict_e = {}
  79.     key_dict_d = {}
  80.    
  81.     # TODO: implement an LC pseudo-random range generator function
  82.     # To efficiently iterate through huge ranges without having to
  83.     # allocate so much memory.
  84.     key_deck = range(pow(2, key_size))
  85.     #random.shuffle(key_deck)
  86.  
  87.     # Compute the size of a thousandth step over the keyspace.
  88.     # This is used to display the progress in terms of keyspace
  89.     # coverage.
  90.     permille = pow(2, key_size) // 1000
  91.    
  92.     # Randomly cycle through the keyspace.
  93.     for i, j in enumerate(key_deck):
  94.         # Generate DES key from current random value. This is the
  95.         # key guess for the current iteration.
  96.         k = get_key(j)
  97.  
  98.         # If the current index is a whole multiple of a thousandth
  99.         # step over the keyspace, print the current coverage
  100.         # percentage.
  101.         if i % permille == 0:
  102.             print("{}% of keyspace covered".format((i / permille)/10.0))
  103.  
  104.         # Encrypt the plaintext using the current key guess.
  105.         c = des_enc(plaintext, k)
  106.         # If the same intermediate value has been found by decrypting
  107.         # the ciphertext, return the current key guess as k1 and the
  108.         # key stored at the index of the intermediate value as k2.
  109.         if c in key_dict_d.keys():
  110.             return k, key_dict_d[c]
  111.         # Else, Store the current key guess at the index of the
  112.         # intermediate value.
  113.         else:
  114.             key_dict_e[c] = k
  115.  
  116.         # Decrypt the ciphertext using the current key guess.
  117.         m = des_dec(ciphertext, k)
  118.         # If the same intermediate value has been found by encrypting
  119.         # the plaintext, return the key stored at the index of the
  120.         # intermediate value as k1 and the current key guess as k2.
  121.         if m in key_dict_e.keys():
  122.             return key_dict_e[m], k
  123.         # Else, Store the current key guess at the index of the
  124.         # intermediate value.
  125.         else:
  126.             key_dict_d[m] = k
  127.  
  128.     # Abandon hope; all is lost. This should never happen.
  129.     return b'lol     ', b'nope    '
  130.  
  131. # Define some integers in the range [1 .. 2^20] and use them
  132. # to generate DES keys.
  133. k1 = get_key(193)
  134. k2 = get_key(5523)
  135.  
  136. # Define the plaintext for testing. This is known to the attacker.
  137. plaintext = b'ABCDEFGH'
  138. # Encrypt once using k1 and store for later use.
  139. middle = des_enc(plaintext, k1)
  140. # Encrypt again using k2 and store as ciphertext. This is known to
  141. # the attacker.
  142. ciphertext = des_enc(middle, k2)
  143.  
  144. # Print the actual keys for ease of analysis.
  145. print("Actual k1: %r" % k1)
  146. print("Actual k2: %r" % k2)
  147.  
  148. # Print the plaintext and ciphertext for ease of analysis.
  149. print("Plaintext:\t%r" % plaintext)
  150. print("Ciphertext:\t%r" % ciphertext)
  151.  
  152. # Hack the planet! But mostly double DES, using a 20-bit keyspace.
  153. keys = hack_double_des(plaintext, ciphertext, 20)
  154.  
  155. # Print the keys identified by the hack function for ease of analysis.
  156. print("Guess k1: %r" % keys[0])
  157. print("Guess k2: %r" % keys[1])
  158.  
  159. # Generate the intermediate value produced using each of the
  160. # identified keys.
  161. res1 = des_enc(plaintext, keys[0])
  162. res2 = des_dec(ciphertext, keys[1])
  163.  
  164. # Assert that the intermediate values are identical.
  165. assert res1 == res2
  166. # Assert that the first identified key is identical to k1.
  167. assert keys[0] == k1
  168. # Assert that the second identified key is identical to k2.
  169. assert keys[1] == k2
  170.  
  171. # Inform the user that all tests have passed.
  172. print("All tests passed!")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement