Differences

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

Link to this comparison view

ic:labs:04 [2023/10/01 23:21]
razvan.smadu [SPN 1 (3p)]
ic:labs:04 [2023/10/09 23:21] (current)
razvan.smadu
Line 3: Line 3:
 Prezentarea PowerPoint pentru acest laborator poate fi găsită [[https://​drive.google.com/​file/​d/​1mjbkxFqYNB-lRRXGAhsdh1vK9nwbnDuS/​view?​usp=sharing|aici]]. Prezentarea PowerPoint pentru acest laborator poate fi găsită [[https://​drive.google.com/​file/​d/​1mjbkxFqYNB-lRRXGAhsdh1vK9nwbnDuS/​view?​usp=sharing|aici]].
  
-Puteți lucra acest laborator folosind ​și platforma Google Colab, accesând [[https://​colab.research.google.com/​drive/1rxZ9eyzMXqq3NDia22suPO_1QPAb5o0C?​usp=sharing+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/​lab04/​lab4.ipynb
 |acest]] link. |acest]] link.
  
 +<​hidden>​
 <spoiler Click pentru a vedea utils.py>​ <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):​ 
-        yield string[i:​i+chunk_size] 
  
-THIS ONE IS NEW +def _pad(data: str, size: int) -> str: 
-def byte_2_bin(bval):​ +    reminder = len(data) % size 
-    """​ +    if reminder != 0: 
-      Transform ​a byte (8-bit) value into bitstring+        data = "​0"​ * (size - reminder) + data 
 +    return data 
 + 
 + 
 +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):​ +def hex_2_bin(data: str-> str
-    ​return ''​.join(f'​{int(x,​ 16):​08b}'​ for x in _chunks(data,​ 2))+    ​"""​Converts a hexadecimal string to a binary representation.
  
-def str_2_bin(data): +    Args: 
-    return ''​.join(f'​{ord(c):​08b}'​ for c in data)+        ​data (str): The hexadecimal string to be convertedIt should have an 
 +            even number of characters and only contain valid hexadecimal digits 
 +            ​(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))+        strThe binary representation of the hexadecimal stringwhere each 
 +            pair of hexadecimal digits is encoded as an 8-bit binary number.
  
-def str_2_hex(data): +    Examples: 
-    ​return ​''​.join(f'{ord(c):02x}' ​for in data)+        >>>​ hex_2_bin("​01abcd"​
 +        '000000011010101111001101' 
 +        >>>​ hex_2_bin("​0a"​) 
 +        '​00001010'​ 
 +    """​ 
 +    return ""​.join(f"{int(x, 16):08b}" ​for in _chunks(data, 2))
  
-def bin_2_str(data):​ 
-    return ''​.join(chr(int(b,​ 2)) for b in _chunks(data,​ 8)) 
  
-def hex_2_str(data): +def bin_2_hex(data: str-> str
-    ​return ''​.join(chr(int(x,​ 16)) for x in _chunks(data,​ 2))+    ​"""​Converts a binary string to a hexadecimal representation.
  
-# XOR FUNCTIONS +    Args: 
-def strxor(a, b):  # xor two strings, trims the longer input +        ​data ​(str): The binary string to be converted. It should have a multiple 
-    ​return ''​.join(chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b))+            of 8 characters and only contain valid binary digits ​(0 or 1).
  
-def bitxor(a, b) # xor two bit-strings,​ trims the longer input +    Returns
-    ​return ''​.join(str(int(x) ^ int(y)) for (xy) in zip(a, b))+        str: The hexadecimal representation of the binary stringwhere each 
 +            group of 8 binary digits is encoded as pair of hexadecimal digits.
  
