Differences

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

Link to this comparison view

sasc:laboratoare:03 [2016/03/08 17:46]
marios.choudary
sasc:laboratoare:03 [2017/03/07 15:32] (current)
dan.dragan
Line 1: Line 1:
-===== Lab 03 =====+===== Lab 03 - PRGs =====
  
  
 ==== Exercise 1 (4p) ==== ==== Exercise 1 (4p) ====
  
-Advantage. The purpose of this problem is to clarify the concept of advantageConsider the following two experiments $\mathsf{EXP}(0)$ and $\mathsf{EXP}(1)$:​ +In this exercise we'll try to break a Linear Congruential Generator, that may be used to generate "​poor"​ random numbers
-  * In $\mathsf{EXP}(0)$ the challenger flips fair coin (probability $1/2$ for HEADS and $1/2$ for TAILS) and sends the result to the adversary $\mathsf{A}$+We implemented such weak RNG to generate ​sequence of bytes and then encrypted a plaintext message
-  * In $\mathsf{EXP}(1)$ the challenger always sends TAILS to the adversary.+The resulting ciphertext in hexadecimal is this: 
 +<​code>​ 
 +a432109f58ff6a0f2e6cb280526708baece6680acc1f5fcdb9523129434ae9f6ae9edc2f224b73a8 
 +</​code>​
  
-Let r = 0 for HEADS and r = 1 for TAILS. Then we have the experiment as shown below: +You know that the LCG uses the following formula to produce each byte:
-{{:​sasc:​laboratoare:adversar_prg.png?​400|}}+
  
-The adversary’s goal is to distinguish these two experiments:​ at the end of each experiment the adversary outputs ​bit $0$ or $1$ for its guess for which experiment it is in. For $= 0,1$ let $W_{b}$ be the event that in experiment $b$ the adversary output $1$. The adversary tries to maximize its distinguishing advantage, namely the quantity +s_next = (* s_prev + b) mod p
-$\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 experiments. If the advantage is $0$ then the adversary behaves exactly the same in both experiments ​and therefore does not distinguish ​between ​them. If 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.+where both s_prev ​and s_next are byte values (between ​0 and 255) and p is 257. 
 +Both a and b are values between 0 and 256.
  
-a. Calculate the advantage of each of the following adversaries:​ 
-  * A1: Always output $1$. 
-  * A2: Ignore the result reported by the challenger, and randomly output $0$ or $1$ with even probability. 
-  * A3: Output $1$ if HEADS was received from the challenger, else output $0$. 
-  * A4: Output $0$ if HEADS was received from the challenger, else output $1$. 
-  * A5: If HEADS was received, output $1$. If TAILS was received, randomly output $0$ or $1$ with even probability. 
  
-b. What is the maximum advantage possible in distinguishing these two experiments?​ Explain why.+You also know that the first 16 letters of the plaintext are "Let all creation"​ and that the ciphertext was generated by xor-ing a string of consecutive bytes generated by the LCG with the plaintext.
  
