Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ic:laboratoare:05 [2018/09/25 22:01]
dan.dragan
ic:laboratoare:05 [2020/11/04 14:00] (current)
philip.dumitru [Exercise 3 (5p)]
Line 1: Line 1:
-<​hidden>​ 
 ===== Laboratorul 05 - DES ===== ===== Laboratorul 05 - DES =====
  
 +In this lab we'll do some exercises with DES and some of its variants, as we discussed in the last lecture [[https://​drive.google.com/​file/​d/​1Fjybv6k5QudRB1bkAi5shVUGlUyTO_0U/​view|here]].
  
-In this lab we'll do some exercises with DES and some of its variantsas we discussed ​in the last lecture+<file python utils.py>​ 
-http://cs.curs.pub.ro/​2014/​pluginfile.php/​13095/​mod_resource/​content/​2/​sasc_curs4_5.pdf+import base64 
 + 
 +# CONVERSION FUNCTIONS 
 +def _chunks(string,​ chunk_size):​ 
 +    for i in range(0, len(string),​ chunk_size):​ 
 +        yield string[i:​i+chunk_size] 
 + 
 +def byte_2_bin(bval):​ 
 +    return bin(bval)[2:​].zfill(8) 
 + 
 +def _hex(x): 
 +    return format(x, ​'02x'​) 
 + 
 +def hex_2_bin(data):​ 
 +    return ''​.join(f'​{int(x16):​08b}'​ for x in _chunks(data,​ 2)) 
 + 
 +def str_2_bin(data)
 +    ​return ''​.join(f'​{ord(c):08b}' for c in data) 
 + 
 +def bin_2_hex(data):​ 
 +    return ''​.join(f'​{int(b,​ 2):​02x}'​ for b in _chunks(data,​ 8)) 
 + 
 +def str_2_hex(data):​ 
 +    return ''​.join(f'​{ord(c):​02x}'​ for c in data) 
 + 
 +def bin_2_str(data):​ 
 +    return ''​.join(chr(int(b,​ 2)) for b in _chunks(data,​ 8)) 
 + 
 +def hex_2_str(data):​ 
 +    return ''​.join(chr(int(x,​ 16)) for x in _chunks(data, ​2)) 
 + 
 +# XOR FUNCTIONS 
 +def strxor(a, b):  # xor two strings, trims the longer input 
 +    return ''​.join(chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)) 
 + 
 +def bitxor(a, b):  # xor two bit-strings,​ trims the longer input 
 +    return ''​.join(str(int(x) ^ int(y)) for (x, y) in zip(a, b)) 
 + 
 +def hexxor(a, b):  # xor two hex-strings,​ trims the longer input 
 +    return ''​.join(_hex(int(x,​ 16) ^ int(y, 16)) for (x, y) in zip(_chunks(a,​ 2), _chunks(b, 2))) 
 + 
 +# BASE64 FUNCTIONS 
 +def b64decode(data):​ 
 +    return bytes_to_string(base64.b64decode(string_to_bytes(data))) 
 + 
 +def b64encode(data):​ 
 +    return bytes_to_string(base64.b64encode(string_to_bytes(data))) 
 + 
 +# PYTHON3 '​BYTES'​ FUNCTIONS 
 +def bytes_to_string(bytes_data):​ 
 +    return bytes_data.decode() ​ # default utf-8 
 + 
 +def string_to_bytes(string_data):​ 
 +    return string_data.encode() ​ # default utf-8 
 +     
 +# THIS ONE IS NEW 
 +def hex_2_bytes(hex_data):​ 
 +    return bytes.fromhex(hex_data) ​ # default utf-8 
 +</​file>​
  
 ==== Exercise 1 (2p) ==== ==== Exercise 1 (2p) ====
Line 22: Line 80:
  
 The goal of this exercise is to implement the meet-in-the-middle attack on double DES. The goal of this exercise is to implement the meet-in-the-middle attack on double DES.
-For this, you are given a starter code (see below), implemented using the Pycrypto ​library.+For this, you are given a starter code (see below), implemented using the pycrypto ​library.
  
 Perform the following tasks: Perform the following tasks:
Line 28: Line 86:
 === A. Install the pycrypto library === === A. Install the pycrypto library ===
  
-See https://​pypi.python.org/​pypi/​pycrypto.+<​hidden>​this is outdated: ​https://​pypi.python.org/​pypi/​pycrypto.</​hidden>​ 
 +See https://​pypi.org/​project/​pycryptodome/​ 
  
 === B. Implement 2DES === === B. Implement 2DES ===
  
-Starting from the starter code (see below), write methods to encrypt and decrypt using double-DES (2DES), defined as follows: +Starting from the starter code (see below), write methods to encrypt and decrypt using double-DES (2DES), defined as follows: 2DES( (k1,k2), m) = DES(k1, DES(k2, m))
-<​quote> ​2DES( (k1,k2), m) = DES(k1, DES(k2, m))</​quote>​+
  
 === C. Test 2DES === === C. Test 2DES ===
