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> | ||