This shows you the differences between two versions of the page.
|
ic:laboratoare:05 [2020/11/03 16:54] acosmin.maria |
ic:laboratoare:05 [2020/11/04 14:00] (current) philip.dumitru [Exercise 3 (5p)] |
||
|---|---|---|---|
| Line 58: | Line 58: | ||
| def string_to_bytes(string_data): | def string_to_bytes(string_data): | ||
| return string_data.encode() # default utf-8 | 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> | </file> | ||
| Line 82: | 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 === | ||
| Line 152: | 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> | ||