Line 42: Line 101:
  
 c2 = '​54826ea0937a2c34d47f4595f3844445520c0995331e5d492f55abcf9d8dfadf'​ c2 = '​54826ea0937a2c34d47f4595f3844445520c0995331e5d492f55abcf9d8dfadf'​
- 
-as hex strings (i.e. you need to decode them to get the actual byte strings to use with DES, e.g. c1.decode('​hex'​)) 
  
 Decrypt them using the following keys: Decrypt them using the following keys:
Line 66: Line 123:
 In this last but most important task, you are given the following ciphertext/​plaintext pairs for 2DES with unknown keys: In this last but most important task, you are given the following ciphertext/​plaintext pairs for 2DES with unknown keys:
  
-m1 = '​Pocainta'​ (in byte string, i.e. can be used directly with Pycrypto ​DES)+m1 = '​Pocainta'​ (in byte string, i.e. can be used directly with pycrypto ​DES)
  
 c1 = '​9f98dbd6fe5f785d'​ (in hex string, you need to hex-decode) c1 = '​9f98dbd6fe5f785d'​ (in hex string, you need to hex-decode)
Line 80: Line 137:
 Your task is now to find the full keys k1 and k2 by applying the meet-in-the-middle attack over 2DES. Your task is now to find the full keys k1 and k2 by applying the meet-in-the-middle attack over 2DES.
  
-To build a table, ​recommend using a list of tuples, where you add new (key,enc) pairs as follows:+To build a table, ​we recommend using a list of tuples, where you add new (key,enc) pairs as follows:
 <​code>​ <​code>​
 tb = [] tb = []
-tb.append(('​keyval',​ 'encva'))+tb.append(('​keyval',​ 'encval'))
 </​code>​ </​code>​
  
Line 101: Line 158:
  
 <code python desmitm.py>​ <code python desmitm.py>​
-import ​sys +from utils import ​*
-import random +
-import string+
 from operator import itemgetter from operator import itemgetter
-import time 
 import bisect import bisect
 from Crypto.Cipher import DES from Crypto.Cipher import DES
- 
-def strxor(a, b): # xor two strings (trims the longer input) 
-  return ""​.join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)]) 
- 
-def hexxor(a, b): # xor two hex strings (trims the longer input) 
-  ha = a.decode('​hex'​) 
-  hb = b.decode('​hex'​) 
-  return ""​.join([chr(ord(x) ^ ord(y)).encode('​hex'​) for (x, y) in zip(ha, hb)]) 
- 
-def bitxor(a, b): # xor two bit strings (trims the longer input) 
-  return ""​.join([str(int(x)^int(y)) for (x, y) in zip(a, b)]) 
- 
-def str2bin(ss):​ 
-  """​ 
-    Transform a string (e.g. '​Hello'​) into a string of bits 
-  """​ 
-  bs = ''​ 
-  for c in ss: 
-    bs = bs + bin(ord(c))[2:​].zfill(8) 
-  return bs 
- 
-def str2int(ss):​ 
-  """​ 
-    Transform a string (e.g. '​Hello'​) into a (long) integer by converting 
-    first to a bistream 
-  """​ 
-  bs = str2bin(ss) 
-  li = int(bs, 2) 
-  return li 
- 
-def hex2bin(hs):​ 
-  """​ 
-    Transform a hex string (e.g. '​a2'​) into a string of bits (e.g.10100010) 
-  """​ 
-  bs = ''​ 
-  for c in hs: 
-    bs = bs + bin(int(c,​16))[2:​].zfill(4) 
-  return bs 
- 
-def bin2hex(bs):​ 
-  """​ 
-    Transform a bit string into a hex string 
-  """​ 
-  bv = int(bs,2) 
-  return int2hexstring(bv) 
- 
-def byte2bin(bval):​ 
-  """​ 
-    Transform a byte (8-bit) value into a bitstring 
-  """​ 
-  return bin(bval)[2:​].zfill(8) 
- 
-def int2hexstring(bval):​ 
-  """​ 
-    Transform an int value into a hexstring (even number of characters) 
-  """​ 
-  hs = hex(bval)[2:​] 
-  lh = len(hs) 
-  return hs.zfill(lh + lh%2) 
  
 def get_index(a,​ x): def get_index(a,​ x):
-  'Locate the leftmost value exactly equal to x in list a' +    """​Locate the leftmost value exactly equal to x in list a"""​ 
-  i = bisect.bisect_left(a,​ x) +    i = bisect.bisect_left(a,​ x) 
-  if i != len(a) and a[i] == x: +    if i != len(a) and a[i] == x: 
-    return i +        return i 
-  else: +    else: 
-    return -1+        return -1
  
 def des_enc(k, m): def des_enc(k, m):
-  ​"""​ +    ​"""​ 
-  Encrypt a message m with a key k using DES as follows: +    Encrypt a message m with a key k using DES as follows: 
-  c = DES(k, m)+    c = DES(k, m)
  
