This shows you the differences between two versions of the page.
|
ic:laboratoare:04 [2018/10/06 18:07] george.pirtoaca |
ic:laboratoare:04 [2020/11/02 01:08] (current) acosmin.maria |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | <hidden> | + | ===== Laboratorul 04 - PRFs, PRPs, SPNs ===== |
| - | ===== Laboratorul 04 - PRFs and PRPs ===== | + | |
| + | <file python utils.py> | ||
| + | import base64 | ||
| + | |||
| + | # CONVERSION FUNCTIONS | ||
| + | def _chunks(string, chunk_size): | ||
| + | for i in range(0, len(string), chunk_size): | ||
| + | yield string[i:i+chunk_size] | ||
| + | |||
| + | # THIS ONE IS NEW | ||
| + | def byte_2_bin(bval): | ||
| + | """ | ||
| + | Transform a byte (8-bit) value into a bitstring | ||
| + | """ | ||
| + | return bin(bval)[2:].zfill(8) | ||
| + | |||
| + | 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 | ||
| + | </file> | ||
| In this recitation, we shall do some exercises related to PRFs, PRPs and DES. | In this recitation, we shall do some exercises related to PRFs, PRPs and DES. | ||
| - | Please check the course, available here: | + | Please check the course available [[https://drive.google.com/file/d/1Fjybv6k5QudRB1bkAi5shVUGlUyTO_0U/view?usp=sharing|here]] and make sure you understand the basic definitions and principles before moving forward to solving the exercises. |
| - | http://cs.curs.pub.ro/2014/pluginfile.php/13095/mod_resource/content/2/sasc_curs4_5.pdf | + | |
| ==== Exercise 1 (4p) ==== | ==== Exercise 1 (4p) ==== | ||
| Line 10: | Line 69: | ||
| Let $F : K × X \to Y$ be a secure PRF with $K = X = Y = \{0, 1\}^{n}$. | Let $F : K × X \to Y$ be a secure PRF with $K = X = Y = \{0, 1\}^{n}$. | ||
| - | * a) Show that $F_1(k,x) = F(k,x) \| 0$ is not a secure PRF. (for strings $y$ and $z$ we use $y \| z$ to denote the concatenation of $y$ and $z$) | + | * a) Show that $F_1(k,x) = F(k,x) \| 0$ is not a secure PRF. (for strings $y$ and $z$ we use $y \| z$ to denote the concatenation of $y$ and $z$); |
| * b) Prove that $F_2(k, x) = F \left(k, x \oplus 1^{n}\right)$ is a secure PRF. Here $x \oplus 1^{n}$ is the bit-wise complement of $x$. To prove security argue the contra-positive: a distinguisher $A$ that breaks $F_2$ implies a distinguisher $B$ that breaks $F$ and whose running time is about the same as $A$’s. | * b) Prove that $F_2(k, x) = F \left(k, x \oplus 1^{n}\right)$ is a secure PRF. Here $x \oplus 1^{n}$ is the bit-wise complement of $x$. To prove security argue the contra-positive: a distinguisher $A$ that breaks $F_2$ implies a distinguisher $B$ that breaks $F$ and whose running time is about the same as $A$’s. | ||
| * c) Let $K_3 = \{0, 1\}^{n+1}$. Construct a new PRF $F_3 : K_3 \times X \to Y$ with the following property: the PRF $F_3$ is secure, however if the adversary learns the last bit of the key then the PRF is no longer secure. This shows that leaking even a single bit of the secret key can completely destroy the PRF security property. | * c) Let $K_3 = \{0, 1\}^{n+1}$. Construct a new PRF $F_3 : K_3 \times X \to Y$ with the following property: the PRF $F_3$ is secure, however if the adversary learns the last bit of the key then the PRF is no longer secure. This shows that leaking even a single bit of the secret key can completely destroy the PRF security property. | ||
| Line 16: | Line 75: | ||
| Hint: Let $k_3 = k \| b$ where $k \in \{0,1\}^{n}$ and $b \in \{0,1\}$. Set $F_3(k_3,x)$ to be the same as $F (k, x)$ for all $x \neq 0^{n}$. Define $F_3\left(k_3, 0^{n}\right)$ so that $F_3$ is a secure PRF, but becomes easily distinguishable from a random function if the last bit of the secret key $k_3$ is known to the adversary. Prove that your $F_3$ is a secure PRF by arguing the contra-positive, as in part (b). | Hint: Let $k_3 = k \| b$ where $k \in \{0,1\}^{n}$ and $b \in \{0,1\}$. Set $F_3(k_3,x)$ to be the same as $F (k, x)$ for all $x \neq 0^{n}$. Define $F_3\left(k_3, 0^{n}\right)$ so that $F_3$ is a secure PRF, but becomes easily distinguishable from a random function if the last bit of the secret key $k_3$ is known to the adversary. Prove that your $F_3$ is a secure PRF by arguing the contra-positive, as in part (b). | ||
| </note> | </note> | ||
| - | * d) Construct a new PRF $F_4 : K_2 × X \to Y$ that remains secure if the attacker learns any single bit of the key. Your function $F_2$ may only call $F$ once. Briefly explain why your PRF remains secure if any single bit of the key is leaked. | + | * d) Construct a new PRF $F_4 : K × X \to Y$ that remains secure if the attacker learns any single bit of the key. Your function $F_4$ may only call $F$ once. Briefly explain why your PRF remains secure if any single bit of the key is leaked. |
| - | ==== Exercise 2 ==== | + | ==== Exercise 2-3-4 ==== |
| Let's analyse some substitution-permutation networks (SPN). | Let's analyse some substitution-permutation networks (SPN). | ||
| - | === SPN 1 (3p) === | + | ==== SPN 1 (3p) ==== |
| We have the SPN from this figure: | We have the SPN from this figure: | ||
| Line 37: | Line 96: | ||
| <code python spn1.py> | <code python spn1.py> | ||
| - | import sys | + | from utils import * |
| - | import random | + | |
| - | import string | + | |
| - | import operator | + | |
| # Rijndael S-box | # Rijndael S-box | ||
| - | sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, | + | sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, |
| 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, | 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, | ||
| 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, | 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, | ||
| Line 67: | Line 123: | ||
| 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, | 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, | ||
| 0x54, 0xbb, 0x16] | 0x54, 0xbb, 0x16] | ||
| - | |||
| # Rijndael Inverted S-box | # Rijndael Inverted S-box | ||
| rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, | rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, | ||
| - | 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, | + | 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, |
| - | 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54, | + | 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, |
| - | 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, | + | 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, |
| - | 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, | + | 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, |
| - | 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8, | + | 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, |
| - | 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, | + | 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, |
| - | 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, | + | 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, |
| - | 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab, | + | 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, |
| - | 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, | + | 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, |
| - | 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, | + | 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, |
| - | 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41, | + | 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, |
| - | 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, | + | 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, |
| - | 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, | + | 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, |
| - | 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d, | + | 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, |
| - | 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b , | + | 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, |
| - | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, | + | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, |
| - | 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, | + | 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, |
| - | 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60, | + | 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, |
| - | 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, | + | 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, |
| - | 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, | + | 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, |
| - | 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b, | + | 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, |
| - | 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, | + | 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, |
| - | 0x21, 0x0c, 0x7d] | + | 0x21, 0x0c, 0x7d] |
| - | 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) | + | def permute4(s): |
| - | ha = a.decode('hex') | + | """ |
| - | hb = b.decode('hex') | + | Perform a permutatation by shifting all bits 4 positions right. |
| - | return "".join([chr(ord(x) ^ ord(y)).encode('hex') for (x, y) in zip(ha, hb)]) | + | The input is assumed to be a 16-bit bitstring |
| + | """ | ||
| + | ps = '' | ||
| + | ps = ps + s[12:16] | ||
| + | ps = ps + s[0:12] | ||
| + | return ps | ||
| - | 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): | + | def permute_inv4(s): |
| - | """ | + | """ |
| - | Transform a hex string (e.g. 'a2') into a string of bits (e.g.10100010) | + | Perform the inverse of permute4 |
| - | """ | + | The input is assumed to be a 16-bit bitstring |
| - | bs = '' | + | """ |
| - | for c in hs: | + | ps = '' |
| - | bs = bs + bin(int(c,16))[2:].zfill(4) | + | ps = ps + s[4:16] |
| - | return bs | + | ps = ps + s[0:4] |
| + | return ps | ||
| - | def bin2hex(bs): | ||
| - | """ | ||
| - | Transform a bit string into a hex string | ||
| - | """ | ||
| - | return hex(int(bs,2))[2:] | ||
| - | def byte2bin(bval): | + | def spn_1r_reduced_2s(k, x): |
| - | """ | + | """ |
| - | Transform a byte (8-bit) value into a bitstring | + | Performs an encryption with a substitution-permutation network. |
| - | """ | + | Key k = {k1, k2}, total of 16 bits (2 x 8 bits) |
| - | return bin(bval)[2:].zfill(8) | + | Input x = {x1, x2}, total of 16 bits (2 x 8 bits) |
| + | Both k and x are assumed to be bitstrings. | ||
| + | Return: | ||
| + | a 16-bit bitstring containing the encryption y = {y1, y2} | ||
| + | """ | ||
| - | def permute4(s): | + | # Split input and key |
| - | """ | + | x1 = x[0:8] |
| - | Perform a permutatation by shifting all bits 4 positions right. | + | x2 = x[8:16] |
| - | The input is assumed to be a 16-bit bitstring | + | k1 = k[0:8] |
| - | """ | + | k2 = k[8:16] |
| - | ps = '' | + | |
| - | ps = ps + s[12:16] | + | |
| - | ps = ps + s[0:12] | + | |
| - | return ps | + | |
| - | def permute_inv4(s): | + | # Apply S-box |
| - | """ | + | u1 = bitxor(x1, k1) |
| - | Perform the inverse of permute4 | + | v1 = sbox[int(u1, 2)] |
| - | The input is assumed to be a 16-bit bitstring | + | v1 = byte_2_bin(v1) |
| - | """ | + | |
| - | ps = '' | + | |
| - | ps = ps + s[4:16] | + | |
| - | ps = ps + s[0:4] | + | |
| - | return ps | + | |
| - | def spn_1r_reduced_2s(k, x): | + | u2 = bitxor(x2, k2) |
| - | """ | + | v2 = sbox[int(u2, 2)] |
| - | Performs an encryption with a substitution-permutation network. | + | v2 = byte_2_bin(v2) |
| - | Key k = {k1, k2}, total of 16 bits (2 x 8 bits) | + | |
| - | Input x = {x1, x2}, total of 16 bits (2 x 8 bits) | + | |
| - | Both k and x are assumed to be bitstrings. | + | |
| - | Return: | + | # Apply permutation |
| - | a 16-bit bitstring containing the encryption y = {y1, y2} | + | pin = v1 + v2 |
| - | """ | + | pout = permute4(pin) |
| - | # Split input and key | + | return pout |
| - | x1 = x[0:8] | + | |
| - | x2 = x[8:16] | + | |
| - | k1 = k[0:8] | + | |
| - | k2 = k[8:16] | + | |
| - | #Apply S-box | ||
| - | u1 = bitxor(x1, k1) | ||
| - | v1 = sbox[int(u1,2)] | ||
| - | v1 = byte2bin(v1) | ||
| - | u2 = bitxor(x2, k2) | + | def spn_1r_full_2s(k, x): |
| - | v2 = sbox[int(u2,2)] | + | """ |
| - | v2 = byte2bin(v2) | + | Performs an encryption with a substitution-permutation network. |
| + | Key k = {k1, k2, k3, k4}, total of 32 bits (4 x 8 bits) | ||
| + | Input x = {x1, x2}, total of 16 bits (2 x 8 bits) | ||
| + | Both k and x are assumed to be bitstrings. | ||
| - | #Apply permutation | + | Return: |
| - | pin = v1 + v2 | + | a 16-bit bitstring containing the encryption y = {y1, y2} |
| - | pout = permute4(pin) | + | """ |
| - | return pout | + | # Split input and key |
| - | + | x1 = x[0:8] | |
| - | def spn_1r_full_2s(k, x): | + | x2 = x[8:16] |
| - | """ | + | k1 = k[0:8] |
| - | Performs an encryption with a substitution-permutation network. | + | k2 = k[8:16] |
| - | Key k = {k1, k2, k3, k4}, total of 32 bits (4 x 8 bits) | + | k3 = k[16:24] |
| - | Input x = {x1, x2}, total of 16 bits (2 x 8 bits) | + | k4 = k[24:32] |
| - | Both k and x are assumed to be bitstrings. | + | |
| - | Return: | + | # Apply S-box |
| - | a 16-bit bitstring containing the encryption y = {y1, y2} | + | u1 = bitxor(x1, k1) |
| - | """ | + | v1 = sbox[int(u1, 2)] |
| + | v1 = byte_2_bin(v1) | ||
| - | # Split input and key | + | u2 = bitxor(x2, k2) |
| - | x1 = x[0:8] | + | v2 = sbox[int(u2, 2)] |
| - | x2 = x[8:16] | + | v2 = byte_2_bin(v2) |
| - | k1 = k[0:8] | + | |
| - | k2 = k[8:16] | + | |
| - | k3 = k[16:24] | + | |
| - | k4 = k[24:32] | + | |
| - | #Apply S-box | + | # Apply permutation |
| - | u1 = bitxor(x1, k1) | + | pin = v1 + v2 |
| - | v1 = sbox[int(u1,2)] | + | pout = permute4(pin) |
| - | v1 = byte2bin(v1) | + | |
| - | u2 = bitxor(x2, k2) | + | # Apply final XOR |
| - | v2 = sbox[int(u2,2)] | + | po1 = pout[0:8] |
| - | v2 = byte2bin(v2) | + | po2 = pout[8:16] |
| + | y1 = bitxor(po1, k3) | ||
| + | y2 = bitxor(po2, k4) | ||
| - | #Apply permutation | + | return y1+y2 |
| - | pin = v1 + v2 | + | |
| - | pout = permute4(pin) | + | |
| - | #Apply final XOR | ||
| - | po1 = pout[0:8] | ||
| - | po2 = pout[8:16] | ||
| - | y1 = bitxor(po1, k3) | ||
| - | y2 = bitxor(po2, k4) | ||
| - | return y1+y2 | ||
| - | | ||
| def main(): | def main(): | ||
| - | #Run reduced 2-byte SPN | + | # Run reduced 2-byte SPN |
| - | msg = 'Hi' | + | msg = 'Hi' |
| - | key = '??' # Find this | + | key = '??' # Find this |
| - | xs = str2bin(msg) | + | xs = str_2_bin(msg) |
| - | ks = str2bin(key) | + | ks = str_2_bin(key) |
| - | ys = spn_1r_reduced_2s(ks, xs) | + | ys = spn_1r_reduced_2s(ks, xs) |
| - | print 'Two y halves of reduced SPN: ' + ys[0:8] + ' (hex: ' + bin2hex(ys[0:8]) + '), ' + ys[8:16] + ' (hex: ' + bin2hex(ys[8:16]) + ')' | + | print('Two y halves of reduced SPN: ' + ys[0:8] + ' (hex: ' + bin_2_hex( |
| - | + | ys[0:8]) + '), ' + ys[8:16] + ' (hex: ' + bin_2_hex(ys[8:16]) + ')') | |
| - | #Run full 2-byte SPN | + | |
| - | msg = 'Om' | + | |
| - | key = '????' # Find this | + | |
| - | xs = str2bin(msg) | + | |
| - | ks = str2bin(key) | + | |
| - | ys = spn_1r_full_2s(ks, xs) | + | |
| - | print 'Two y halves of full SPN (2 bytes): ' + ys[0:8] + ' (hex: ' + bin2hex(ys[0:8]) + '), ' + ys[8:16] + ' (hex: ' + bin2hex(ys[8:16]) + ')' | + | |
| + | # Run full 2-byte SPN | ||
| + | msg = 'Om' | ||
| + | key = '????' # Find this | ||
| + | xs = str_2_bin(msg) | ||
| + | ks = str_2_bin(key) | ||
| + | ys = spn_1r_full_2s(ks, xs) | ||
| + | print('Two y halves of full SPN (2 bytes): ' + ys[0:8] + ' (hex: ' + bin_2_hex( | ||
| + | ys[0:8]) + '), ' + ys[8:16] + ' (hex: ' + bin_2_hex(ys[8:16]) + ')') | ||
| if __name__ == "__main__": | if __name__ == "__main__": | ||
| - | main() | + | main() |
| </code> | </code> | ||
| Line 271: | Line 290: | ||
| - Try to find the key in this case as well, using the following message/ciphertext pairs: ('Omul', 0xddcf7bc7), ('stea', 0x96d58b43), ('luna', 0x9c3f2303) . Again print the key in ascii. | - Try to find the key in this case as well, using the following message/ciphertext pairs: ('Omul', 0xddcf7bc7), ('stea', 0x96d58b43), ('luna', 0x9c3f2303) . Again print the key in ascii. | ||
| - | <note tip> This time you cannot (easily) do a brute-force on all the bytes of the last XOR. However, you may try to attack one S-box at a time. Think of the bits that affect one such S-box and find an efficient attack. | + | <note tip> This time you cannot (easily) do a brute-force on all the bytes of the last XOR. However, you may try to attack one S-box at a time. Think of the bits that affect one such S-box and find an efficient attack. Suppose you brute force k5 and k6, is it possible to find out k1? |
| </note> | </note> | ||
| - | |||
| - | |||
| - | <hidden>The solution is {{:ic:laboratoare:lab4_sol.zip|here}}.</hidden> | ||
| - | </hidden> | ||