Differences

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

Link to this comparison view

ic:labs:03 [2021/10/11 00:36]
philip.dumitru [Exercise 4]
ic:labs:03 [2023/10/16 20:53] (current)
razvan.smadu
Line 1: Line 1:
 ===== Laboratorul 03 - PRGs ===== ===== Laboratorul 03 - PRGs =====
  
-Prezentarea PowerPoint pentru acest laborator poate fi găsită [[https://​drive.google.com/​file/​d/​1IfyMkfV6jQDzW5KhS_B6wt_azV31SLjL/​view?​usp=sharing|aici]].+Prezentarea PowerPoint pentru acest laborator poate fi găsită [[https://​drive.google.com/​file/​d/​1IfyMkfV6jQDzW5KhS_B6wt_azV31SLjL/​view?​usp=sharing|aici]]. Puteți găsi o scurtă prezentare a noțiunii de avantaje în [[https://​drive.google.com/​file/​d/​1F_mtKi0zeAn1xYQs6Wc7IiiVX8ZW6aeG/​view?​usp=sharing|acest]] PDF.
  
 +
 +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/​lab03/​lab3.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(stringchunk_size): +def _pad(data: strsize: int-> str
-    ​for i in range(0, ​len(string), chunk_size): +    ​reminder = len(data% size 
-        ​yield string[i:i+chunk_size]+    if reminder != 0
 +        ​data = "​0"​ * (size - reminder) ​data 
 +    return data
  
-def _hex(x): 
-    return format(x, '​02x'​) 
  
-def hex_2_bin(data): +def _chunks(data: str, chunk_size: int-> Generator[str,​ None, None]
-    ​return ''​.join(f'​{int(x16):​08b}' ​for in _chunks(data, ​2))+    ​data = _pad(datachunk_size) 
 +    ​for in range(0, len(data)chunk_size)
 +        yield data[i : i + chunk_size]
  
-def str_2_bin(data):​ 
-    return ''​.join(f'​{ord(c):​08b}'​ for c in data) 
  
-def bin_2_hex(data): +def _hex(data: int-> str
-    return ​''​.join(f'​{int(b2):02x}' for b in _chunks(data,​ 8))+    return ​format(data"02x")
  
-def str_2_hex(data):​ 
-    return ''​.join(f'​{ord(c):​02x}'​ for c in data) 
  
-def bin_2_str(data):​ +# Conversion functions
-    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 hex_2_bin(data:​ str) -> str: 
 +    """​Converts a hexadecimal string to a binary representation.
  
-def strxor(a, b):  # xor two strings, trims the longer input +    Args: 
-    ​return ''​.join(chr(ord(x) ^ ord(y)) for (xy) in zip(a, b))+        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).
  
-def bitxor(a, b) # xor two bit-stringstrims the longer input +    Returns: 
-    ​return ''​.join(str(int(x) ^ int(y)) for (x, y) in zip(a, b))+        str: The binary representation of the hexadecimal stringwhere each 
 +            pair of hexadecimal digits is encoded as an 8-bit binary number.
  
-def hexxor(a, b):  # xor two hex-strings,​ trims the longer input +    Examples: 
-    return ​''​.join(_hex(int(x, 16) ^ int(y, 16)) for (x, y) in zip(_chunks(a, 2), _chunks(b, 2)))+        >>>​ hex_2_bin("​01abcd"​) 
 +        '​000000011010101111001101'​ 
 +        >>>​ hex_2_bin("​0a"​) 
 +        '​00001010'​ 
 +    """​ 
 +    return ​""​.join(f"{int(x, 16):​08b}" ​for x in _chunks(data, 2))
  
-# BASE64 FUNCTIONS 
  
-def b64decode(data): +def bin_2_hex(data: str-> str
-    ​return bytes_to_string(base64.b64decode(string_to_bytes(data)))+    ​"""​Converts a binary string to a hexadecimal representation.
  
-def b64encode(data):​+    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 hexadecimal representation of the binary string, where each 
 +            group of 8 binary digits is encoded as a pair of hexadecimal digits. 
 + 
 +    Examples: 
 +        >>>​ bin_2_hex("​000000011010101111001101"​) 
 +        '​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:​ 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): +def b64decode(data: str-> str
-    ​return bytes_data.decode() ​ # default utf-8+    ​"""​Decodes a base64 encoded string.
  
-def string_to_bytes(string_data): +    Args: 
-    return ​string_data.encode()  # default utf-8+        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>​
  
-==== Exercițiul 1 ==== + 
-In acest exercitiu ​vom incerca sa spargem un LCG (Linear Congruential Generator)ce se poate folosi pentru a genera numere ​"slab" ​aleatoare. +==== Exercițiul 1 (3p) ==== 
-Am folosit un astfel de generator pentru a obtine ​secventa ​de octeti ​cu care a fost criptat un mesaj (plaintext). +În acest exercițiu ​vom încerca să spargem un LCG (Linear Congruential Generator, ​care se poate folosi pentru a genera numere ​slab” aleatoare. 
-Textul cifrat (ciphertext) ​in sistemul hexazecimal este urmatorul:+Am folosit un astfel de generator pentru a obține ​secvență ​de octeți ​cu care a fost criptat un mesaj (plaintext). 
 +Textul cifrat (ciphertext) ​în sistemul hexazecimal este următorul:
 <​code>​ <​code>​
 a432109f58ff6a0f2e6cb280526708baece6680acc1f5fcdb9523129434ae9f6ae9edc2f224b73a8 a432109f58ff6a0f2e6cb280526708baece6680acc1f5fcdb9523129434ae9f6ae9edc2f224b73a8
 </​code>​ </​code>​
  
-Dupa cum stiti, LCG foloseste urmatoare ​formula pentru a genera ​octeti:+ 
 + 
 +După cum știți, LCG folosește următoarea ​formula pentru a genera ​octeți:
  
 s_next = (a * s_prev + b) mod p s_next = (a * s_prev + b) mod p
  
-unde s_next ​si s_prev sunt octeti ​(0-255) ​generati, p = 257 iar a si b au valori ​intre si 256. +unde s_next ​și s_prev sunt octeți ​(0-255) ​generați, p = 257iar a și b au valori ​între ​și 256. 
  
-Mai stiti si ca primele 16 litere din plaintext sunt "Let all creation". Criptarea a fost obtinuta executand ​XOR intre plaintext ​si secventa ​de octeti ​consecutivi ​generati ​de LCG+Mai știți și că primele 16 litere din plaintext sunt Let all creation. Criptarea a fost obținută realizând ​XOR între ​plaintext ​și secvența ​de octeți ​consecutivi ​generați ​de LCG.
  
-Spargeti ​LCG astfel ​incat sa puteti ​prezice ​sirul de numere generate ​"​aleator"​. Care este mesajul ​initial?+Spargeți ​LCG astfel ​încât să puteți ​prezice ​șirul ​de numere generate ​“aleatoriu”. Care este mesajul ​inițial?
  
-Puteti ​folosi ​urmatorul ​schelet de cod:+Puteți ​folosi ​următorul ​schelet de cod:
 <code python '​ex1_weak_rng.py'>​ <code python '​ex1_weak_rng.py'>​
 +from typing import List, Tuple
 +
 from utils import * from utils import *
  
-#Parameters for weak LC RNG+
 class WeakRNG: class WeakRNG:
-    "​Simple class for weak RNG" +    ​""​"​Simple class for weak RNG"""​ 
-    def __init__(self):​+ 
 +    def __init__(self) ​-> None:
         self.rstate = 0         self.rstate = 0
         self.maxn = 255         self.maxn = 255
-        self.a = 0 #Set this to correct value +        self.a = 0  # Set this to correct value 
-        self.b = 0 #Set this to correct value+        self.b = 0  # Set this to correct value
         self.p = 257         self.p = 257
  
-    def init_state(self):​ +    def init_state(self, rstate: int-> None
-        "​Initialise rstate"​ +        ​""​"​Initialise rstate""​
-        self.rstate = #Set this to some value+        self.rstate = rstate  ​# Set this to some value
         self.update_state()         self.update_state()
  
-    def update_state(self):​ +    def update_state(self) ​-> None
-        "​Update state"+        ​""​"​Update state""​"
         self.rstate = (self.a * self.rstate + self.b) % self.p         self.rstate = (self.a * self.rstate + self.b) % self.p
  
-    def get_prg_byte(self):​ +    def get_prg_byte(self) ​-> int
-        "​Return a new PRG byte and update PRG state"+        ​""​"​Return a new PRG byte and update PRG state""​"
         b = self.rstate & 0xFF         b = self.rstate & 0xFF
         self.update_state()         self.update_state()
         return b         return b
  
-  ​ 
-def main(): 
  
-    ​#Initialise weak rng+def main() -> None: 
 +    ​# Initialise weak rng
     wr = WeakRNG()     wr = WeakRNG()
-    wr.init_state()+    wr.init_state(0)
  
-    #Print ciphertext +    # Print ciphertext 
-    CH = 'a432109f58ff6a0f2e6cb280526708baece6680acc1f5fcdb9523129434ae9f6ae9edc2f224b73a8' +    CH = "a432109f58ff6a0f2e6cb280526708baece6680acc1f5fcdb9523129434ae9f6ae9edc2f224b73a8" 
-    print("​Full ciphertext in hexa: " ​CH)+    print("​Full ciphertext in hexa:"CH)
  
-    #Print known plaintext +    # Print known plaintext 
-    pknown = 'Let all creation'+    pknown = "Let all creation"
     nb = len(pknown)     nb = len(pknown)
-    print("​Known plaintext: " ​+ known)+    print("​Known plaintext:"​, pknown)
     pkh = str_2_hex(pknown)     pkh = str_2_hex(pknown)
-    print("​Plaintext in hexa: " ​pkh)+    print("​Plaintext in hexa:"pkh)
  
-    #Obtain first nb bytes of RNG +    # Obtain first nb bytes of RNG 
-    gh = hexxor(pkh, CH[0:nb*2])+    gh = hexxor(pkh, CH[0 : nb * 2])
     print(gh)     print(gh)
     gbytes = []     gbytes = []
     for i in range(nb):     for i in range(nb):
-        gbytes.append(ord(hex_2_str(gh[2*i:​2*i+2])))+        gbytes.append(ord(hex_2_str(gh[2 * i : 2 * i + 2])))
     print("​Bytes of RNG: ")     print("​Bytes of RNG: ")
     print(gbytes)     print(gbytes)
  
-    #Break the LCG here: +    # Break the LCG here: 
-    #1. find a and b +    # TODO 1: Find a and b, and set them in the RNG
-    #2. predict/​generate rest of RNG bytes +
-    #3. decrypt plaintext+
  
-    # Print full plaintext +    # TODO 2: Predict/​generate rest of RNG bytes 
-    p = ''​ + 
-    print("​Full plaintext is: " ​p)+    # TODO 3: Decrypt plaintext 
 + 
 +    # TODO 4: Print the full plaintext 
 +    p = ... 
 +    print("​Full plaintext is:"p)
  
  
 if __name__ == "​__main__":​ if __name__ == "​__main__":​
-    main() ​ +    main()
 </​code>​ </​code>​
  
-==== Exercise 2 ==== 
  
-AdvantageThe purpose of this problem is to clarify the concept of advantageConsider the following two experiments ​$\mathsf{EXP}(0)$ ​and $\mathsf{EXP}(1)$:​ +==== Exercițiul 2 (2p) ==== 
-  * In $\mathsf{EXP}(0)$ ​the challenger flips a fair coin (probability ​$1/2$ for HEADS and $1/2$ for TAILSand sends the result to the adversary ​$\mathsf{A}$. + 
-  * In $\mathsf{EXP}(1)$ ​the challenger always sends TAILS to the adversary.+AvantajeScopul acestui exercițiu este de a clarifica conceptul de avantaje prezentat la cursVom considera două experimente ​$\mathsf{EXP}(0)$ ​și $\mathsf{EXP}(1)$, astfel
 +  * În $\mathsf{EXP}(0)$ ​verificatorul dă cu banul (probabilitate de $1/2$ pentru CAP și $1/2$ pentru PAJURĂși transmite rezultatul adversarului ​$\mathsf{A}$. 
 +  * În $\mathsf{EXP}(1)$ ​verificatorul întotdeauna va transmite PAJURĂ către adversar.
  
-Let r = 0 for HEADS and r = 1 for TAILSThen we have the experiment as shown below:+Considerăm $r = 0$ pentru CAP și $r = 1$ pentru PAJURĂJocul va arăta astfel:
 {{:​sasc:​laboratoare:​adversar_prg.png?​400|}} {{:​sasc:​laboratoare:​adversar_prg.png?​400|}}
  
-The adversary’goal is to distinguish these two experimentsat the end of each experiment ​the adversary outputs a bit $0$ or $1$ for its guess for which experiment it is in. For $b = 0,1let $W_{b}$ ​be the event that in experiment ​$b$ the adversary output ​$1$. The adversary tries to maximize its distinguishing advantagenamely the quantity +Scopul adversarului este să diferențieze între cele două experimentela finalul fiecarui ​experiment, adversarul returnează un bit $\mathsf{b'​}$, ​$0$ sau $1$, în speranța de a ghici experimentul în care se află (adică, ​$\mathsf{EXP}(b\mathsf{EXP}(b'​)$). 
-$\mathsf{Adv} = \left| \mathsf{Pr}\left[W_{0}\right] − \mathsf{Pr}\left[W_{1}\right] \right| \in \left[0, 1\right]$ .+Fie $W_{b}$ ​evenimentul când în experimentul ​$\mathsf{EXP}(b)adversarul returnează ​$b' = 1$. Adversarul vrea să își maximizeze avantajul de a distinge experimentele. Mai exactel vrea să maximizeze valoarea ​$\mathsf{Adv} = \left| \mathsf{Pr}\left[W_{0}\right] − \mathsf{Pr}\left[W_{1}\right] \right| \in \left[0, 1\right]$.
  
-The advantage ​$\mathsf{Adv}$ ​captures the adversary’s ability to distinguish the two experimentsIf the advantage is $0$ then the adversary behaves exactly the same in both experiments and therefore does not distinguish between themIf the advantage is $1$ then the adversary can tell perfectly what experiment it is inIf the advantage is negligible for all efficient adversaries (as defined in class) then we say that the two experiments are indistinguishable.+Avantajul ​$\mathsf{Adv}$ ​redă capacitatea adversarului de a diferenția experimenteleDacă avantajul este $0$, atunci advesarul se comportă identic în ambele cazuri și nu poate să le distingăDacă avantajul este $1$, atunci adversarul știe concret care este valoarea lui $b$Dacă avantajul este neglijabil pentru orice adversar eficient atunci putem spune că nu se poate distinge între experimente.
  
-a. Calculate the advantage of each of the following adversaries+a. Calculați avantajul pentru fiecare dintre următorii adversari
-  * A1: Always output ​$1$. +  * A1: Returnează mereu $b'=1$. 
-  * A2: Ignore the result reported by the challenger, and randomly output ​$0$ or $1$ with even probability+  * A2: Ignoră valoarea primită de la verificator și returnează aleatoriu ​$0$ sau $1$, cu aceeași probabilitate
-  * A3: Output ​$1$ if HEADS was received from the challengerelse output ​$0$. +  * A3: Returnează ​$1$ dacă a primit CAP ($r=0$) de la verificatoraltfel returnează ​$0$. 
-  * A4: Output ​$0$ if HEADS was received from the challengerelse output ​$1$. +  * A4: Returnează ​$0$ dacă a primit CAP de la verificatoraltfel returnează ​$1$. 
-  * A5: If HEADS was receivedoutput ​$1$. If TAILS was receivedrandomly output ​$0$ or $1$ with even probability+  * A5: Dacă a primit CAPreturnează ​$1$. Dacă a primit PAJURĂreturnează aleatoriu ​$0$ sau $1$ cu aceeași probabilitate
-  * A6: If HEADS was receivedrandomly output ​$0$ or $1$ with even probabilityIf TAILS was receivedoutput ​$0$.+  * A6: Dacă a primit CAPreturnează aleatoriu ​$0$ sau $1$, cu aceeași probabilitateDacă a primit PAJURĂreturnează ​$0$.
  
-b. What is the maximum advantage possible in distinguishing these two experimentsExplain why.+b. Care este avantajul maxim pe care îl poate obține un adversar? De ce?
  
 <note tip> <note tip>
-You may want to compute the general ​formula, regardless of what the adversary is.+Încercați să obtineți mai întai o formulă ​generală ce nu depinde de adversar.
 </​note>​ </​note>​
  
-==== Exercise 3 ==== 
  
-One of the applications of computing the advantage for an adversary on cryptographic scheme is to prove that a $\mathsf{PRG}is secure or notRecall from the lecture that $G : K \rightarrow \{0, 1\}^n$ ​is a secure ​$\mathsf{PRG}if for any efficient (that runs in polynomial time) statistical ​test $\mathsf{A}$, ​the advantage ​$\mathsf{Adv_{PRG}[A,​ G]}$ is negligibleA statistical ​test is basically an algorithm that tries to determine ​whether the input seems random or not, therefore it can be defined as follows:+==== Exercițiul 3 (2p) ==== 
 + 
 +O aplicație ​avantajului în schemele criptografice este de arăta că un $PRG$ este sigur sau nuAmintiți-vă de la curs că $G : K \rightarrow \{0, 1\}^n$ ​este un $PRG$ sigur dacă pentru orice test statistic ​$\mathsf{A}$ ​eficient (care rulează în timp polinomial)avantajul ​$\mathsf{Adv_{PRG}[A,​ G]}$ este neglijabilUn test statistic este de fapt un algoritm care încearcă să determine ​dacă intrarea pare aleatoare sau nu. Acest algoritm poate fi definit astfel:
  
 \begin{equation*} \begin{equation*}
   A(x) =   A(x) =
     \begin{cases}     \begin{cases}
-      1 & \text{if is random}\\ +      1 ,& \text{dacă e aleatoriu}\\ 
-      0 & \text{otherwise+      0 ,& \text{altfel
-    \end{cases} ​      ​+    \end{cases} ​
 \end{equation*} \end{equation*}
  
-You can associate the statistical ​test $\mathsf{A}with an adversary that tries to break the $\mathsf{PRG}$ (i.e. it can distinguish the output of the $\mathsf{PRG}$ ​from a truly random ​generator). ​In this casewe shall define the experiments as follows+Putem asocia pentru fiecare ​test statistic ​$A$ câte un adversar care încearcă să spargă ​$\mathsf{PRG}$-ul (adică poate distinge între rezultatul ​$\mathsf{PRG}$-ului și un generator ​de numere complet aleatoare). În acest cazvom defini experimentele după cum urmează
-  * In $\mathsf{EXP}(0)$ ​the challenger sends the output ​$G(k)$ ​generated by the $\mathsf{PRG}$ to the adversary $\mathsf{A}$; +  * În $\mathsf{EXP}(0)$ ​verificatorul trimite către adversarul $\mathsf{A}$ valoarea ​$G(k)$ ​generată de $\mathsf{PRG}$;​ 
-  * In $\mathsf{EXP}(1)$ ​the challenger sends the output ​$r$ generated by truly random ​generator ​to the adversary.+  * În $\mathsf{EXP}(1)$ ​verificatorul trimite către adversarul $\mathsf{A}$ o valoare ​$r$ generată de un generator de numere complet aleatoare.  
 + 
 +Ca mai devreme, $W_{b}$ este evenimentul în care adversarul spune că numărul este aleatoriu și avut loc experimentul $b$. Dacă adversarul poate să distingă între $\mathsf{PRG}$ și un generator ​de numere complet aleatoare, atunci $\mathsf{PRG}$-ul nu e sigurAșadar, avantajul devine:
  
-Also, $W_{b}$ represents the event in which the adversary guesses that the input is random (i.e. $A(x) = 1$), in the experiment $b$. The idea behind this is that if the adversary can tell the difference between the $\mathsf{PRG}$ and a truly random generator, then the $\mathsf{PRG}$ is not secure. Thus, the advantage becomes: +$$\mathsf{Adv_{PRG}[A,​ G]} = \left|\underset{k \leftarrow K}{Pr}[A(G(k)) = 1] - \underset{r \leftarrow \{0, 1\}^n}{Pr}[A(r) = 1] \right|$$
-$\mathsf{Adv_{PRG}[A,​ G]} = \left|\underset{k \leftarrow K}{Pr}[A(G(k)) = 1] - \underset{r \leftarrow \{0, 1\}^n}{Pr}[A(r) = 1] \right|$.+
  
-Although the problem of determining whether there are provably secure ​$\mathsf{PRG}sis equivalent to solving the well-known problem $\mathsf{P}$ vs $\mathsf{NP}$, ​in practice there are some $\mathsf{PRG}sthat are considered secure, by using some heuristics.+Deși problema determinării dacă există ​$\mathsf{PRG}$-uri care să poată fi demonstrate ca fiind sigure este echivalentă cu a rezolva bine-cunoscuta ​problemă $\mathsf{P}$ vs $\mathsf{NP}$, ​în practică există ​$\mathsf{PRG}$-uri considerate sigure prin folosirea unor euristici.
  
-In this exerciseyou are given a $\mathsf{PRG}$ $G : \{0, 1\}^s \rightarrow \{0, 1\}^n$ ​that is known to be secure and your assignment is to determine which of the following ​$\mathsf{PRG}sare also secure:+În acest exercițiuse dă un $\mathsf{PRG}$ $G : \{0, 1\}^s \rightarrow \{0, 1\}^n$ ​sigur. Cu ajutorul acestuia, spuneți dacă următoarele ​$\mathsf{PRG}$-uri sunt sigure.
   * $G_{1}(k) = G(k) \oplus 1^n$   * $G_{1}(k) = G(k) \oplus 1^n$
   * $G_{2}(k) = G(k) \| 0$   * $G_{2}(k) = G(k) \| 0$
Line 205: Line 468:
   * $G_{5}(k)=G(k) \| G(k)$   * $G_{5}(k)=G(k) \| G(k)$
  
-<​note>​For strings ​$y$ and $z$ we use $y \| z$ to denote the concatenation of $y$ and $z$.</​note>​+<​note>​Pentru două șiruri de biți $y$ și $z$ folosim ​$y \| z$ pentru a indica concatenarea între ​$y$ și $z$.</​note>​
  
-<note tip>Some of these exercises may not require computing any advantage.</​note>​+<note tip>Pentru unele dintre ele nu este nevoie să calculați avantajul.</​note>​
  
-==== Exercițiul 4 ==== 
  
-Vom folosi experimentul definit mai devreme pentru a construi un pseudorandom generator ​($\mathsf{PRG}$)+==== Exercițiul 4 (3p====
-  - Se alege lungimea $n$ a sirului ce va fi generat +
-  - Se obtine un sir de biti $R$ de lungime $n$ (e.g. puteti folosi chiar si LCG-ul din Exercitiul 1) +
-  - Pentru fiecare bit $r$ din sirul $R$ generat anterior, $\mathsf{PRG}$-ul va intoarce un bit $b$ astfel: +
-  * daca bitul $r$ este $0$, atunci intoarce un bit aleator $b \in \{0, 1\}$ +
-  * daca bitul $r$ este $1$, atunci intoarce $1$+
  
-a. Implementati //​frequency ​(monobittest// asa cum e descris in articolul din [[http://​csrc.nist.gov/​publications/​nistpubs/​800-22-rev1a/​SP800-22rev1a.pdf | NIST (vezi section 2.1)]]. Verificati daca secventa generata de $\mathsf{PRG}$-ul ​de mai sus este aleatoare sau nu. (presupunem ​$n=100$)+Vom folosi experimentul definit mai devreme pentru ​construi un generator pseudoaleatoriu ​($\mathsf{PRG}$): 
 +  ​Se alege lungimea $n$ a șirului ce va fi generat 
 +  ​Se obține un șir de biți $R$ de lungime $n$ (de exemplu, puteți folosi chiar și LCG-ul din Exercițiul ​1) 
 +  - Pentru fiecare bit $r$ din șirul $R$ generat anterior, ​$\mathsf{PRG}$-ul ​va întoarce un bit $b$ astfel: 
 +    * dacă bitul $r$ este $0$, atunci întoarce un bit aleatoriu $b \in \{0, 1\}$ 
 +    * dacă bitul $r$ este $1$, atunci întoarce $1$
  
-bExecutati testul pe un sir aleator ​de biti (puteti folosi sirul R folosit in $\mathsf{PRG}$) ​si comparati rezultatele.+aImplementați //frequency (monobit) test// așa cum este descris ​de către [[http://​csrc.nist.gov/​publications/​nistpubs/​800-22-rev1a/​SP800-22rev1a.pdf | NIST (vezi secțiunea 2.1)]]. Verificați dacă secvența generată de $\mathsf{PRG}$-ul de mai sus este aleatoare sau nu (să presupunem pentru $n=100$).
  
-Daca rezultatele celor 2 experimente difera in mod regulat, acest test ofera un atacator care sparge ​$\mathsf{PRG}$-ul descris mai sus.+b. Executați testul pe un șir aleatoriu de biți (de exemplu, șirul R folosit în $\mathsf{PRG}$) și comparați rezultatele.
  
-<note tip>​Pentru a genera un sir aleator ​de bitiputeti ​folosi o functie ​de forma:+Dacă rezultatele celor două experimente diferă în mod regulat, acest test vă oferă un atacator care sparge $\mathsf{PRG}$-ul descris mai sus. 
 + 
 +<note tip>​Pentru a genera un șir aleatoriu ​de bițiputeți ​folosi o funcție ​de forma:
 <code python> <code python>
 import random import random
  
-def get_random_string(n): ​#​generate ​random bit string +def get_random_string(n: int-> str: 
-    ​bstr = bin(random.getrandbits(n)).lstrip('0b').zfill(n) +    """​Generate ​random bit string"""​ 
-    return bstr+    ​return ​bin(random.getrandbits(n)).lstrip("0b").zfill(n)
 </​code>​ </​code>​
 </​note>​ </​note>​
  
-<note tip>In Python ​puteti ​folosi ​functii ​precum sqrt, fabs sau erfc din modulul math+<note tip>În Python ​puteți ​folosi ​funcții ​precum sqrt, fabs sau erfc din modulul math.
 <code python> <code python>
 import math import math
Line 240: Line 504:
 </​note>​ </​note>​
  
-==== Exercițiul 5 (Bonus) ====+<file python ex4.py>​ 
 +import math 
 +import random
  
-In acest exercitiuveti incerca sa verificati daca intr-adevar Salsa20 stream cipher este mai rapid decat RC4. Descarcati ​{{:​ic:​laboratoare:​salsa20_rc4_surse_c.zip|aceasta}} arhiva+from utils import * 
-Rulati ​programul folosind ​acelasi fisier ​de intrare ​atat pentru Salsa20 ​cat si pentru RC4. Comparati ​timpul de executie in ambele cazuri.+ 
 + 
 +def get_random_string(n:​ int) -> str: 
 +    """​Generate random bit string"""​ 
 +    return bin(random.getrandbits(n)).lstrip("​0b"​).zfill(n) 
 + 
 + 
 +def main() -> None: 
 +    N_RUNS = 100  # the number of runs 
 +    N_BITS = 1000  # the number of bits to generate 
 + 
 +    # TODO: implement and run the multiple times (e.g., 100) the 
 +    # statistical tests 
 + 
 + 
 +if __name__ == "​__main__":​ 
 +    main() 
 +</​file>​ 
 +==== Exercițiul 5 - Bonus (2p) ==== 
 + 
 +În acest exercițiuveți încerca să verificați dacă într-adevar Salsa20 stream cipher este mai rapid decât ​RC4. Descărcați ​{{:​ic:​laboratoare:​salsa20_rc4_surse_c.zip|această}} arhivă
 +Rulați ​programul folosind ​același fișier ​de intrare ​atât pentru Salsa20, cât și pentru RC4. Comparați ​timpul de execuție în ambele cazuri.
  
 <note tip> <note tip>
-Pentru sistemele UNIX (si WSL), folositi ​scriptul **prepare.sh** pentru a complila sursele ​si a genera ​fisierele ​necesare.  +Pentru sistemele UNIX (și WSL), folosiți ​scriptul **prepare.sh** pentru a complila sursele ​și a genera ​fișierele ​necesare. 
-Daca nu folositi ​WSL pe Windows, scriptul **prepare.ps1** ​genereaza fisierele ​necesare dar **nu** ​si compileaza ​sursele.+Dacă nu folosiți ​WSL pe Windows, scriptul **prepare.ps1** ​generează fișierele ​necesaredar **nu** ​și compilează ​sursele.
 </​note>​ </​note>​
  
 <note tip> <note tip>
-Folositi optiunea ​"​-h"​ pentru a afisa lista tuturor argumentelor folosite de program.+Folosiți opțiunea ​"​-h"​ pentru a afișa ​lista tuturor argumentelor folosite de program.
 </​note>​ </​note>​
  
 <note tip> <note tip>
-Uitati-va in fisierul ​salsa20.h. Unde se executa ​rundele de criptare?+Uitați-vă în fișierul ​salsa20.h. Unde se execută ​rundele de criptare?
 </​note>​ </​note>​
  
-Incercati sa implementati aceeasi functionalitate folosint ​OpenSSL. OpenSSL ​suporta ​RC4 dar nu si Salsa20. ​Folositi ​ChaCha20 in loc de Salsa20, aceasta fiind o varianta imbunatatita ​a algoritmului.+Încercați să implementați aceeași funcționalitate folosind ​OpenSSL. OpenSSL ​suportă ​RC4dar nu și Salsa20. ​Folosiți ​ChaCha20 in loc de Salsa20, aceasta fiind o variantă îmbunătățită ​a algoritmului. 
 + 
 +</​hidden>​
ic/labs/03.1633901772.txt.gz · Last modified: 2021/10/11 00:36 by philip.dumitru
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