-def hexxor(a, b):  # xor two hex-strings,​ trims the longer input +    Examples: 
-    return ​''​.join(_hex(int(x16) ^ int(y, 16)) for (x, y) in zip(_chunks(a2), _chunks(b, 2)))+        >>>​ bin_2_hex("​000000011010101111001101"​) 
 +        '​01abcd'​ 
 +        >>>​ bin_2_hex("​00001010"​) 
 +        '​0a'​ 
 +    """​ 
 +    return ​""​.join(f"{int(b2):​02x}" ​for in _chunks(data8))
  
-# BASE64 FUNCTIONS 
-def b64decode(data):​ 
-    return bytes_to_string(base64.b64decode(string_to_bytes(data))) 
  
-def b64encode(data):​+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:​ str, operand_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_1,​ operand_2)) 
 + 
 + 
 +def bitxor(operand_1:​ str, operand_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_1,​ operand_2)) 
 + 
 + 
 +def hexxor(operand_1:​ str, operand_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 Latin-1 format. 
 + 
 +    Returns: 
 +        str: The string representation of the byte array or the byte string, 
 +            decoded using Latin-1 encoding. 
 + 
 +    Examples: 
 +        >>>​ bytes_to_string(b'​Hello'​) 
 +        '​Hello'​ 
 +        >>>​ bytes_to_string(bytearray(b'​IC'​)) 
 +        '​IC'​ 
 +    """​ 
 +    return bytes_data.decode(encoding="​raw_unicode_escape"​) 
 + 
 + 
 +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 
 +        Latin-1 encoding. 
 + 
 +    Examples: 
 +        >>>​ string_to_bytes('​Hello'​) 
 +        b'​Hello'​ 
 +        >>>​ string_to_bytes('​IC'​) 
 +        b'​IC'​ 
 +    """​ 
 +    return string_data.encode(encoding="​raw_unicode_escape"​) 
 + 
 + 
 +# 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 Latin-1 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): +def b64decode(data: str-> str
-    ​return string_data.encode()  # default utf-8+    ​"""​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 Latin-1 encoding. 
 + 
 +    Examples: 
 +        >>>​ b64decode("​SGVsbG8="​) 
 +        '​Hello'​ 
 +        >>>​ b64decode("​SUM="​) 
 +        '​IC'​ 
 +    """​ 
 +    return bytes_to_string(base64.b64decode(string_to_bytes(data)))
 </​file>​ </​file>​
 </​spoiler>​ </​spoiler>​
Line 168: Line 434:
  
  
-def permute4_32(s:​ str) -> str: 
-    """​Perform a permutatation by shifting all bits 4 positions right. 
- 
-    Args: 
-        s (str): The input is assumed to be a 32-bit bitstring. 
- 
-    Raises: 
-        TypeError: Expected input to be a string. 
-        ValueError: Expected input to have length 32. 
- 
-    Returns: 
-        str: The permuted string by shifting all bits 4 positions right. 
-    """​ 
-    if not isinstance(s,​ str): 
-        raise TypeError( 
-            f"​Invalid type for the input. Expected `str`, but got `{type(s)}`."​ 
-        ) 
-    if len(s) != 32: 
-        raise ValueError( 
-            f"​Invalit input length. Expected to be 32, but got {len(s)}."​ 
-        ) 
-    return s[28:32] + s[0:28] 
- 
- 
-def permute_inv4_32(s:​ str) -> str: 
-    """​Perform the inverse of permute4_32. 
- 
-    Args: 
-        s (str): The input is assumed to be a 32-bit bitstring. 
- 
-    Raises: 
-        TypeError: Expected input to be a string. 
-        ValueError: Expected input to have length 32. 
- 
-    Returns: 
-        str: The permuted string by shifting all bits 4 positions left. 
-    """​ 
-    if not isinstance(s,​ str): 
-        raise TypeError( 
-            f"​Invalid type for the input. Expected `str`, but got `{type(s)}`."​ 
-        ) 
-    if len(s) != 32: 
-        raise ValueError( 
-            f"​Invalit input length. Expected to be 32, but got {len(s)}."​ 
-        ) 
-    return s[4:32] + s[0:4] 
  
  
Line 332: Line 552:
  
     return y1 + y2     return y1 + y2
 +
 +
  
  
Line 338: Line 560:
     msg = "​Hi"​     msg = "​Hi"​
     key = "??" ​ # Find the key that should replace ??     key = "??" ​ # Find the key that should replace ??
 +    ks = str_2_bin(key)
 +
 +    # TODO 1: Find the key in the reduced 2-byte SPN
 +
  
     xs = str_2_bin(msg)     xs = str_2_bin(msg)
-    ks = str_2_bin(key) 
     ys = spn_1r_reduced_2s(ks,​ xs)     ys = spn_1r_reduced_2s(ks,​ xs)
     print(     print(
-        ​f"Two y halves of reduced SPN:"+        "Two y halves of reduced SPN:"
         f" {ys[0:8]} (hex: {bin_2_hex(ys[0:​8])}),"​         f" {ys[0:8]} (hex: {bin_2_hex(ys[0:​8])}),"​
         f" {ys[8:16]} (hex: {bin_2_hex(ys[8:​16])})"​         f" {ys[8:16]} (hex: {bin_2_hex(ys[8:​16])})"​
Line 351: Line 576:
     msg = "​Om"​     msg = "​Om"​
     key = "????" ​ # Find the key that should replace ????     key = "????" ​ # Find the key that should replace ????
-    xs = str_2_bin(msg) 
     ks = str_2_bin(key)     ks = str_2_bin(key)
 +
 +    # TODO 2: Find the key in the full 2-byte SPN
 +
 +    xs = str_2_bin(msg)
     ys = spn_1r_full_2s(ks,​ xs)     ys = spn_1r_full_2s(ks,​ xs)
     print(     print(
-        ​f"Two y halves of full SPN (2 bytes):"​+        "Two y halves of full SPN (2 bytes):"​
         f" {ys[0:8]} (hex: {bin_2_hex(ys[0:​8])}),"​         f" {ys[0:8]} (hex: {bin_2_hex(ys[0:​8])}),"​
         f" {ys[8:16]} (hex: {bin_2_hex(ys[8:​16])})"​         f" {ys[8:16]} (hex: {bin_2_hex(ys[8:​16])})"​
     )     )
 +
  
  
 if __name__ == "​__main__":​ if __name__ == "​__main__":​
-    main() ​+    main()
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
Line 390: Line 619:
 De data aceasta nu se poate executa o cautare brute-force pe toți octeții de XOR. Încercați să atacați câte un S-box pe rând. Gandiți-vă ce biți sunt afectați de fiecare S-box pentru a construi un atac eficient. Ce se întâmplă dacă faceți brute force pe k5 și k6? Puteți să aflați k1? De data aceasta nu se poate executa o cautare brute-force pe toți octeții de XOR. Încercați să atacați câte un S-box pe rând. Gandiți-vă ce biți sunt afectați de fiecare S-box pentru a construi un atac eficient. Ce se întâmplă dacă faceți brute force pe k5 și k6? Puteți să aflați k1?
 </​note>​ </​note>​
 +</​hidden>​
ic/labs/04.1696191703.txt.gz · Last modified: 2023/10/01 23:21 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