This shows you the differences between two versions of the page.
sasc:laboratoare:01 [2016/02/21 21:05] sergiu.costea |
sasc:laboratoare:01 [2017/02/21 11:28] (current) dan.dragan |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Lab 01 ===== | + | ===== Lab 01 - Introduction ===== |
==== Python Crash Course ==== | ==== Python Crash Course ==== | ||
Line 52: | Line 52: | ||
<code Python> | <code Python> | ||
def foo(a, b): | def foo(a, b): | ||
- | if (a > b): | + | if a > b: |
x = a | x = a | ||
else: | else: | ||
Line 68: | Line 68: | ||
return | return | ||
else: | else: | ||
- | return alphabet[(ord(letter) - ord('A') - 3) % len(alphabet)] | + | return alphabet[(ord(letter) - ord('A') + 3) % len(alphabet)] |
</code> | </code> | ||
Line 136: | Line 136: | ||
</code> | </code> | ||
- | Test the above by starting a new interpreter; this time, we'll skip the ''from caesar import *'' part by including it when starting interactive mode: | + | Test the above by starting a new interpreter; this time, we'll skip the ''from caesar import *'' part by running the source file before starting interactive mode: |
<code Python> | <code Python> | ||
Line 143: | Line 143: | ||
>>> test + 'WORLD' | >>> test + 'WORLD' | ||
>>> caesar_enc_string(test) | >>> caesar_enc_string(test) | ||
+ | </code> | ||
+ | |||
+ | Another way to run things, which can be very useful in general is to use a main() function and write your program script as follows: | ||
+ | |||
+ | <code Python 'test_caesar.py'> | ||
+ | import sys | ||
+ | import random | ||
+ | import string | ||
+ | import operator | ||
+ | |||
+ | alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ' | ||
+ | |||
+ | def caesar_enc(letter): | ||
+ | if letter < 'A' or letter > 'Z': | ||
+ | print 'Invalid letter' | ||
+ | return | ||
+ | else: | ||
+ | return alphabet[(ord(letter) - ord('A') + 3) % len(alphabet)] | ||
+ | |||
+ | def caesar_enc_string(plaintext): | ||
+ | ciphertext = '' | ||
+ | for letter in plaintext: | ||
+ | ciphertext = ciphertext + caesar_enc(letter) | ||
+ | return ciphertext | ||
+ | |||
+ | def main(): | ||
+ | m = 'BINEATIVENIT' | ||
+ | c = caesar_enc_string(m) | ||
+ | print c | ||
+ | | ||
+ | |||
+ | if __name__ == "__main__": | ||
+ | main() | ||
+ | </code> | ||
+ | |||
+ | Then you can simply run the program, or type the following in a terminal: | ||
+ | <code Python> | ||
+ | python test_caesar.py | ||
</code> | </code> | ||
Line 152: | Line 190: | ||
=== Python Recipe #3 - Shift ciphers === | === Python Recipe #3 - Shift ciphers === | ||
- | We'll now look at default parameter passing. | + | Python allows passing default values to parameters: |
- | TODO | + | <code Python> |
+ | def foo(a, b = 3): | ||
+ | print a, b | ||
+ | </code> | ||
+ | <code Python> | ||
+ | >>> foo(1) | ||
+ | >>> foo(1, 2) | ||
+ | </code> | ||
- | ==== Exercise 1 ==== | + | We can use default parameter values to expand our ''caesar_enc'' function to take the key as an additional parameter, without breaking compatibility with our previous code. |
- | Alice sends Bob the following ciphertexts: | + | <code Python> |
+ | def caesar_enc(letter, k = 3): | ||
+ | if letter < 'A' or letter > 'Z': | ||
+ | print 'Invalid letter' | ||
+ | return None | ||
+ | else: | ||
+ | return alphabet[(ord(letter) - ord('A') + k) % len(alphabet)] | ||
- | <code> | + | def caesar_enc_string(plaintext, k = 3): |
- | LDPWKHORUGBRXUJRG | + | ciphertext = '' |
- | XNTRGZKKGZUDMNNSGDQFNCRADENQDLD | + | for letter in plaintext: |
- | DTZXMFQQSTYRFPJDTZWXJQKFSDLWFAJSNRFLJ | + | ciphertext = ciphertext + caesar_enc(letter, k) |
- | SIOMBUFFHINNUEYNBYHUGYIZNBYFILXSIOLAIXCHPUCH | + | return ciphertext |
- | ERZRZOREGURFNOONGUQNLGBXRRCVGUBYL | + | |
- | CJIJPMTJPMAVOCZMVIYTJPMHJOCZM | + | |
- | DTZXMFQQSTYRZWIJW | + | |
- | ZPVTIBMMOPUDPNNJUBEVMUFSZ | + | |
- | FVBZOHSSUVAZALHS | + | |
- | KAGETMXXZAFSUHQRMXEQFQEFUYAZKMSMUZEFKAGDZQUSTNAGD | + | |
- | MCIGVOZZBCHRSGWFSOBMHVWBUHVOHPSZCBUGHCMCIFBSWUVPCIF | + | |
</code> | </code> | ||
- | Charlie manages to capture the ciphertexts and he finds that the cipher used for | + | To test the new functions, try the below: |
- | encryption is the shift cipher (each message possibly encrypted with a different | + | <code Python> |
- | key). Can you decrypt the messages ? | + | linux$ python -i caesar.py |
+ | >>> caesar_enc_string('HELLO') | ||
+ | >>> caesar_enc_string('HELLO', 0) | ||
+ | >>> caesar_enc_string('HELLO', 1) | ||
+ | </code> | ||
- | Charlie also knows that the plaintext consists only of the English letters A to | ||
- | Z (all capitals, no punctuation). | ||
- | ==== Exercise 2 ==== | + | === Python Exercise #3 - Shift ciphers === |
- | Alice sends Bob another ciphertext, but much longer this time: | + | Using default parameters, expand your shift cipher decryption functions to support arbitrary keys. |
- | {{:sasc:laboratoare:sasc_msg_lab1.txt|Download message file}} | + | === Python Recipe #4 - Format conversions === |
- | Charlie needs to decrypt this as well. Some colleagues tell him this is encrypted | + | <code Python> |
- | using the substitution cipher, and that again the plaintext consists only of the English letters **A** to **Z** (all capitals, no punctuation). Try to help Charlie to decrypt this. | + | import binascii |
- | Hint: use the frequency analysis mechanisms we discussed in class. Note that the frequency of each letter does not map precisely. In particular, the most frequent two letters do match well with the given table, but the others are sometimes mixed. However, Charlie knows that the most frequent bi-grams are the following (from most frequent to less frequent): | + | def strxor(a, b): # xor two strings (trims the longer input) |
- | **TH**, **HE**, **IN**, **OR**, **HA**, **ET**, **AN**, **EA**, **IS**, **OU**, **HI**, **ER**, **ST**, **RE**, **ND** | + | 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 bitxor(a, b): # xor two bit strings (trims the longer input) | ||
+ | return "".join([str(int(x)^int(y)) for (x, y) in zip(a, b)]) | ||
+ | |||
+ | def str2bin(ss): | ||
+ | """ | ||
+ | Transform a string (e.g. 'Hello') into a string of bits | ||
+ | """ | ||
+ | bs = '' | ||
+ | for c in ss: | ||
+ | bs = bs + bin(ord(c))[2:].zfill(8) | ||
+ | return bs | ||
+ | |||
+ | def hex2bin(hs): | ||
+ | """ | ||
+ | Transform a hex string (e.g. 'a2') into a string of bits (e.g.10100010) | ||
+ | """ | ||
+ | bs = '' | ||
+ | for c in hs: | ||
+ | bs = bs + bin(int(c,16))[2:].zfill(4) | ||
+ | return bs | ||
+ | |||
+ | def bin2hex(bs): | ||
+ | """ | ||
+ | Transform a bit string into a hex string | ||
+ | """ | ||
+ | return hex(int(bs,2))[2:-1] | ||
+ | |||
+ | def byte2bin(bval): | ||
+ | """ | ||
+ | Transform a byte (8-bit) value into a bitstring | ||
+ | """ | ||
+ | return bin(bval)[2:].zfill(8) | ||
+ | |||
+ | def str2int(ss): | ||
+ | """ | ||
+ | Transform a string (e.g. 'Hello') into a (long) integer by converting | ||
+ | first to a bistream | ||
+ | """ | ||
+ | bs = str2bin(ss) | ||
+ | li = int(bs, 2) | ||
+ | return li | ||
+ | |||
+ | def int2hexstring(bval): | ||
+ | """ | ||
+ | Transform an int value into a hexstring (even number of characters) | ||
+ | """ | ||
+ | hs = hex(bval)[2:] | ||
+ | lh = len(hs) | ||
+ | return hs.zfill(lh + lh%2) | ||
+ | |||
+ | def bin2str(bs): | ||
+ | """ | ||
+ | Transform a binary srting into an ASCII string | ||
+ | """ | ||
+ | n = int(bs, 2) | ||
+ | return binascii.unhexlify('%x' % n) | ||
+ | </code> | ||
+ | |||
+ | === Python Exercise #4 - Format conversions === | ||
+ | |||
+ | Find the plaintext messages for the following ciphertexts knowing that the cipher is the XOR operation (ciphertext = plaintext XOR key) and the key is "abcdefghijkl". | ||
+ | |||
+ | <code> | ||
+ | C1 = "000100010001000000001100000000110001011100000111000010100000100100011101000001010001100100000101" | ||
+ | |||
+ | C2 = "02030F07100A061C060B1909" | ||
+ | </code> | ||
- | With this information, can you tell what the ciphertext is about? | ||
+ | <hidden> | ||
+ | The solution is {{:ic:laboratoare:lab1_sol.zip|here}}. | ||
+ | </hidden> |