-==== Exercise 2 (4p) ====+Can you break the LCG and predict the RNG stream so that in the end you find the entire plaintext ? 
 + 
 +You may use this starting code: 
 +<code python '​ex1_weak_rng.py'>​ 
 +import sys 
 +import random 
 +import string 
 +import operator 
 + 
 +#Parameters for weak LC RNG 
 +class WeakRNG: 
 +    "​Simple class for weak RNG" 
 +    def __init__(self):​ 
 +        self.rstate = 0 
 +        self.maxn = 255 
 +        self.a = 0 #Set this to correct value 
 +        self.b = 0 #Set this to correct value 
 +        self.p = 257 
 + 
 +    def init_state(self):​ 
 +        "​Initialise rstate"​ 
 +        self.rstate = 0 #Set this to some value 
 +        self.update_state() 
 + 
 +    def update_state(self):​ 
 +        "​Update state"​ 
 +        self.rstate = (self.a * self.rstate + self.b) % self.p 
 + 
 +    def get_prg_byte(self):​ 
 +        "​Return a new PRG byte and update PRG state"​ 
 +        b = self.rstate & 0xFF 
 +        self.update_state() 
 +        return b 
 + 
 +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 main(): 
 + 
 +  #Initialise weak rng 
 +  wr = WeakRNG() 
 +  wr.init_state() 
 + 
 +  #Print ciphertext 
 +  CH = '​a432109f58ff6a0f2e6cb280526708baece6680acc1f5fcdb9523129434ae9f6ae9edc2f224b73a8'​ 
 +  print "Full ciphertext in hexa: " + CH 
 + 
 +  #Print known plaintext 
 +  pknown = 'Let all creation'​ 
 +  nb = len(pknown) 
 +  print "Known plaintext: " + pknown 
 +  pkh = pknown.encode('​hex'​) 
 +  print "​Plaintext in hexa: " + pkh 
 + 
 +  #Obtain first nb bytes of RNG 
 +  gh = hexxor(pkh, CH[0:​nb*2]) 
 +  print gh 
 +  gbytes = [] 
 +  for i in range(nb):​ 
 +    gbytes.append(ord(gh[2*i:​2*i+2].decode('​hex'​))) 
 +  print "Bytes of RNG: " 
 +  print gbytes 
 + 
 +  #Break the LCG here: 
 +  #1. find a and b 
 +  #2. predict/​generate rest of RNG bytes 
 +  #3. decrypt plaintext 
 + 
 +  # Print full plaintext 
 +  p = ''​ 
 +  print "Full plaintext is: " + p 
 + 
 + 
 +if __name__ == "​__main__":​ 
 +  main() ​  
 +</​code>​ 
 + 
 +==== Exercise 2 (3p) ====
  
 Let's use the experiment defined earlier as a pseudorandom generator ($\mathsf{PRG}$) as follows: Let's use the experiment defined earlier as a pseudorandom generator ($\mathsf{PRG}$) as follows:
   - Set a desired output length $n$   - Set a desired output length $n$
-  - Obtain a random sequence $R$ of bits of length $n$ (say flipping a coin, using Linear-congruential generator, or any other method)+  - Obtain a random sequence $R$ of bits of length $n$ (e.g. using the Linear-congruential generator ​from Exercise 1)
   - For each bit $r$ in the random sequence $R$ generated in the previous step, output a bit $b$ as follows:   - For each bit $r$ in the random sequence $R$ generated in the previous step, output a bit $b$ as follows:
-  * if the bit $r$ is $0$, then output a random bit $b$ (e.g. flip a coin and output either $0$ or $1$ depending on its result)+  * if the bit $r$ is $0$, then output a random bit $b \in \{01\}$
   * if the bit $r$ is $1$, then output $1$   * if the bit $r$ is $1$, then output $1$
  
Line 51: Line 129:
 <note tip>​Also,​ in Python you may find the functions sqrt, fabs and erfc from the module math useful</​note>​ <note tip>​Also,​ in Python you may find the functions sqrt, fabs and erfc from the module math useful</​note>​
  
- +==== Exercise 3 - LFSR (3p) ====
-==== Exercise 3 - LFSR (2p) ====+
  
 In this exercise we'll build a simple Linear Feedback Shift Register (LFSR). LFSRs produce random bit strings with good statistical properties, but are very easy to predict. In this exercise we'll build a simple Linear Feedback Shift Register (LFSR). LFSRs produce random bit strings with good statistical properties, but are very easy to predict.
Line 66: Line 143:
 </​code>​ </​code>​
  
-we generate a new random ​bit $b$ by $\mathsf{xor}$-ing bits $11$ ($0$) and $18$ ($1$), thus obtaining $b = 1$. We then shift the whole register to the right (thus dropping the right-most bit, which is the bit we add to the generated random sequence) and insert $b$ to the left. Thus, the new state is:+we generate a new bit $b$ by $\mathsf{xor}$-ing bits $11$ ($0$) and $18$ ($1$), thus obtaining $b = 1$. We then shift the whole register to the right (thus dropping the right-most bit, which is the bit we add to the generated random sequence) and insert $b$ to the left. Thus, the new state is:
 <​code>​ <​code>​
   state = '​100100100100100100'​   state = '​100100100100100100'​
Line 75: Line 152:
  
 Using the above starting state and polynomial, generate $100$ random bits and run the monobit statistical test from the previous exercise to see if their frequency seems random. Using the above starting state and polynomial, generate $100$ random bits and run the monobit statistical test from the previous exercise to see if their frequency seems random.
- 
sasc/laboratoare/03.1457451963.txt.gz · Last modified: 2016/03/08 17:46 by marios.choudary
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