-  ​Args: +    ​Args: 
-    m should be a bytestring (i.e. a sequence of characters such as '​Hello'​ or '​\x02\x04'​) +        m should be a bytestring (i.e. a sequence of characters such as '​Hello'​ or '​\x02\x04'​) 
-    k should be a bytestring of length exactly 8 bytes.+        k should be a bytestring of length exactly 8 bytes.
  
-  ​Note that for DES the key is given as 8 bytes, where the last bit of +    ​Note that for DES the key is given as 8 bytes, where the last bit of 
-  each byte is just a parity bit, giving the actual key of 56 bits, as expected for DES. +    each byte is just a parity bit, giving the actual key of 56 bits, as expected for DES. 
-  The parity bits are ignored.+    The parity bits are ignored.
  
-  ​Return: +    ​Return: 
-    The bytestring ciphertext c +        The bytestring ciphertext c 
-  """​ +    """​ 
-  d = DES.new(k) +    d = DES.new(k, DES.MODE_ECB
-  c = d.encrypt(m) +    c = d.encrypt(m) 
- +    return c
-  ​return c+
  
 def des_dec(k, c): def des_dec(k, c):
-  ​"""​ +    ​"""​ 
-  Decrypt a message c with a key k using DES as follows: +    Decrypt a message c with a key k using DES as follows: 
-  m = DES(k, c)+    m = DES(k, c)
  
-  ​Args: +    ​Args: 
-    c should be a bytestring (i.e. a sequence of characters such as '​Hello'​ or '​\x02\x04'​) +        c should be a bytestring (i.e. a sequence of characters such as '​Hello'​ or '​\x02\x04'​) 
-    k should be a bytestring of length exactly 8 bytes.+        k should be a bytestring of length exactly 8 bytes.
  
-  ​Note that for DES the key is given as 8 bytes, where the last bit of +    ​Note that for DES the key is given as 8 bytes, where the last bit of 
-  each byte is just a parity bit, giving the actual key of 56 bits, as expected for DES. +    each byte is just a parity bit, giving the actual key of 56 bits, as expected for DES. 
-  The parity bits are ignored.+    The parity bits are ignored.
  
-  ​Return: +    ​Return: 
-    The bytestring plaintext m +        The bytestring plaintext m 
-  """​ +    """​ 
-  d = DES.new(k) +    d = DES.new(k, DES.MODE_ECB
-  m = d.decrypt(c) +    m = d.decrypt(c) 
- +    return m
-  ​return m+
   ​   ​
 def main(): def main():
 +    # Exercitiu pentru test des2_enc
 +    key1 = '​Smerenie'​
 +    key2 = '​Dragoste'​
 +    m1_given = '​Fericiti cei saraci cu duhul, ca'
 +    c1 = '​cda98e4b247612e5b088a803b4277710f106beccf3d020ffcc577ddd889e2f32'​
 +    # TODO: implement des2_enc and des2_dec
 +    m1 = des2_dec(key1,​ key2, hex_2_str(c1))
  
-  # Exercitiu pentru test des2_enc +    print('​ciphertext:​ ' + c1) 
-  key1 = '​Smerenie'​ +    print('​plaintext:​ ' + m1) 
-  key2 = '​Dragoste'​ +    print('​plaintext in hexa: ' + str_2_hex(m1)
-  m1_given = '​Fericiti cei saraci cu duhul, ca' +     
-  c1 = '​cda98e4b247612e5b088a803b4277710f106beccf3d020ffcc577ddd889e2f32'​ +    # TODO: run meet-in-the-middle attack for the following plaintext/​ciphertext 
-  # TODO: implement des2_enc and des2_dec +    m1 = '​Pocainta'​ 
-  m1 = des2_dec(key1, key2, c1.decode('​hex'​)) +    c1 = '​9f98dbd6fe5f785d'​ # in hex string 
- +    m2 = '​Iertarea'​ 
-  print '​ciphertext:​ ' + c1 +    c2 = '​6e266642ef3069c2'​
-  print '​plaintext:​ ' + m1 +
-  print '​plaintext in hexa: ' + m1.encode('​hex'​+
- +
-  # TODO: run meet-in-the-middle attack for the following plaintext/​ciphertext +
-  m1 = '​Pocainta'​ +
-  c1 = '​9f98dbd6fe5f785d'​ # in hex string +
-  m2 = '​Iertarea'​ +
-  c2 = '​6e266642ef3069c2'​+
   ​   ​
-  ​# Note: you only need to search for the first 2 bytes of the each key: +    ​# Note: you only need to search for the first 2 bytes of the each key: 
-  k1 = '??​oIkvH5'​ +    k1 = '??​oIkvH5'​ 
-  k2 = '??​GK4EoU'​ +    k2 = '??​GK4EoU'​
- +
  
 if __name__ == "​__main__":​ if __name__ == "​__main__":​
-  ​main()+    ​main()
 </​code>​ </​code>​
  
-<​hidden>​The solution is {{:​ic:​laboratoare:​lab5_sol.zip|here}}.</​hidden>​ 
-</​hidden>​ 
ic/laboratoare/05.1537902072.txt.gz · Last modified: 2018/09/25 22:01 by dan.dragan
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0