This is an old revision of the document!
Check-out this tutorial: here.
During the labs, you will often need to convert data from one format to another. The most used data formats are the following:
Finally, here you have some useful conversion functions and XOR operations for different data formats:
import base64 # CONVERSION FUNCTIONS def _chunks(string, chunk_size): for i in range(0, len(string), chunk_size): yield string[i:i+chunk_size] def _hex(x): return format(x, '02x') def hex_2_bin(data): return ''.join(f'{int(x, 16):08b}' for x in _chunks(data, 2)) def str_2_bin(data): return ''.join(f'{ord(c):08b}' for c in data) def bin_2_hex(data): return ''.join(f'{int(b, 2):02x}' for b in _chunks(data, 8)) def str_2_hex(data): return ''.join(f'{ord(c):02x}' for c in data) def bin_2_str(data): 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 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 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 hexxor(a, b): # xor two hex-strings, trims the longer input return ''.join(_hex(int(x, 16) ^ int(y, 16)) for (x, y) in zip(_chunks(a, 2), _chunks(b, 2))) # BASE64 FUNCTIONS def b64decode(data): return bytes_to_string(base64.b64decode(string_to_bytes(data))) def b64encode(data): return bytes_to_string(base64.b64encode(string_to_bytes(data))) # PYTHON3 'BYTES' FUNCTIONS def bytes_to_string(bytes_data): return bytes_data.decode() # default utf-8 def string_to_bytes(string_data): return string_data.encode() # default utf-8
Check out the following examples:
text1 = "Ana are mere" text2 = b"Ana are mere" type(text1) # <class 'str'> type(text2) # <class 'bytes'>
Both texts store basically the same information. The difference is in how the data is internally 'encoded' into 2 different object types. During the labs, we will mostly work with str types, but some external libraries may require to transform the data from the string representation to a bytes object.
Decode the following strings:
C1 = "010101100110000101101100011010000110000101101100011011000110000100100001" C2 = "526f636b2c2050617065722c2053636973736f727321" C3 = "WW91IGRvbid0IG5lZWQgYSBrZXkgdG8gZW5jb2RlIGRhdGEu"
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”.
C1 = "000100010001000000001100000000110001011100000111000010100000100100011101000001010001100100000101" C2 = "02030F07100A061C060B1909"
Let's start with a simple one:
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)]
Create a new file named caesar.py containing the code above. To test the code, open the interpreter and try the following:
shell$ python >>> from caesar import * >>> print(alphabet) >>> alphabet[0] >>> ord('A') >>> len(alphabet) >>> ord('D') - ord('A') >>> 26 % 26 >>> 28 % 26 >>> -1 % 26 >>> caesar_enc('D') >>> caesar_enc('Z') >>> caesar_enc('B')
Add a 'caesar_dec' function to 'caesar.py', which decrypts a single letter encrypted using Caesar's cipher.
We'll now expand our function to take strings as input.
alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ' def caesar_enc_string(plaintext): ciphertext = '' for letter in plaintext: ciphertext = ciphertext + caesar_enc(letter) return ciphertext
Test the above by starting a new interpreter:
linux$ python -i caesar.py >>> test = 'HELLO' >>> test + 'WORLD' >>> caesar_enc_string(test)
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:
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()
Then you can simply run the program, or type the following in a terminal:
python test_caesar.py
Add the corresponding 'caesar_dec_string' function.
Python allows passing default values to parameters. 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.
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
To test the new functions, try the below:
shell$ python -i caesar.py >>> caesar_enc_string('HELLO') >>> caesar_enc_string('HELLO', 0) >>> caesar_enc_string('HELLO', 1)
Using default parameters, expand your shift cipher decryption functions to support arbitrary keys.
Decrypt the last ciphertext knowing that all the messages were encrypted with the same key using OTP.
8841a58f876901c9e195d1e320e0c30a017bec11b0643d30533adcb0475e85a820d64e1a0869963453b490933b7005839f7d8a9571c8a890d75773bc2acc11d5cb3259f0610e95ad6ae1ec8445fc836b661b9c0554494c430210989e4a42ff7b4c19338945a68653c89d783e8460935c93896a3d73d9bc84a8e381951443ab8ada62c5d662d43c0da848c3602d 8e14e681d0651cd5fb99d1a87cee972b4436fe19b22c3d1e7a75c2a6155ac4fa06d74e07042889300ab490d226614c818574d99a38d8a899d45478f83cca04818a3549f061079bb139a5f78542eac63873499513460d48534345addf5f42b632475623d14fb49c16c1913d7fca019f59d09b253c3c98a480e1e3829c0942bec2da478bcc6bd42a00e953883a622497 e332a0cad0610ad6e691c6b967ad90634c73ec04fe216e586272dcb0474f98b336de5252042895310ab48c93277d4089d061968e76cbe194da0174f97dc512cd8e7b59bf351a8dad39acfdcb04edc62a275695045c4e405f4910bb9e4746f27915541fc653b5c81ec09f7f22ca2d945c9c916a2a7397bc8da4add1990945b7869c4a969a7a9c3f06a846882c6c28d6f9e6255ec96dd0b50e378054b2c89f6ee255312d330508e9cf4d43db 8812e8c6842612d5a895c3a87ca28230557fe717fe2b75117571d0ad475985ae3bd04550041d8e2744a5d5ca3c60058e9e6c96db379ceb90df427df9338850c7842948a6701dd0e853b4eb9f45ffc6386e56800c5001095d4544ad934e06f3385d1f25c243a9c653eed23b3983239a589ec23d206891e882a2e3869b1445bbc38907c2d461d42c0dfb57c7207e2adbfeaa2a4bc37ccceb5777cf36f58f8776a75b242a7d105babd2564d959b79b8bd 8008ac83d06f079cfbd0dba27aee89365262a904b62d740a3679dab01305cabb3ed30b0a4c2c92270aa581d227660586827dd99e2eddeb8cda5836e835c150d28a3648fe352698e878afe19f0df7882c2b1b9914125e09500c52b08b0b5db63a5e13348952af891d8f9f37229e609254868b26206698bc85a2ad82d3465cbccf9d4396c922d42d01e644cd6e7424ccb7b12c518d6d9faf166fc538bacc947fb149773f7c444ae7c95609959776b9e028502e45e0f6186c4fa51f4c80834f373d1f0b6130b770b6e1ce87 9603efdd952614d4e69ed4ed66af95260171e61cba687b0a797795a4154893fa33cc0b094125977b0a8f9ac673745782d074968c76d3e6d8d14e7af8628438c0833a45b1351b9bbd6daef69849be9f2e6653dc4042425b425810a99e474bb7325b0566c048e79c1bcad23f308725dd1db9c52769689ca480a4ad96d41f58a786974a8c942ebd7904e407db2b632f99eea9361fd976d2a25771c574ab81 8907a18f9d671a9bfa95c5a86aabcf634072fc50b1686f177778d4e3174583b433910b2e4820953415f6a5df3a7b44c7936dd9983383a8bbc34c36ff288413c4c77b4ea5350c9be86db3fd8910f7836a277a9101544c4411455ead9a474fa075153e27c006aa891a8f803d218f24941d93976a3b7398aa8deda29895481793c58f46c2d66bd43f1afd49cb2f606bc9f2e6255ad87cdeb4036bc138abcad76ead5b232e3d446ee2cf190c8d9b76a8b37b5e7c0bf6b71d7d42a50105c1964739224a1230 960ea9dbd04e169bec9fd0be2ea790635263fb00ac216e11787d9bed47618ffa35d65d1b57699a3b45a29dd62135428e966cd8db14c9fcd8c2497fef7dc319c79f7b44a3350b97ae7fa4ea8e0beac865274c9801410d6e5e4810be965d4fa07b5c0566e14faa9b16c3947671be28941db88d393d3cb1a181bea69d924654bdcb9f58c2ce61d43407e1498827636bcdffa3634cda76d6ab127d8068badd8363ec b952fa8f836e1cccfbd0c0bd2ebd8c635925bb50bf3a78587c6fc6b74768b9991bf60b1d4c28893449a290c120355688d074908f33cee994da5836e835c150d29f2944be724f86fc2be1f19845f0893f27499117154f50454910bf90590ae17b461966c543b3cf008f95377188219256d083242d3c95a783a6e390804658a7d4da588adf62983d07ec42882f6a2ad0f9e8 a20cbb9f953f1083e283dfba3afbcf6e142fff1aa964304c606edffa574286f7608248121622916118e28580637348cb982dc9936581bd8edb0d31ff2ec2038cdf37168b385bceba2ab5fb9e48f9952c3c57833d120d6a6375608db07469871d4e3823df43b5bd00cabd16149e299c58a0a30e2672b4bd80b9aa8198037ab7d5894a85df7dd57f15