This shows you the differences between two versions of the page.
sasc:laboratoare:01 [2015/02/24 23:28] 127.0.0.1 external edit |
sasc:laboratoare:01 [2017/02/21 11:28] (current) dan.dragan |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Laboratorul 01. ===== | + | ===== Lab 01 - Introduction ===== |
+ | ==== Python Crash Course ==== | ||
+ | === Python Interactive Mode === | ||
+ | |||
+ | Python is an easy to learn interactive programming language. Throughout this lab, we'll be using Python 2.7. | ||
+ | |||
+ | You can run Python code in two ways: | ||
+ | * by writing a source file and running it (eventually, with some command line arguments) | ||
+ | * by entering commands in interactive mode | ||
+ | |||
+ | To start interactive mode, simply open a terminal window and run ''python'': | ||
+ | |||
+ | <code> | ||
+ | linux$ python | ||
+ | </code> | ||
+ | |||
+ | You can now write Python code just as you would in an actual program: | ||
+ | |||
+ | <code> | ||
+ | >>> print "Hello, SASC" | ||
+ | </code> | ||
+ | |||
+ | To quit interactive mode either press ''Ctrl+D'' or use: | ||
+ | |||
+ | <code> | ||
+ | >>> quit() | ||
+ | </code> | ||
+ | |||
+ | Interactive mode is useful when you want to quickly try something out (for example, testing decryption for a certain key) without going through the hassle of writing a new source file and running it. | ||
+ | |||
+ | |||
+ | === Python Recipe #1 - Hail, Caesar! === | ||
+ | |||
+ | In Python, indentation is important; it is used to organize code in blocks. For example, the following C code: | ||
+ | |||
+ | <code C> | ||
+ | int foo(int a, int b) { | ||
+ | int x; | ||
+ | if (a > b) { | ||
+ | x = a; | ||
+ | } else { | ||
+ | x = b; | ||
+ | } | ||
+ | return x | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | is (approximately) the same as the following in Python: | ||
+ | |||
+ | <code Python> | ||
+ | def foo(a, b): | ||
+ | if a > b: | ||
+ | x = a | ||
+ | else: | ||
+ | x = b | ||
+ | return x | ||
+ | </code> | ||
+ | |||
+ | In this first recipe we'll see how to encrypt a single letter using Caesar's cipher. | ||
+ | |||
+ | <code Python> | ||
+ | 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)] | ||
+ | </code> | ||
+ | |||
+ | Create a new file named caesar.py containing the code above. To test the code, open the interpreter and try the following: | ||
+ | |||
+ | <code python> | ||
+ | linux$ python | ||
+ | >>> from caesar import * | ||
+ | >>> print alphabet | ||
+ | >>> alphabet[0] | ||
+ | >>> ord('A') | ||
+ | >>> len(alphabet) | ||
+ | >>> ord('D') - ord('A') | ||
+ | >>> 28 % 26 | ||
+ | >>> -1 % 26 | ||
+ | >>> caesar_enc('D') | ||
+ | >>> caesar_enc('Z') | ||
+ | >>> caesar_enc('B') | ||
+ | </code> | ||
+ | |||
+ | === Python Exercise #1 - Decrypting a letter === | ||
+ | Add a ''caesar_dec'' function to ''caesar.py'', which decrypts a single letter encrypted using Caesar's cipher. | ||
+ | |||
+ | === Python Recipe #2 - Encrypting a string === | ||
+ | |||
+ | We'll now expand our function to take string as input. First, a little intro to Python ''for'' loops. Some examples: | ||
+ | |||
+ | <code python> | ||
+ | for i in [1, 2, 3]: | ||
+ | print i | ||
+ | </code> | ||
+ | |||
+ | In this first example, ''i'' iterates through the values in list ''[1, 2, 3]''. The code is similar to the classical **C** code: | ||
+ | |||
+ | <code C> | ||
+ | for (int i = 1; i <= 3; i++) { | ||
+ | printf("%d\n", i); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | To create lists of integers use the ''range'' function: | ||
+ | |||
+ | <code python> | ||
+ | for i in range(3): | ||
+ | print i | ||
+ | </code> | ||
+ | |||
+ | Execute the code above in the interpreter. Using the range function with two parameters, change the above to print integers 1 through 10. | ||
+ | |||
+ | In Python, ''for'' can iterate through multiple types of objects, including strings. Try the below: | ||
+ | |||
+ | <code python> | ||
+ | for letter in 'ABCD': | ||
+ | print letter | ||
+ | </code> | ||
+ | |||
+ | We will now use the ''for'' instruction to expand our ''caesar_enc'' function: | ||
+ | |||
+ | <code Python> | ||
+ | alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ' | ||
+ | def caesar_enc_string(plaintext): | ||
+ | ciphertext = '' | ||
+ | for letter in plaintext: | ||
+ | ciphertext = ciphertext + caesar_enc(letter) | ||
+ | return ciphertext | ||
+ | | ||
+ | </code> | ||
+ | |||
+ | 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> | ||
+ | linux$ python -i caesar.py | ||
+ | >>> test = 'HELLO' | ||
+ | >>> test + 'WORLD' | ||
+ | >>> 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> | ||
+ | |||
+ | |||
+ | === Python Exercise #2 - Decrypting a string === | ||
+ | |||
+ | Add the corresponding ''caesar_dec_string'' function. | ||
+ | |||
+ | === Python Recipe #3 - Shift ciphers === | ||
+ | |||
+ | Python allows passing default values to parameters: | ||
+ | |||
+ | <code Python> | ||
+ | def foo(a, b = 3): | ||
+ | print a, b | ||
+ | </code> | ||
+ | <code Python> | ||
+ | >>> foo(1) | ||
+ | >>> foo(1, 2) | ||
+ | </code> | ||
+ | |||
+ | 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. | ||
+ | |||
+ | <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)] | ||
+ | |||
+ | def caesar_enc_string(plaintext, k = 3): | ||
+ | ciphertext = '' | ||
+ | for letter in plaintext: | ||
+ | ciphertext = ciphertext + caesar_enc(letter, k) | ||
+ | return ciphertext | ||
+ | </code> | ||
+ | |||
+ | To test the new functions, try the below: | ||
+ | <code Python> | ||
+ | linux$ python -i caesar.py | ||
+ | >>> caesar_enc_string('HELLO') | ||
+ | >>> caesar_enc_string('HELLO', 0) | ||
+ | >>> caesar_enc_string('HELLO', 1) | ||
+ | </code> | ||
+ | |||
+ | |||
+ | === Python Exercise #3 - Shift ciphers === | ||
+ | |||
+ | Using default parameters, expand your shift cipher decryption functions to support arbitrary keys. | ||
+ | |||
+ | === Python Recipe #4 - Format conversions === | ||
+ | |||
+ | <code Python> | ||
+ | import binascii | ||
+ | |||
+ | 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 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> | ||
+ | |||
+ | |||
+ | <hidden> | ||
+ | The solution is {{:ic:laboratoare:lab1_sol.zip|here}}. | ||
+ | </hidden> |