Differences

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

Link to this comparison view

ic:labs:05 [2021/11/01 15:51]
razvan.smadu [Exercitiul 3 (5p)]
ic:labs:05 [2023/10/09 23:22] (current)
razvan.smadu
Line 1: Line 1:
 ===== Laboratorul 05 - DES ===== ===== Laboratorul 05 - DES =====
  
-In acest laborator vom face niste exercitii ​ce folosesc algoritmul DES si variatii ​ale acestuia discutate la [[https://​drive.google.com/​file/​d/​1Fjybv6k5QudRB1bkAi5shVUGlUyTO_0U/​view|curs]]. ​+În acest laborator vom face niște exerciții ​ce folosesc algoritmul DES și variații ​ale acestuia discutate la [[https://​drive.google.com/​file/​d/​1Fjybv6k5QudRB1bkAi5shVUGlUyTO_0U/​view|curs]].
 Prezentarea PowerPoint pentru acest laborator poate fi găsită [[https://​drive.google.com/​file/​d/​1FU422fCHM24fRnMuzFd0OjhQqT6AQZ3X/​view?​usp=sharing|aici]]. Prezentarea PowerPoint pentru acest laborator poate fi găsită [[https://​drive.google.com/​file/​d/​1FU422fCHM24fRnMuzFd0OjhQqT6AQZ3X/​view?​usp=sharing|aici]].
 +Puteți lucra acest laborator folosind platforma Google Colab, accesând [[https://​colab.research.google.com/​github/​ACS-IC-labs/​IC-labs/​blob/​main/​labs/​lab05/​lab5.ipynb|acest]] link.
  
 +<​hidden>​
 +<spoiler Click pentru a vedea utils.py>​
 <file python utils.py>​ <file python utils.py>​
 import base64 import base64
-  +from typing import Generator 
-# CONVERSION FUNCTIONS + 
-def _chunks(string, chunk_size):​ + 
-    for i in range(0, len(string), chunk_size):​ +def _pad(data: str, size: int) -> str: 
-        yield string[i:​i+chunk_size] +    reminder = len(data) % size 
-  +    if reminder != 0: 
-def byte_2_bin(bval):​ +        data = "​0"​ * (size - reminder) + data 
-    """​ +    return data 
-      Transform ​a byte (8-bit) value into bitstring+ 
 + 
 +def _chunks(data: str, chunk_size: int-> Generator[str,​ None, None]: 
 +    data = _pad(data, chunk_size) 
 +    for i in range(0, len(data), chunk_size):​ 
 +        yield data[i : i + chunk_size] 
 + 
 + 
 +def _hex(data: int) -> str: 
 +    return format(data,​ "​02x"​) 
 + 
 + 
 +# Conversion functions 
 + 
 + 
 +def byte_2_bin(bval: int-> str
 +    """​Converts ​a byte value to a binary string. 
 + 
 +    Args: 
 +        bval (int)
 +            The byte value to be converted. It should be an integer between 
 +            0 and 255. 
 + 
 +    Returns: 
 +        str: The binary string representation of the byte value, where each bit 
 +        is encoded as character. The result has a fixed length of 8 characters 
 +        and is padded with leading zeros if necessary. 
 + 
 +    Examples: 
 +        >>>​ byte_2_bin(72) 
 +        '​01001000'​ 
 +        >>>​ byte_2_bin(66) 
 +        '​01000010'​
     """​     """​
     return bin(bval)[2:​].zfill(8)     return bin(bval)[2:​].zfill(8)
-  + 
-def _hex(x): + 
-    ​return format(x, '​02x'​+def hex_2_bin(data: str-> str
-  +    ​"""​Converts a hexadecimal string to a binary representation. 
-def hex_2_bin(data): + 
-    ​return ​''​.join(f'{int(x, 16):08b}' ​for x in _chunks(data,​ 2)) +    Args: 
-  +        data (str): The hexadecimal string to be converted. It should have an 
-def str_2_bin(data): +            even number of characters and only contain valid hexadecimal digits 
-    ​return ''​.join(f'{ord(c):08b}' for c in data+            (0-9, A-F, a-f)
-  + 
-def bin_2_hex(data): +    Returns: 
-    ​return ​''​.join(f'{int(b, 2):02x}' ​for b in _chunks(data,​ 8)) +        str: The binary representation of the hexadecimal string, where each 
-  +            pair of hexadecimal digits is encoded as an 8-bit binary number. 
-def str_2_hex(data): + 
-    ​return ​''​.join(f'{ord(c):02x}' ​for c in data) +    ​Examples: 
-  +        >>>​ hex_2_bin("​01abcd"​) 
-def bin_2_str(data):​ +        ​'000000011010101111001101' 
-    ​return ​''​.join(chr(int(b,​ 2)) for b in _chunks(data,​ 8)) +        >>>​ hex_2_bin("​0a"​) 
-  +        '​00001010'​ 
-def hex_2_str(data): +    """​ 
-    return ''​.join(chr(int(x,​ 16)) for x in _chunks(data,​ 2)) +    return ""​.join(f"{int(x, 16):08b}" ​for x in _chunks(data,​ 2)) 
-  + 
-# XOR FUNCTIONS + 
-def strxor(ab):  # xor two strings, ​trims the longer ​input +def bin_2_hex(data: str-> str
-    ​return ​''​.join(chr(ord(x) ^ ord(y)) for (x, y) in zip(ab)) +    ​"""​Converts a binary string to a hexadecimal representation. 
-  + 
-def bitxor(ab):  # xor two bit-strings, ​trims the longer ​input +    Args: 
-    ​return ​''​.join(str(int(x) ^ int(y)) for (x, y) in zip(ab)) +        data (str): The binary string to be converted. It should have a multiple 
-  +            of 8 characters and only contain valid binary digits ​(0 or 1)
-def hexxor(ab):  # 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))) +    Returns: 
-  +        str: The hexadecimal representation of the binary string, where each 
-BASE64 FUNCTIONS +            group of 8 binary digits is encoded as a pair of hexadecimal digits. 
-def b64decode(data): + 
-    ​return ​bytes_to_string(base64.b64decode(string_to_bytes(data))) +    Examples: 
-  +        >>>​ bin_2_hex("​000000011010101111001101"​
-def b64encode(data):​+        '​01abcd'​ 
 +        >>> ​bin_2_hex("​00001010"​
 +        '0a' 
 +    """​ 
 +    return ""​.join(f"{int(b, 2):02x}" ​for b in _chunks(data,​ 8)) 
 + 
 + 
 +def str_2_bin(data: str-> str
 +    ​"""​Converts a string to a binary representation. 
 + 
 +    Args: 
 +        data (str): The string to be converted. 
 + 
 +    Returns: 
 +        str: The binary representation of the string, where each character is 
 +            encoded as an 8-bit binary number. 
 + 
 +    Examples: 
 +        >>>​ str_2_bin("​Hello"​) 
 +        ​'0100100001100101011011000110110001101111' 
 +        >>>​ str_2_bin("​IC"​) 
 +        '​0100100101000011'​ 
 +    """​ 
 +    return ""​.join(f"{ord(c):08b}" ​for c in data) 
 + 
 + 
 +def bin_2_str(data: str-> str
 +    ​"""​Converts a binary string to a string. 
 + 
 +    Args: 
 +        data (str): The binary string to be converted. It should have a multiple 
 +            of 8 characters and only contain valid binary digits (0 or 1). 
 + 
 +    Returns: 
 +        str: The string representation of the binary string, where each group 
 +            of 8 binary digits is decoded as a character. 
 + 
 +    Examples: 
 +        >>>​ bin_2_str("​0100100001100101011011000110110001101111"​) 
 +        ​'Hello' 
 +        >>>​ bin_2_str("​0100100101000011"​) 
 +        '​IC'​ 
 +    """​ 
 +    return ""​.join(chr(int(b,​ 2)) for b in _chunks(data,​ 8)) 
 + 
 + 
 +def str_2_hex(data: str-> str: 
 +    """​Converts a string to a hexadecimal representation. 
 + 
 +    Args: 
 +        data (str): The string to be converted. 
 + 
 +    Returns: 
 +        str: The hexadecimal representation of the string, where each character 
 +            is encoded as a pair of hexadecimal digits. 
 + 
 +    Examples: 
 +        >>>​ str_2_hex("​Hello"​) 
 +        '​48656c6c6f'​ 
 +        >>>​ str_2_hex("​IC"​) 
 +        '​4943'​ 
 +    """​ 
 +    return ​""​.join(f"​{ord(c):​02x}"​ for c in data) 
 + 
 + 
 +def hex_2_str(data:​ str) -> str: 
 +    """​Converts a hexadecimal string to a string. 
 + 
 +    Args: 
 +        data (str): The hexadecimal string to be converted. It should have an 
 +            even number of characters and only contain valid hexadecimal digits 
 +            (0-9, A-F, a-f). 
 + 
 +    Returns: 
 +        str: The string representation of the hexadecimal string, where each 
 +            pair of hexadecimal digits is decoded as a character. 
 + 
 +    Examples: 
 +        >>>​ hex_2_str("​48656c6c6f"​) 
 +        ​'Hello' 
 +        >>>​ hex_2_str("​4943"​) 
 +        '​IC'​ 
 +    """​ 
 +    return ""​.join(chr(int(x,​ 16)) for x in _chunks(data,​ 2)) 
 + 
 + 
 +# XOR functions 
 + 
 + 
 +def strxor(operand_1: stroperand_2: str-> str: 
 +    """​Performs a bitwise exclusive OR (XOR) operation on two strings. 
 + 
 +    Args: 
 +        operand_1 (str): The first string to be XORed. 
 +        operand_2 (str): The second string to be XORed. 
 + 
 +    Returns: 
 +        str: The result of the XOR operation on the two strings, ​where each 
 +            character is encoded as an 8-bit binary number. The result has 
 +            the same length as the shorter ​input string. 
 + 
 +    ​Examples: 
 +        >>>​ strxor("​Hello",​ "​IC"​) 
 +        ​'\\x01&' 
 +        >>>​ strxor("​secret",​ "​key"​) 
 +        '​\\x18\\x00\\x1a'​ 
 +    """​ 
 +    return ""​.join(chr(ord(x) ^ ord(y)) for (x, y) in zip(operand_1operand_2)) 
 + 
 + 
 +def bitxor(operand_1: stroperand_2: str-> str: 
 +    """​Performs a bitwise exclusive OR (XOR) operation on two bit-strings. 
 + 
 +    Args: 
 +        operand_1 (str): The first bit-string to be XORed. It should only 
 +            contain valid binary digits (0 or 1). 
 +        operand_2 (str): The second bit-string to be XORed. It should only 
 +            contain valid binary digits (0 or 1). 
 + 
 +    Returns: 
 +        str: The result of the XOR operation on the two bit-strings, ​where each 
 +            bit is encoded as a character. The result has the same length as 
 +            the shorter ​input bit-string. 
 + 
 +    ​Examples: 
 +        >>>​ bitxor("​01001000",​ "​01000010"​) 
 +        ​'00001010' 
 +        >>>​ bitxor("​10101010",​ "​00110011"​) 
 +        '​10011001'​ 
 +    """​ 
 +    return ""​.join(str(int(x) ^ int(y)) for (x, y) in zip(operand_1operand_2)) 
 + 
 + 
 +def hexxor(operand_1: stroperand_2: str-> str: 
 +    """​Performs a bitwise exclusive OR (XOR) operation on two hexadecimal 
 +    strings. 
 + 
 +    Args: 
 +        operand_1 (str): The first hexadecimal string to be XORed. It should 
 +            have an even number of characters and only contain valid hexadecimal 
 +            digits (0-9, A-F, a-f). 
 +        operand_2 (str): The second hexadecimal string to be XORed. It should 
 +            have an even number of characters and only contain valid 
 +            digits (0-9, A-F, a-f). 
 + 
 +    Returns: 
 +        str: The result of the XOR operation on the two hexadecimal ​strings, 
 +            where each pair of hexadecimal digits is encoded as a pair of 
 +            hexadecimal digits. The result has the same length as the shorter 
 +            ​input hexadecimal string. 
 + 
 +    ​Examples: 
 +        >>>​ hexxor("​48656c6c6f",​ "​42696e67"​) 
 +        ​'0a0c020b' 
 +        >>>​ hexxor("​736563726574",​ "​6b6579"​) 
 +        '​18001a'​ 
 +    """​ 
 +    return ""​.join( 
 +        ​_hex(int(x, 16) ^ int(y, 16)) 
 +        ​for (x, y) in zip(_chunks(operand_1, 2), _chunks(operand_2, 2)) 
 +    ​) 
 + 
 + 
 +Python3 '​bytes'​ functions 
 + 
 + 
 +def bytes_to_string(bytes_data: bytearray | bytes-> str
 +    ​"""​Converts a byte array or a byte string to a string. 
 + 
 +    Args: 
 +        bytes_data (bytearray | bytes): The byte array or the byte string to be 
 +            converted. It should be encoded in UTF-8 format. 
 + 
 +    Returns: 
 +        str: The string representation of the byte array or the byte string, 
 +            decoded using UTF-8 encoding. 
 + 
 +    Examples: 
 +        >>> ​bytes_to_string(b'​Hello'​) 
 +        '​Hello'​ 
 +        >>>​ bytes_to_string(bytearray(b'​IC'​)) 
 +        '​IC'​ 
 +    """​ 
 +    return bytes_data.decode(encoding="​utf-8"​) 
 + 
 + 
 +def string_to_bytes(string_data:​ str-> bytes: 
 +    """​Converts a string to a byte string. 
 + 
 +    Args: 
 +        string_data (str): The string to be converted. 
 + 
 +    Returns: 
 +        bytes: The byte string representation of the string, encoded using 
 +        UTF-8 encoding. 
 + 
 +    Examples: 
 +        >>>​ string_to_bytes('​Hello'​) 
 +        b'​Hello'​ 
 +        >>>​ string_to_bytes('​IC'​) 
 +        b'​IC'​ 
 +    """​ 
 +    return string_data.encode(encoding="​utf-8"​) 
 + 
 + 
 +# Base64 functions 
 + 
 + 
 +def b64encode(data: str-> str: 
 +    """​Encodes a string to base64. 
 + 
 +    Parameters:​ 
 +        data (str): The string to be encoded. 
 + 
 +    Returns: 
 +        str: The base64 encoded string, using UTF-8 encoding. 
 + 
 +    Examples: 
 +        >>>​ b64encode("​Hello"​) 
 +        '​SGVsbG8='​ 
 +        >>>​ b64encode("​IC"​) 
 +        '​SUM='​ 
 +    """​
     return bytes_to_string(base64.b64encode(string_to_bytes(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 
-</​file>​ 
  
-==== Exercitiul ​1 (2p) ====+ 
 +def b64decode(data:​ str) -> str: 
 +    """​Decodes a base64 encoded string. 
 + 
 +    Args: 
 +        data (str): The base64 encoded string to be decoded. It should only 
 +            contain valid base64 characters (A-Z, a-z, 0-9, +, /, =). 
 + 
 +    Returns: 
 +        str: The decoded string, using UTF-8 encoding. 
 + 
 +    Examples: 
 +        >>>​ b64decode("​SGVsbG8=") 
 +        '​Hello'​ 
 +        >>>​ b64decode("​SUM=") 
 +        '​IC'​ 
 +    """​ 
 +    return bytes_to_string(base64.b64decode(string_to_bytes(data))) 
 +</​file>​ 
 +</​spoiler>​ 
 +==== Exercițiul ​1 (2p) ====
  
 DESX este definit sub forma DESX( (k1,k2,k3), m) = k1 ⊕ DES(k2, m ⊕ k3). DESX este definit sub forma DESX( (k1,k2,k3), m) = k1 ⊕ DES(k2, m ⊕ k3).
-Construiti ​un atac impotriva ​DESX care sa ruleze ​intr-un timp proportional ​cu 2<​sup>​120</​sup>​.+Construiți ​un atac împotriva ​DESX care să ruleze ​într-un timp proporțional ​cu 2<​sup>​120</​sup>​.
  
-==== Exercise ​2 (3p) ====+==== Exercițiul ​2 (3p) ====
  
-De ce urmatoarele ​scheme nu aduc nicio imbunatatire fata de DES? Justificati!+De ce următoarele ​scheme nu aduc nicio îmbunătățire față ​de DES? Justificați!
  
   * a) c = k1 ⊕ DES(k2, m)   * a) c = k1 ⊕ DES(k2, m)
   * b) c = DES(k2, m ⊕ k1)   * b) c = DES(k2, m ⊕ k1)
  
-<note tip>Puteti ​folosi mai multe perechi (mesaj, ciphertext).</​note>​ +<note tip>Puteți ​folosi mai multe perechi (mesaj, ciphertext).</​note>​
-==== Exercitiul 3 (5p) ====+
  
-Scopul acestui exercitiu este de a implementa atacul meet-in-the-middle pe 2DES. +==== Exercițiul 3 (5p====
-Porniti de la scheletul de laborator ​(vezi mai joscare se foloseste de biblioteca pycrypto.+
  
-Realizati urmatoarele sarcini:+Scopul acestui exercițiu este de a implementa atacul meet-in-the-middle pe 2DES. 
 +Porniți de la scheletul de laborator (vezi mai jos) care se folosește de biblioteca pycrypto.
  
-=== A. Instalati ​biblioteca pycrypto ===+Realizați următoarele sarcini: 
 + 
 +=== A. Instalați ​biblioteca pycrypto ===
  
 Vezi https://​pypi.org/​project/​pycryptodome/​ Vezi https://​pypi.org/​project/​pycryptodome/​
  
  
-=== B. Implementati ​2DES ===+=== B. Implementați ​2DES (1p) ===
  
-Pornind de la schelet, ​implementati ​metodele des2_enc si des2_dec folosind double-DES (2DES).+Pornind de la schelet, ​implementați ​metodele des2_enc si des2_dec folosind double-DES (2DES).
  
 2DES( (k1,k2), m) = DES(k1, DES(k2, m)) 2DES( (k1,k2), m) = DES(k1, DES(k2, m))
  
-=== C. Testati ​2DES ===+=== C. Testați ​2DES (1p) ===
  
-Folositi urmatoarele ​ciphertexts+Folosiți următoarele ​ciphertexts
  
 c1 = '​cda98e4b247612e5b088a803b4277710f106beccf3d020ffcc577ddd889e2f32'​ c1 = '​cda98e4b247612e5b088a803b4277710f106beccf3d020ffcc577ddd889e2f32'​
Line 103: Line 373:
 c2 = '​54826ea0937a2c34d47f4595f3844445520c0995331e5d492f55abcf9d8dfadf'​ c2 = '​54826ea0937a2c34d47f4595f3844445520c0995331e5d492f55abcf9d8dfadf'​
  
-Decriptati-le folosind cheile:+Decriptați-le folosind cheile:
  
 k1 = '​Smerenie'​ k1 = '​Smerenie'​
Line 109: Line 379:
 k2 = '​Dragoste'​ k2 = '​Dragoste'​
  
-Primul plaintext corespunzator lui c1 este m1='​Fericiti cei saraci cu duhul, ca'​. ​Gasiti ​al doilea plaintext m2 ce ii corespunde lui c2.+Primul plaintext corespunzator lui c1 este m1='​Fericiti cei saraci cu duhul, ca'​. ​Găsiți ​al doilea plaintext m2 ce îi corespunde lui c2.
  
 <​note>​ <​note>​
-In biblioteca Pycrypto, DES primeste ​o cheie pe 8 octeti ​(64 biti) chiar daca ar trebui ​sa primeasca numai 7 octeti (56 biti). Ultimul bit din fiecare octet este considerat ca fiind un bit de paritate, dar este ignorat de biblioteca. Astfel cheia ce se foloseste ​va fi intr-adevar ​de dimensiunea 56 biti. Pentru simplitate ​insain acest exercitiu ​vom considera ​ca dimensiunea cheiei este de 64 biti. Astfel putem folosi cheile de 8 caractere de mai sus pentru DES.+În biblioteca Pycrypto, DES primește ​o cheie pe 8 octeți ​(64 biți) chiar dacă ar trebui ​să primeasca numai 7 octeti (56 biti). Ultimul bit din fiecare octet este considerat ca fiind un bit de paritate, dar este ignorat de bibliotecă. Astfel cheia ce se folosește ​va fi într-adevăr ​de dimensiunea 56 biți. Pentru simplitate ​însăîn acest exercițiu ​vom considera ​că dimensiunea cheiei este de 64 biți. Astfel putem folosi cheile de 8 caractere de mai sus pentru DES.
  
-Vom considera de asemenea ​ca initializam ​DES-ul cu valorile default (i.e. modul ECB si niciun IV).+Vom considera de asemenea ​că inițializăm ​DES-ul cu valorile default (i.e. modul ECB și niciun IV).
 </​note>​ </​note>​
  
-Decriptati intregul ​ciphertext (c1 || c2) cu cheile k1 si k2 folosind 2DES si asigurati-va ca rezultatul dat este mesajul ​initial ​m1||m2.+Decriptați întregul ​ciphertext (c1 || c2) cu cheile k1 și k2 folosind 2DES și asigurați-vă că rezultatul dat este mesajul ​inițial ​m1||m2.
  
-=== D. Implementati ​atacul meet-in-the-middle pentru 2DES ===+=== D. Implementați ​atacul meet-in-the-middle pentru 2DES (3p) ===
  
-In ultimul ​si cel mai important pas vi se dau niste perechi plaintext/​ciphertext ​obtinute ​prin criptarea cu 2DES cu niste chei necunoscute:​+În ultimul ​și cel mai important pas vi se dau niște ​perechi plaintext/​ciphertext ​obținute ​prin criptarea cu 2DES cu niște ​chei necunoscute:​
  
-m1 = '​Pocainta'​ (in byte string, i.e. poate fi dat direct ca parametru ​catre pycrypto DES)+m1 = '​Pocainta'​ (în byte string, i.e. poate fi dat direct ca parametru ​către ​pycrypto DES)
  
-c1 = '​9f98dbd6fe5f785d'​ (in hex string, trebuie ​sa il decodificati ​mai intai)+c1 = '​9f98dbd6fe5f785d'​ (în hex string, trebuie ​să îl decodificați ​mai întâi)
  
 m2 = '​Iertarea'​ m2 = '​Iertarea'​
Line 131: Line 401:
 c2 = '​6e266642ef3069c2'​ c2 = '​6e266642ef3069c2'​
  
-Vi se mai dau si ultimii 6 bytes ale celor 2 chei (care sunt altele decat cele folosite la pasii anteriori):+Vi se mai dau și ultimii 6 bytes ale celor 2 chei (care sunt altele decat cele folosite la pașii ​anteriori):
  
 k1 (last 6 bytes) = '​oIkvH5'​ k1 (last 6 bytes) = '​oIkvH5'​
Line 137: Line 407:
 k2 (last 6 bytes) = '​GK4EoU'​ k2 (last 6 bytes) = '​GK4EoU'​
  
-Sarcina ​voastra ​este sa gasiti ​restul ​octetilor ​din k1 si k2 aplicand ​atacul meet-in-the-middle+Sarcina ​voastră ​este să găsiți ​restul ​octeților ​din k1 și k2 aplicând ​atacul meet-in-the-middle.
-Your task is now to find the full keys k1 and k2 by applying the meet-in-the-middle attack over 2DES.+
  
-Pentru a construi un tabel, ​recomandam sa folositi ​o lista de tupluri unde adaugati ​perechi de forma (cheie, ​encriptie) ca in urmatorul ​exemplu:+Pentru a construi un tabel, ​recomandăm să folosiți ​o lista de tupluri unde adăugați ​perechi de forma (cheie, ​encripție) ca în următorul ​exemplu:
 <​code>​ <​code>​
 tb = [] tb = []
Line 151: Line 420:
 </​code>​ </​code>​
  
-Pentru a realiza ​cautare binara in tabel, ​selectati ​mai intai a doua coloana ​(pentru a cauta dupa encriptie):+Pentru a realiza ​căutarea binară în tabel, ​selectați ​mai întâi ​a doua coloană ​(pentru a căuta după encripție):
 <​code>​ <​code>​
 tenc = [value for _,value in tbs] tenc = [value for _,value in tbs]
 </​code>​ </​code>​
-iar apoi folositi ​biblioteca bisect ​ (e.g. bisect.bisect_left):​+iar apoi folosiți ​biblioteca bisect (e.g. bisect.bisect_left):​
 https://​docs.python.org/​2/​library/​bisect.html https://​docs.python.org/​2/​library/​bisect.html
  
 Scheletul de cod: Scheletul de cod:
  
-<code python desmitm.py> +<spoiler Click pentru a vedea lab05.py> 
-from utils import * +<file python lab05.py>​
-from operator import itemgetter+
 import bisect import bisect
 +from operator import itemgetter
 +from typing import List
 +
 from Crypto.Cipher import DES from Crypto.Cipher import DES
 +from utils import *
  
-def get_index(a,​ x): + 
-    """​Locate the leftmost value exactly equal to x in list a"""​+def get_index(a: List[bytes], x: bytes-> int
 +    """​Locate the leftmost value exactly equal to x in list a 
 + 
 +    Args: 
 +        a (List[bytes]):​ the list in which to search 
 +        x (bytes): the value to be searched 
 + 
 +    Returns: 
 +        int: The leftmost index at which the value is found in the list, 
 +            or -1 if not found 
 +    ​"""​
     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:
Line 174: Line 456:
         return -1         return -1
  
-def des_enc(k, m):+ 
 +def des_enc(k: bytes, m: bytes-> bytes:
     """​     """​
     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: 
-        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. 
  
     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 
-    ​The parity bits are ignored.+    ​expected for DES. The parity bits are ignored. 
 + 
 +    Args: 
 +        k (str): bytestring of length exactly 8 bytes. 
 +        m (str): bytestring containing the message (i.e. a sequence of 
 +            characters such as '​Hello'​ or '​\x02\x04'​)
  
     Return:     Return:
-        The bytestring ciphertext c+        ​bytes: ​The bytestring ciphertext c
     """​     """​
     d = DES.new(k, DES.MODE_ECB)     d = DES.new(k, DES.MODE_ECB)
Line 194: Line 478:
     return c     return c
  
-def des_dec(k, c):+ 
 +def des_dec(k: bytes, c: bytes-> bytes:
     """​     """​
     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: 
-        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. 
  
     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 
-    ​The parity bits are ignored.+    ​expected for DES. The parity bits are ignored. 
 + 
 +    Args: 
 +        k (str): bytestring of length exactly 8 bytes. 
 +        c (str): bytestring containing the ciphertext (i.e. a sequence of 
 +            characters such as '​Hello'​ or '​\x02\x04'​)
  
     Return:     Return:
-        The bytestring plaintext m+        ​bytes: ​The bytestring plaintext m
     """​     """​
     d = DES.new(k, DES.MODE_ECB)     d = DES.new(k, DES.MODE_ECB)
     m = d.decrypt(c)     m = d.decrypt(c)
     return m     return m
-  ​ 
-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)) 
  
-    print('​ciphertext:​ ' + c1) 
-    print('​plaintext:​ ' + m1) 
-    print('​plaintext in hexa: ' + str_2_hex(m1)) 
-    ​ 
-    # 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: 
-    k1 = '??​oIkvH5'​ 
-    k2 = '??​GK4EoU'​ 
  
-if __name__ == "​__main__"​+def des2_enc(k1:​ bytes, k2: bytes, m: bytes) -> bytes
-    ​main() +    ​# TODO B.1: implement des2_enc 
-</​code>​+    raise NotImplementedError("Not implemented"​)
  
 +
 +def des2_dec(k1:​ bytes, k2: bytes, c: bytes) -> bytes:
 +    # TODO B.2: implement des2_dec
 +    raise NotImplementedError("​Not implemented"​)
 +
 +
 +def test_des2() -> None:
 +    k1 = "​Smerenie"​
 +    k2 = "​Dragoste"​
 +    m1_given = "​Fericiti cei saraci cu duhul, ca"
 +    c1 = "​cda98e4b247612e5b088a803b4277710f106beccf3d020ffcc577ddd889e2f32"​
 +    c2 = "​54826ea0937a2c34d47f4595f3844445520c0995331e5d492f55abcf9d8dfadf"​
 +
 +    # TODO C: Decrypt c1 and c2 using k1 and k2, and make sure that
 +    #           ​des2_dec(k1,​ k2, c1 || c2) == m1 || m2
 +
 +    # TODO C.1: Convert k1, k2, c1, and c2 to bytes. It may make the exercise
 +    # easier to implement. Use string_to_bytes() for plain texts (i.e., string
 +    # in human-readable format), and bytes.fromhex() for hex strings.
 +    k1 = ...
 +    k2 = ...
 +    c1 = ...
 +    c2 = ...
 +
 +    # NOTE: The code to decrypt c1 is already provided below. You **need**
 +    # to decrypt c2 as well.
 +    m1 = bytes_to_string(des2_dec(k1,​ k2, c1))
 +    assert m1 == m1_given, f'​Expected "​{m1_given}",​ but got "​{m1}"'​
 +
 +    print("​ciphertext:",​ c1)
 +    print("​plaintext:",​ m1)
 +    print("​plaintext in hexa:",​ str_2_hex(m1))
 +
 +    # TODO C.2: Decrypt m2 similar to m1. Keep in mind that des_dec()
 +    # returns bytes
 +    m2 = ...
 +
 +    print("​ciphertext:",​ c2)
 +    print("​plaintext:",​ m2)
 +    print("​plaintext in hexa:",​ str_2_hex(m2))
 +
 +    # TODO C.3: Just to make sure you implemented the task correctly:
 +    #           ​des2_dec(k1,​ k2, c1 || c2) == m1 || m2
 +    m12 = ...
 +    assert m12 == m1 + m2, f'​Expected "​{m12}"​ to equal "{m1 + m2}"'​
 +
 +
 +def mitm() -> None:
 +    # TODO D: run meet-in-the-middle attack for the following plaintext/​ciphertext
 +    m1 = "​Pocainta"​
 +    c1 = "​9f98dbd6fe5f785d"​
 +    m2 = "​Iertarea"​
 +    c2 = "​6e266642ef3069c2"​
 +
 +    # TODO D.1: Convert m1, m2, c1, and c2 to bytes. It may make the exercise
 +    # easier to implement. Use string_to_bytes() for plain texts (i.e., string
 +    # in human-readable format), and bytes.fromhex() for hex strings.
 +    m1 = ...
 +    c1 = ...
 +    m2 = ...
 +    c2 = ...
 +
 +    # NOTE: You only need to search for the first 2 bytes of the each key (i.e.,
 +    # to find out what are the values for each `?`).
 +    k1 = "??​oIkvH5"​
 +    k2 = "??​GK4EoU"​
 +
 +    # TODO D.2: Generate the table containing (k2, DES(k2, m1)), for every
 +    # possible k2. Use a List[Tuple[bytes,​ bytes]] for the table (see task
 +    # description above).
 +
 +    # TODO D.3: Sort the table based on the ciphertexts. Extract the ciphertexts
 +    # in a list  (see task description above).
 +
 +    # TODO D.4: Perform binary search for all possible k1, such that .
 +    # Save the set of candidate keys (k1, k2) in a list.
 +
 +    # TODO D.5: From the set of candidate keys, print the ones matching
 +    # the second constraint: 2DES(k1, k2, m2) == c2
 +
 +
 +def main() -> None:
 +    test_des2()
 +    mitm()
 +
 +
 +if __name__ == "​__main__":​
 +    main()</​file>​
 +</​spoiler>​
 +</​hidden>​
ic/labs/05.1635774708.txt.gz · Last modified: 2021/11/01 15:51 by razvan.smadu
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