This is an old revision of the document!


Lab 02

In this lab we'll do some exercises related to OTP and stream ciphers.

Exercise 1

Charlie manages to capture a last communication which turns out to be the most important, so it is crucial he decrypts it. However, this time Alice used the Vigenere cipher, with a key that Charlie knows has 7 characters.

The ciphertext is in the file attached. Try the method of multiplying probabilities as I explained in class and see if you can decrypt the ciphertext.

These are the known frequencies of the plaintext:

{'A': 0.07048643054277828,
'C': 0.01577161913523459,
'B': 0.012074517019319227,
'E': 0.13185372585096597,
'D': 0.043393514259429625,
'G': 0.01952621895124195,
'F': 0.023867295308187673,
'I': 0.06153403863845446,
'H': 0.08655128794848206,
'K': 0.007566697332106716,
'J': 0.0017594296228150873,
'M': 0.029657313707451703,
'L': 0.04609015639374425,
'O': 0.07679967801287949,
'N': 0.060217341306347746,
'Q': 0.0006382244710211592,
'P': 0.014357175712971482,
'S': 0.05892939282428703,
'R': 0.05765294388224471,
'U': 0.02749540018399264,
'T': 0.09984475620975161,
'W': 0.01892824287028519,
'V': 0.011148804047838086,
'Y': 0.023045078196872126,
'X': 0.0005289788408463661,
'Z': 0.00028173873045078196}

Exercise 2

In class we explained that the one time pad is malleable (i.e. we can easily change the encrypted plaintext by simply modifying the ciphertext). Let’s see a concrete example. Suppose you are told that the one time pad encryption of the message “attack at dawn” is 09e1c5f70a65ac51626bc3d25f17 (the plaintext letters are encoded as 8-bit ASCII and the given ciphertext is written in hex). What would be the one time pad encryption of the message “attack at dusk” under the same OTP key?

Exercise 3

In this exercise we'll try to break a Linear Congruential Generator, that may be used to generate “poor” random numbers. We implemented such weak RNG to generate a sequence of bytes and then encrypted a plaintext message. The resulting ciphertext in hexadecimal is this:

a432109f58ff6a0f2e6cb280526708baece6680acc1f5fcdb9523129434ae9f6ae9edc2f224b73a8

You know that the LCG uses the following formula to produce each byte:

s_next = a * s_prev + b mod p

where both s_prev and s_next are byte values (between 0 and 255) and p is 257.

You also know that the first 16 letters of the plaintext are “Let all creation” and that the ciphertext was generated by xor-ing the string generated by the LCG with the plaintext.

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:

'ex3_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()  
sasc/laboratoare/02.1456831404.txt.gz · Last modified: 2016/03/01 13:23 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