# CRY [TOC] ## Symmetric Cipher 1. Homophonic Substitution Cipher: Plaintext: HELLO Homophonic substitution: H → 28, 83, 79 E → 31, 22, 19, 75, 91 L → 47, 58 O → 62, 35, 89 Ciphertext: 28 31 47 47 62 To decrypt, each number is replaced with its corresponding letter. The multiple options for each letter help mask the frequency distribution. 2. Polyalphabetic Cipher (Vigenère) and Rotor Machine (Enigma): Vigenère Cipher: Plaintext: ATTACKATDAWN Key: LEMON (repeated) Encryption: A + L = L, T + E = X, T + M = F, A + O = O, C + N = P K + L = V, A + E = E, T + M = F, D + O = R, A + N = N W + L = H, N + E = R Ciphertext: LXFOPVEFRNHR Enigma Machine: Plaintext: SECRETMESSAGE Rotors: I II III, Reflector: UKW-B, Plugboard: (AR) (GK) (OP) Initial rotor positions: (1, 1, 1) Step-by-step encryption: S (1, 1, 1) → V, E (2, 1, 1) → Q, C (3, 1, 1) → B R (4, 1, 1) → L, E (5, 1, 1) → K, T (6, 1, 1) → P M (7, 1, 1) → O, E (8, 1, 1) → A, S (9, 1, 1) → X S (10, 2, 1) → F, A (1, 3, 1) → U, G (2, 3, 1) → H E (3, 3, 1) → Z Ciphertext: VQBLKPOAXFUHZ 3. Running Key Cipher: Plaintext: MEETMEATTHEPARKAT9 Key (from a book): THECURSEOFCAPISTRANOBYJOHNSTONMCCUL LEY Encryption: M + T = F, E + H = L, E + E = I, T + C = V M + U = G, E + R = V, A + S = S, T + E = X T + O = B, H + F = M, E + C = G, P + A = P A + P = P, R + I = Z, K + S = C, A + T = T T + R = K, 9 + A = 9 Ciphertext: FLIVGVSSXBMGPPZCTK9 Decryption would subtract the key letters from the ciphertext mod 26. However, if the key is unknown to the recipient, decryption is very difficult unless the key text can be guessed or recovered through cryptanalysis. I hope these examples help illustrate how each cipher works in practice! Let me know if you have any further questions. ## Feistel Cipher > Feistel ciphers is orignally designed by the cryptographer, Horst Feistel, who worked in IBM. It has the fundamental concept for the modern symmetric encryption -- block cipher. ![illustration of Feistel Cipher](https://hackmd.io/_uploads/SyK4zgzeC.png" =x500) *Fig.1 illustration of Feistel Cipher* ### Encryption > The main idea for this encryption is to have multiple round of **substitution** and **permutation**. ### Components There are several components in encryption: * Plaintext: plaintext is divided into two part, $L_i$ and $R_i$ * $K_i$: The round key (i.e., subkey) * $F$: A function to deal with right plaintext and the round key. ($F$ can be different based on different Feistel algorithm) * $\oplus$: XOR ### Preparation 2 steps to prepare: 1. pick the round keys $K_i$ and $F$, and of course the plaintext to encrpyt. 2. separate plaintext into Left and Right part, which is shown as $L_i$ and $R_i$ in the $i^{\text{th}}$ round. ### Round works 3 steps doing in each round: 1. input $R_i$ and $K_i$ as input into $F$ and generate the output. $O_{1,i} = F(R_i, K_i)$. 2. **Substitution**: $O_{2,i}$ = $L_i \oplus O_{1,i}$ 3. **Permutation**(swap): $L_{i+1} = R_{i}$ and $R_{i+1} = O_{2,i}$ to be more simply speaking: we can imagine this as a function $R$, in every round we have input $L_i$ and $R_i$, output with $R_{i}$ and $O_{2,i}$. $$ R(L_i, R_i) = (R_i, L_i \oplus F(R_i, K_i)) $$ After n rounds, the result cipher text is combined with $R_{n+1}$ and $L_{n+1}$. (As shown in left picture of fig.1) ### Decrpytion Decrpytion is just the reverse engineering of encryption. ## DES ```java /*package whatever //do not write package name here */ import java.io.*; public class GFG { // int key[]= {0,0,1,0,0,1,0,1,1,1}; int key[] = { 1, 0, 1, 0, 0, 0, 0, 0, 1, 0 }; // extra example for checking purpose int P10[] = { 3, 5, 2, 7, 4, 10, 1, 9, 8, 6 }; int P8[] = { 6, 3, 7, 4, 8, 5, 10, 9 }; int key1[] = new int[8]; int key2[] = new int[8]; int[] IP = { 2, 6, 3, 1, 4, 8, 5, 7 }; int[] EP = { 4, 1, 2, 3, 2, 3, 4, 1 }; int[] P4 = { 2, 4, 3, 1 }; int[] IP_inv = { 4, 1, 3, 5, 7, 2, 8, 6 }; int[][] S0 = { { 1, 0, 3, 2 }, { 3, 2, 1, 0 }, { 0, 2, 1, 3 }, { 3, 1, 3, 2 } }; int[][] S1 = { { 0, 1, 2, 3 }, { 2, 0, 1, 3 }, { 3, 0, 1, 0 }, { 2, 1, 0, 3 } }; // this function basically generates the key(key1 and //key2) using P10 and P8 with (1 and 2)left shifts void key_generation() { int key_[] = new int[10]; for (int i = 0; i < 10; i++) { key_[i] = key[P10[i] - 1]; } int Ls[] = new int[5]; int Rs[] = new int[5]; for (int i = 0; i < 5; i++) { Ls[i] = key_[i]; Rs[i] = key_[i + 5]; } int[] Ls_1 = shift(Ls, 1); int[] Rs_1 = shift(Rs, 1); for (int i = 0; i < 5; i++) { key_[i] = Ls_1[i]; key_[i + 5] = Rs_1[i]; } for (int i = 0; i < 8; i++) { key1[i] = key_[P8[i] - 1]; } int[] Ls_2 = shift(Ls, 2); int[] Rs_2 = shift(Rs, 2); for (int i = 0; i < 5; i++) { key_[i] = Ls_2[i]; key_[i + 5] = Rs_2[i]; } for (int i = 0; i < 8; i++) { key2[i] = key_[P8[i] - 1]; } System.out.println("Your Key-1 :"); for (int i = 0; i < 8; i++) System.out.print(key1[i] + " "); System.out.println(); System.out.println("Your Key-2 :"); for (int i = 0; i < 8; i++) System.out.print(key2[i] + " "); } // this function is use full for shifting(circular) the //array n position towards left int[] shift(int[] ar, int n) { while (n > 0) { int temp = ar[0]; for (int i = 0; i < ar.length - 1; i++) { ar[i] = ar[i + 1]; } ar[ar.length - 1] = temp; n--; } return ar; } // this is main encryption function takes plain text as //input uses another functions and returns the array of //cipher text int[] encryption(int[] plaintext) { int[] arr = new int[8]; for (int i = 0; i < 8; i++) { arr[i] = plaintext[IP[i] - 1]; } int[] arr1 = function_(arr, key1); int[] after_swap = swap(arr1, arr1.length / 2); int[] arr2 = function_(after_swap, key2); int[] ciphertext = new int[8]; for (int i = 0; i < 8; i++) { ciphertext[i] = arr2[IP_inv[i] - 1]; } return ciphertext; } // decimal to binary string 0-3 String binary_(int val) { if (val == 0) return "00"; else if (val == 1) return "01"; else if (val == 2) return "10"; else return "11"; } // this function is doing core things like expansion // then xor with desired key then S0 and S1 //substitution P4 permutation and again xor we have used //this function 2 times(key-1 and key-2) during //encryption and 2 times(key-2 and key-1) during //decryption int[] function_(int[] ar, int[] key_) { int[] l = new int[4]; int[] r = new int[4]; for (int i = 0; i < 4; i++) { l[i] = ar[i]; r[i] = ar[i + 4]; } int[] ep = new int[8]; for (int i = 0; i < 8; i++) { ep[i] = r[EP[i] - 1]; } for (int i = 0; i < 8; i++) { ar[i] = key_[i] ^ ep[i]; } int[] l_1 = new int[4]; int[] r_1 = new int[4]; for (int i = 0; i < 4; i++) { l_1[i] = ar[i]; r_1[i] = ar[i + 4]; } int row, col, val; row = Integer.parseInt("" + l_1[0] + l_1[3], 2); col = Integer.parseInt("" + l_1[1] + l_1[2], 2); val = S0[row][col]; String str_l = binary_(val); row = Integer.parseInt("" + r_1[0] + r_1[3], 2); col = Integer.parseInt("" + r_1[1] + r_1[2], 2); val = S1[row][col]; String str_r = binary_(val); int[] r_ = new int[4]; for (int i = 0; i < 2; i++) { char c1 = str_l.charAt(i); char c2 = str_r.charAt(i); r_[i] = Character.getNumericValue(c1); r_[i + 2] = Character.getNumericValue(c2); } int[] r_p4 = new int[4]; for (int i = 0; i < 4; i++) { r_p4[i] = r_[P4[i] - 1]; } for (int i = 0; i < 4; i++) { l[i] = l[i] ^ r_p4[i]; } int[] output = new int[8]; for (int i = 0; i < 4; i++) { output[i] = l[i]; output[i + 4] = r[i]; } return output; } // this function swaps the nibble of size n(4) int[] swap(int[] array, int n) { int[] l = new int[n]; int[] r = new int[n]; for (int i = 0; i < n; i++) { l[i] = array[i]; r[i] = array[i + n]; } int[] output = new int[2 * n]; for (int i = 0; i < n; i++) { output[i] = r[i]; output[i + n] = l[i]; } return output; } // this is main decryption function // here we have used all previously defined function // it takes cipher text as input and returns the array //of decrypted text int[] decryption(int[] ar) { int[] arr = new int[8]; for (int i = 0; i < 8; i++) { arr[i] = ar[IP[i] - 1]; } int[] arr1 = function_(arr, key2); int[] after_swap = swap(arr1, arr1.length / 2); int[] arr2 = function_(after_swap, key1); int[] decrypted = new int[8]; for (int i = 0; i < 8; i++) { decrypted[i] = arr2[IP_inv[i] - 1]; } return decrypted; } public static void main(String[] args) { GFG obj = new GFG(); obj.key_generation(); // call to key generation // function // int []plaintext= {1,0,1,0,0,1,0,1}; int[] plaintext = { 1, 0, 0, 1, 0, 1, 1, 1 }; // extra example for checking purpose System.out.println(); System.out.println("Your plain Text is :"); for (int i = 0; i < 8; i++) // printing the // plaintext System.out.print(plaintext[i] + " "); int[] ciphertext = obj.encryption(plaintext); System.out.println(); System.out.println( "Your cipher Text is :"); // printing the cipher // text for (int i = 0; i < 8; i++) System.out.print(ciphertext[i] + " "); int[] decrypted = obj.decryption(ciphertext); System.out.println(); System.out.println( "Your decrypted Text is :"); // printing the // decrypted text for (int i = 0; i < 8; i++) System.out.print(decrypted[i] + " "); } } ``` ## AES ``` AddRoundKey(S, K[0]); for (int round = 1; round <= 10; round++){ SubBytes(S); ShiftRows(S); if (round != 10) // Not final round MixColumns(S); AddRoundKey(S,K[round]); } ``` * Add Round Key: * ![image](https://hackmd.io/_uploads/SJdR7MOMC.png =750x) * Substitute Bytes: * ![image](https://hackmd.io/_uploads/H1-TwMOfR.png =750x) * Shift Rows * ![image](https://hackmd.io/_uploads/rJUBYMOMC.png =750x) * Mix Columns * ![image](https://hackmd.io/_uploads/Byjg9fuMC.png =750x) ## EC $$ y^2 = x^3 + Ax + B $$ where ($4A^3 + 27B^2 \neq 0$) Weierstrass Form secp256k1: $$ y^2 = x^3 + 7 $$ **EC over Finite Field** ![image](https://hackmd.io/_uploads/HJRPkKUzR.png =750x) so points on this elliptic curve are: `(1,1), (1,4), (2,0), (3,1), (3,4), (4,0)` + point at infinity $\infty$. Elliptic Curve over field $F$: $$ E(F) = \{ \infty \} \cup \{(x,y) \in F \times F | y^2 + ... = x^3 + ... \} $$ * Forms an **Albelian group** * Symmetric about the **x-axis** * Points of the curve: $P=(x,y)$ with $x, y \in F$ and point $\infty$ * point $\infty$ acting as **Indetity Element in Abelian group**. P, Q, R in E(Fp): 1. commutativity: P + Q = Q + P 2. associativity: (P + Q) + R = P + (Q + R) 3. existence of an identity element: P + O = O + P = P 4. existence of inverses: -P s.t. -P + P = P + (-P) = O **Addition** ![image](https://hackmd.io/_uploads/B1xoIFUf0.png =750x) **Doubling** ![image](https://hackmd.io/_uploads/ByQxPFIfR.png =750x) $$ x_3 = m^2-2x_1; y_3 = m(x_1-x_3)-y_1 $$ **Multiplication** ![image](https://hackmd.io/_uploads/HyXZvt8zA.png =750x) **ECDLP** Q = mP given Q and P, find the value of m. **ECDH** public : curve, point P and Q, prime number private key: bigint $p_A, p_B$ public key: $Q_A$ and $Q_B$ 1. Alice picks $p_A$, computes $Q_A=p_AP$ 2. Bob picks $p_B$, computes $Q_B=p_BP$ 3. Computes: * Alice $p_AQ_B=p_Ap_BP$ * Bob $p_BQ_A=p_Ap_BP$ * both use the **x-value** of this point as the secret key `k` Example: ![image](https://hackmd.io/_uploads/SJbpCFUM0.png =750x) ![image](https://hackmd.io/_uploads/HJK9J9UMR.png =750x) ECDSA ![image](https://hackmd.io/_uploads/BkX2coLM0.png =750x) ![image](https://hackmd.io/_uploads/SyLi2oUGR.png =750x) --- ## Bitcoin * Elliptic Curve: `Secp256k1` * Hash function: `SHA256` **Hash function** * Consistent: H(A) always = K * Pre-image Resistance(one way): given K hard to find A. * 2nd Pre-image Resistance: given A, hard to find B s.t. H(A) = H(B) * Collision Resistance: given H(W) = Z, hard to find X s.t. H(X) = Z. --- ## Security ### Types of SQL Injection Attacks: 1. **Commenting Out**: - **Description**: Attackers can manipulate queries by injecting comment symbols (`--` or `/* */`) to neutralize part of the original SQL command. - **Example**: If a login query is `SELECT * FROM users WHERE username = 'user_input' AND password = 'pass_input'`, an attacker could provide the username input as `admin'--`. This effectively turns the SQL into `SELECT * FROM users WHERE username = 'admin'--' AND password = 'whatever'`, ignoring everything after the `--` (which comments out the rest of the SQL command), bypassing the password check. 2. **Boolean Precedence**: - **Description**: Utilizes the precedence of Boolean operations to manipulate query logic. - **Example**: Input such as `Nguyen' OR '1'='1` could be used in a login form. The resulting SQL query `SELECT * FROM users WHERE username = 'Nguyen' OR '1'='1' AND password = 'user_input'` always returns true because `'1'='1'` is always true, allowing authentication bypass. 3. **Batched SQL Statements with Semicolon**: - **Description**: Attackers exploit the semicolon (`;`) to inject multiple SQL commands. - **Example**: For a query like `SELECT * FROM Customer WHERE CustID = user_input`, an attacker's input of `1; DELETE FROM Customer` would lead to execution of two commands: fetching customer details for ID `1` and deleting all entries from the Customer table. 4. **Union SELECT**: - **Description**: Attackers use `UNION` to combine the results of two or more `SELECT` statements into a single result set. - **Example**: An attacker could input `1 UNION SELECT username, password FROM users`, appended to a legitimate query. This would return a dataset that includes not only the intended data but also usernames and passwords from the users table. 5. **Sub-Queries**: - **Description**: Injection of subqueries can manipulate the intended logical flow of the main query. - **Example**: If an application constructs SQL commands like `UPDATE users SET address = 'user_input' WHERE userID = x`, an input such as `'a', (SELECT password FROM users WHERE username='admin'), 'b'` could expose sensitive data or perform unintended actions. 6. **Using URL Parameters**: - **Description**: Manipulating URL parameters to inject SQL code. - **Example**: In URLs like `http://example.com/app?id=3`, an attacker might change this to `http://example.com/app?id=3; DROP TABLE users`, which could lead to SQL command execution that drops (deletes) the users table. ### Prevention Techniques: - **Input Validation and Sanitization**: Ensuring only valid and expected inputs are processed. - **Parameterized Queries**: Using prepared statements where SQL code and data are separated, preventing execution of injected malicious SQL. - **Stored Procedures**: Encapsulating the SQL logic within the database itself, which can limit exposure to SQL injection if used correctly. These examples underscore the importance of adhering to secure coding practices and implementing robust input validation strategies to mitigate the risk of SQL injection attacks. ### Overview of Cross-Site Scripting (XSS) XSS attacks occur when malicious scripts are injected into content that other users see. In a web application context, this often happens when user-generated content isn't properly sanitized before being rendered in web browsers. This allows attackers to execute scripts in the victim's browser context, potentially leading to unauthorized actions. ### Types of XSS Attacks: 1. **Stored XSS (Persistent)**: - **Description**: The malicious script is permanently stored on target servers, such as in a database, message forum, visitor log, comment field, etc. It is then served to users within web pages whenever they access the stored information. - **Example**: An attacker posts a comment on a blog that includes a `<script>` tag executing malicious JavaScript. Every user viewing the comment will execute the script. 2. **Reflected XSS (Non-Persistent)**: - **Description**: The malicious script is reflected off the web server, such as in an error message, search result, or any response that includes some or all of the input sent to the server as part of the request. - **Example**: An attacker sends a link containing malicious JavaScript embedded in the URL. When the link is clicked, the script travels to the server, which reflects the script back to the user’s browser, where it is executed. 3. **DOM-Based XSS**: - **Description**: This type of XSS attack occurs when a script takes data from the client-side Document Object Model (DOM) that's controlled by an attacker and processes it in an unsafe way. - **Example**: JavaScript on a page takes a URL parameter and makes a DOM write with it without proper sanitization, potentially altering the DOM environment and executing the attacker’s script. ### Key Prevention Strategies: - **Output Encoding/Sanitization**: Ensure that all output is encoded to prevent scripts from executing, which typically involves converting special characters into their HTML-encoded equivalents. - **Content Security Policy (CSP)**: Implementing CSP can restrict the sources of executable scripts and thus prevent the execution of unauthorized scripts. - **Validating Input**: It's equally important to validate and sanitize all user inputs to ensure they do not contain executable code before they are processed or stored. ### Real-World Implications and Security Measures: The slides emphasize the need for vigilant output handling to prevent XSS vulnerabilities, showcasing various attack vectors and methodologies for exploiting unsanitized or improperly handled user inputs in web applications. Academic and development frameworks recommend adhering to secure coding practices, including regular security audits and updates, to mitigate these risks. This understanding and approach toward handling XSS vulnerabilities are crucial in developing secure web applications that protect user data and maintain integrity and trust in digital platforms. The slide from the provided PDF discusses **C/C++ security vulnerabilities**, particularly focusing on buffer overflow vulnerabilities and memory management issues. Below is a summary that outlines each key point with examples and relevant code snippets. ### C/C++ Buffer Overflow - **Description**: C and C++ languages do not automatically check to see if data exceeds array bounds. This can lead to buffer overflow, where excessive data spills over into adjacent memory. - **Example**: A user enters a string longer than the buffer allocated for it, causing the application to write beyond the buffer. - **Code**: ```c char buffer[10]; strcpy(buffer, "This string is too long for the buffer"); ``` - **Prevention**: Programmers must explicitly check the length of input to prevent overflow. ```c char buffer[10]; if (strlen(user_input) < 10) { strcpy(buffer, user_input); } ``` ### C/C++ Memory Allocation - **Stack vs. Heap Allocation**: - **Stack**: Memory allocation at compile time. Faster, but prone to stack overflow. - **Code**: `int numberPoints = 10;` - **Heap**: Memory allocation at runtime using functions like `malloc`. More flexible but can lead to heap overflow. - **Code**: `int* ptr = malloc(10 * sizeof(int));` ### Original UNIX Password Checking - **Process**: 1. Username and password are input and stored. 2. User-supplied password is encrypted and compared to the stored encrypted password. - **Buffer Overflow Exploit**: - **Scenario**: If the user inputs a password that overflows the buffer, it could overwrite the stored encrypted password, allowing unauthorized access. - **Example**: By inputting a long password, an attacker can manipulate the memory to authenticate without a valid password. - **Code**: ```c char user[8], pwd[8], epwd[8], uepwd[8]; strcpy(pwd, "user_long_password_that_overflows"); ``` - **Prevention**: Ensure bounds checking is performed on all user inputs. ### C/C++ Poisoned Null Byte - **Description**: C/C++ strings are null-terminated. If a null byte is inserted in the middle of a string, it can lead to security issues, especially when interfacing with APIs expecting null-terminated strings. - **Example**: Manipulating file processing routines by embedding a null byte in a filename, tricking the program into accepting a dangerous file type. - **Code**: ```c char filename[] = "malicious.php\0.jpg"; ``` - **Prevention**: Always validate and sanitize inputs, especially when processing filenames or other critical data that might be exposed to external input. ### Summary These topics highlight the importance of proper memory management, input validation, and secure coding practices in C/C++ to prevent security vulnerabilities like buffer overflows and poisoned null byte attacks. By implementing thorough checks and using safer coding practices, such as using managed objects like `std::string` or `std::vector`, programmers can significantly reduce the risk of these common security issues in software development. The provided PDF slide focuses on Java security and demonstrates how to utilize Java's standard cryptographic libraries for secure application development. Below is a bullet-point summary of each key point in the slides along with examples and code snippets where applicable: ### Java Security Packages - **Key Points**: - Avoid implementing custom cryptographic algorithms. - Utilize Java's built-in cryptographic packages for reliable security. - **Java Crypto Packages**: - `java.security.*` - `javax.crypto.*` - `javax.crypto.spec.*` ### Java Cryptographic Functions: Implementation - **Symmetric Key Generation**: - Uses Java to generate a random AES key for encryption and decryption. - **Example**: Generating a secret AES key. - **Code**: ```java KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(128); // Initialize the key generator SecretKey secretKey = keyGen.generateKey(); ``` - **Public Key Encryption**: - Creating and using RSA key pairs for encryption and decryption. - **Example**: Generating an RSA key pair. - **Code**: ```java KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); KeyPair keyPair = keyPairGen.generateKeyPair(); ``` - **Message Digests and Digital Signatures**: - Signing and verifying digital signatures using message digests. - **Example**: Creating a SHA-256 digest and signing it. - **Code**: ```java MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] messageDigest = md.digest(inputData.getBytes()); ``` ### Java Security Demo - File Encryption App - **Key Points**: - Demonstrates file encryption using Java's cryptographic libraries. - **Example**: Encrypting and decrypting files with AES. - **Code**: ```java Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] encryptedData = cipher.doFinal(plainData.getBytes()); ``` ### Practical Implementation Considerations - **AES Key Generation**: - Shows how to generate an AES key for encryption and decryption. - **Code**: ```java KeyGenerator kg = KeyGenerator.getInstance("AES"); kg.init(128); SecretKey aesKey = kg.generateKey(); ``` - **AES Encryption/Decryption**: - Details on setting up AES encryption and decryption processes. - **Code**: ```java Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, aesKey); byte[] cipherText = cipher.doFinal(plainText.getBytes()); ``` - **RSA Key Pair Generation**: - Describes generating RSA key pairs for secure communication. - **Code**: ```java KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048); KeyPair kp = kpg.generateKeyPair(); PublicKey publicKey = kp.getPublic(); PrivateKey privateKey = kp.getPrivate(); ``` ### Secure Development Practices - **Overview**: - Emphasizes the importance of integrating security practices throughout the software development lifecycle. - Discusses methods like static analysis, penetration testing, and continuous security integration to enhance application security. This summary provides a concise understanding of Java's cryptographic capabilities demonstrated in the lecture slides, highlighting the application of these technologies in developing secure software solutions. --- ## Practice ![image](https://hackmd.io/_uploads/SyAeQzKfR.png =750x) To answer the questions: 1. This is not a two-key system because the same permutation key is used for both encryption and decryption, just in reverse order. In a two-key system, different keys are used for encryption and decryption. 2. For a ciphertext-only attack, where the attacker only has access to the ciphertext, at least 6 letters of ciphertext would be needed. Since the encryption is done in blocks of 5 characters rearranged from the 32 character alphabet, 5 ciphertext characters could come from any of the 32^5 = 1,073,741,824 possible permutations of 5 plaintext characters. With 6 ciphertext characters, there would be 32^6 = 34,359,738,368 possible permutations, making the attack more feasible. 3. To handle messages that are not an exact multiple of 5 letters long, a padding scheme could be used. One approach is to append a special padding character (e.g. 'X') to the end of the message until its length is a multiple of 5. The decryption process would then remove these padding characters after decrypting the full message. ![image](https://hackmd.io/_uploads/SyzUXGtzA.png =750x) To calculate the redundancy of this language, we need to find the entropy of the language and subtract it from the maximum possible entropy for an alphabet of 4 letters. The maximum possible entropy for an alphabet of 4 letters is log2(4) = 2 bits per letter. Given information: - P(a) = 3/8 - P(β) = P(γ) = 1/4 - P(δ) = 1/8 - The probability of any two-letter combination is the product of the probabilities of each letter occurring independently. The entropy H of the language can be calculated as: H = -Σ P(x) log2 P(x), where x are all possible letters and combinations. H = -(3/8) log2 (3/8) - (1/4) log2 (1/4) - (1/4) log2 (1/4) - (1/8) log2 (1/8) - (3/8 * 3/8) log2 (3/8 * 3/8) - (3/8 * 1/4) log2 (3/8 * 1/4) - ... (for all two-letter combinations) Simplifying, we get: H = (3/8) log2 (8/3) + (1/2) log2 (2) + (1/8) log2 (8) - (9/64) log2 (64/9) - (3/32) log2 (32/3) - ... The redundancy is the maximum possible entropy (2 bits per letter) minus the actual entropy H. Redundancy = 2 - H = 2 - [(3/8) log2 (8/3) + (1/2) log2 (2) + (1/8) log2 (8) - (9/64) log2 (64/9) - (3/32) log2 (32/3) - ...] So the redundancy can be expressed in terms of log2(3), log2(2), log2(8), log2(64/9), log2(32/3), and so on, without needing to calculate the exact value. ![image](https://hackmd.io/_uploads/SJ5jQfFz0.png =750x) For the first question, to hide the redundancy in their language using the cipher alphabet {A, B, C, D, E, F, G, H}, they can assign the letters of their 4-letter native alphabet to different combinations of the 8 cipher letters. For example: a → AB β → CD γ → EF δ → GH By doing this mapping, the frequency distribution of the individual cipher letters A-H will be more uniform, thus hiding the redundancy present in their native 4-letter alphabet. For the second question, to hide two different messages in the ciphertext with their own keys, they would need at least 16 letters from the English alphabet. This is because each message would require its own permutation key, and with 8 cipher letters, there are 8! = 40,320 possible permutations. An example encoding could be: Message 1: "SECRET PLAN" encoded with the key ABCDEFGH → FDAHGEBC Message 2: "ATTACK NOW" encoded with the key HGFEDCBA → WNKCTAACD This code would be easier to break than the previous one because, with 16 different letters, there are only 16! = 20,922,789,888,000 possible permutation keys, which is significantly fewer than the number of possible keys in the previous code (32^5 = 1,073,741,824 for 5-letter blocks). Additionally, the presence of digrams and trigrams in the English language would provide frequency analysis clues, making it easier to break the code compared to the previous code based on a 4-letter alphabet with no special digrams or trigrams. ![image](https://hackmd.io/_uploads/B1x_RmYGC.png =750x) 1. A rotor machine, like the Enigma, could be used to encrypt a text document by inputting the plaintext letters and having the machine perform a complex, dynamic substitution cipher. The advantages of using a rotor machine for encryption include: - The encryption is highly secure due to the large number of possible rotor configurations and settings. - The substitution changes with each letter, making cryptanalysis very difficult. - It automates the encryption process, making it faster than manual methods. 2. The Enigma machine used a set of interchangeable rotors that rotated with each key press to create a dynamic substitution. However, it had some weaknesses that ultimately led to its breaking: - The reflector ensured no letter could encrypt to itself, a property exploited by cryptanalysts. - Procedural flaws, such as using predictable message headers or key settings, provided clues. - The plugboard did not have enough connections to significantly enhance security. - Advancements in computing (like the Bombe machine) and human ingenuity enabled Allied cryptanalysts to deduce Enigma settings and break messages. 3. For secure encryption, a modern mechanical rotor machine would need several rotors (5+) to create a large key space. However, it likely would not rely solely on mechanical components, as this limits the encryption complexity and speed compared to electronic or computerized designs. While a purely mechanical system could be secure with enough rotors, incorporating some electronic components and digital logic (without full-fledged computers) would allow for more advanced encryption schemes. The exact number of rotors required would depend on the specific design and desired security level, but at least 5-10 rotors with irregular stepping and additional permutation components would be a starting point for a secure mechanical/electronic hybrid encryption machine. The main advantage of a mechanical design is that it doesn't rely on computers, which can potentially be compromised remotely. A well-designed mechanical or hybrid system with a large key space and complex stepping/permutation rules could provide very strong encryption without the cyber vulnerabilities of a purely digital system. However, it would be slower and likely more expensive than a computer-based solution. ![image](https://hackmd.io/_uploads/Sy2DAGIGA.png =750x) p = 5, q = 7, n = 35, $\phi(n) = 4*6 = 24$ e = 7, d = 31, ed = 217 mod 24 = 1 M = 17 pk = e, n = 7, 35 sk = d, n = 31, 35 C = M^e mod n = 17^7 mod 35 17^1 mod 35 = 17 17^2 mod 35 = 289 mod 35 = 9 17^3 mod 35 = 17 * 9 mod 35 = 153 mod 35 = 13 17^7 mod 35 = 17^2 * 17^2 * 17^3 mod 35 = 9 * 9 * 13 mode 35 = 1053 mod 35 = 3 C = 3 P = C^d mod n = 3^31 mod 35 3^1 mod 35 = 3 3^2 mod 35 = 9 3^4 mod 35 = 81 mod 35 = 11 3^8 mod 35 = 121 mod 35 = 16 3^10 mod 35 = 16 * 9 mod 35 = 144 mod 35 = 4 3^31 mod = 3^10 * 3^10 * 3^10 * 3 mod 35 = 4 * 4 * 4 * 3 mod 35 = 64 * 3 mod 35 = 29 * 3 mod 35 = 87 mod 35 = 17 --- ### DES, AES ![image](https://hackmd.io/_uploads/SkPkeGOMR.png =750x) Let's delve into these questions regarding the Feistel cipher structure used in DES and the application of DES in a hardware encryption device: ### Question 1: Encryption and Decryption with a Feistel Cipher **Feistel Cipher Overview**: A Feistel cipher is a symmetric structure used in the construction of block ciphers. It is named after Horst Feistel and has the feature that the encryption and decryption processes are very similar, even using the same key generation algorithm. The structure splits the data block into two halves and processes them through multiple rounds of permutation and substitution. **Encryption Process**: - Split the plaintext block into two equal parts, \(L_0\) and \(R_0\). - For each round \(i\), compute: $$ L_{i+1} = R_i \]\[ R_{i+1} = L_i \oplus f(R_i, K_i) $$ ![image](https://hackmd.io/_uploads/B1bGf-YfC.png =750x) Where \(f\) is a round function and \(K_i\) is a subkey generated from the main key. **Decryption Process**: - Apply the same structure but reverse the order of subkeys: $$ R_i = L_{i+1} \] \[ L_i = R_{i+1} \oplus f(L_{i+1}, K_i) $$ ![image](https://hackmd.io/_uploads/SyLQMWKf0.png =750x) - Since the operations of a Feistel cipher are their own inverses, the decryption process effectively undoes the encryption. **Proof that Decryption Undoes Encryption**: Given the last round of encryption outputs \(L_n\) and \(R_n\), the first round of decryption will use these as inputs: $$ R_n = L_{n-1} \text{ (from encryption)} \] \[ L_n = R_{n-1} \oplus f(R_n, K_n) \text{ (from encryption)} $$ ![image](https://hackmd.io/_uploads/BJbEMZFzC.png =750x) The decryption will transform these back to \(L_{n-1}\) and \(R_{n-1}\), demonstrating that each step of decryption reverses the corresponding step of encryption, ultimately restoring the original plaintext. ### Question 2: DES Algorithm and Feistel Structure **DES and Feistel Structure**: - **Key Length**: DES uses a 56-bit key, plus 8 parity bits that are not used by the encryption algorithm. - **Feistel Scheme**: DES employs a 16-round Feistel structure. The main operations involve expanding the 32-bit half-block (right half), mixing it with a subkey using XOR, and then substituting using S-boxes followed by a permutation. **Role of S-Boxes in DES**: - **S-Boxes (Substitution boxes)**: These are at the heart of DES's security, providing non-linearity and complexity. Each round uses eight S-boxes, each taking 6 input bits and producing 4 output bits. They transform input bits in a way that the output bits are dependent on the input in a non-linear fashion, crucial for cryptographic security. ### Question 3: Employing DES Chips in Hardware **Design Considerations**: - **Triple DES (3DES)**: Given the vulnerabilities of DES to brute-force attacks due to its 56-bit key length, using Triple DES would be advisable. It involves encrypting with one key, decrypting with a second key, and encrypting again with a third key, effectively increasing the key length and security. **Security Enhancements**: - **Physical Security**: Implement measures to prevent side-channel attacks such as differential power analysis (DPA) and fault analysis, which could exploit hardware implementation to extract keys. - **Key Management**: Secure key generation and storage mechanisms are critical. Use hardware security modules (HSM) to manage and protect the encryption keys. **Conclusion**: When employing DES chips in a device, especially if anticipating sophisticated attacks, enhancing the security of the basic DES through multiple encryption layers (like 3DES) and robust physical and key management security measures is essential to safeguard data effectively. ![image](https://hackmd.io/_uploads/ByoShM_z0.png =750x) ### Question 4: Process of Choosing AES vs. DES **AES Selection Process:** - The selection process for the Advanced Encryption Standard (AES) was markedly different from that of the Data Encryption Standard (DES). AES was chosen through an open competition held by the National Institute of Standards and Technology (NIST), starting in 1997. Cryptographers from around the world were invited to submit their algorithms. The criteria for selection included security (resistance to all known types of cryptanalytic attack), cost (computational and memory efficiency), algorithm and implementation characteristics (simplicity, flexibility, etc.). **DES Selection Process:** - In contrast, DES was developed in the early 1970s by IBM in collaboration with the National Security Agency (NSA). The process was much less transparent than the AES selection. While IBM developed the algorithm itself, the NSA made certain modifications, the details of which were not fully disclosed at the time, leading to public skepticism about the robustness and security of DES. **Comparison and Evaluation:** - **Transparency**: The AES process was more transparent, involving the public and cryptography community extensively, which helped in building trust in the new standard. - **Inclusiveness**: The AES competition allowed multiple entries from various international experts, making the process more inclusive and comprehensive. - **Security**: AES supports larger key sizes (128, 192, and 256 bits) compared to DES’s 56-bit key, making AES significantly stronger against brute force attacks. - **Adaptability**: AES is designed to be efficient both in software and hardware, on a wide range of platforms, from smart cards to high-performance computers. **Conclusion**: The process leading to the selection of AES is generally considered better because it was more open, competitive, and inclusive, leading to a stronger and more accepted encryption standard. ### Question 5: Rijndael's Polynomial Arithmetic **Rijndael's AES Polynomial Arithmetic:** - The Rijndael algorithm, which became AES, uses polynomial arithmetic over the finite field GF(2^8) for several of its internal operations. Each byte of the state in AES is treated as a polynomial over GF(2), and the operations in the algorithm—such as `SubBytes`, `ShiftRows`, `MixColumns`, and `AddRoundKey`—make use of this polynomial arithmetic. **Advantages Over DES's S-Boxes:** - **Resistance to Cryptanalysis**: Polynomial operations in Rijndael do not have the same weaknesses as the S-boxes in DES, which were vulnerable to differential and linear cryptanalysis. Rijndael’s structure provides better security by diffusing input differences across multiple bytes of the state. - **Efficiency and Parallelism**: Polynomial arithmetic allows for efficient implementation in both software and hardware. The operations can be parallelized easily, making AES faster in environments that support parallel processing. - **Simplicity and Mathematical Foundation**: The use of finite field arithmetic gives AES a strong mathematical foundation, making it easier to analyze and prove certain security properties. **Summary**: Using polynomial arithmetic provides AES with a robust mathematical structure that enhances security and efficiency. This approach addresses some of the cryptanalytic vulnerabilities that were present in DES due to its reliance on fixed S-boxes, contributing to the overall strength and reliability of AES as an encryption standard. ### Bitcoin ![image](https://hackmd.io/_uploads/SJZhm38fC.png =750x) Let's answer each of these questions one by one, providing insights into networking, digital currencies, and blockchain technologies: ### Question 1: Difference between a Peer-to-Peer Network and a Centralized Network **Peer-to-peer (P2P) network**: In a peer-to-peer network, each node in the network can act as both a client and a server. This allows all nodes to share resources and communicate directly without needing a central server. The main advantages include decentralized management, failure resilience (since there is no single point of failure), and potentially better scalability as more nodes join the network. **Centralized network**: In contrast, a centralized network depends on central servers to handle the management of the network, provide resources, and mediate communications. These servers are critical points that manage traffic and provide crucial services like authentication and file storage. **Things harder to do with a peer-to-peer network**: - Centralized monitoring and data collection are more difficult because there is no single point through which all data passes. - Implementing global updates or changes can be more complex, as each node operates independently. - Ensuring consistent security protocols across all nodes is challenging due to the lack of centralized control. ### Question 2: Unique IDs in Digital Coins vs. Physical Coins **Digital coins**, such as those used in cryptocurrencies, typically have a unique transaction ID associated with their transfer, not with the coin itself. This ID helps in tracking and verifying transactions on the blockchain. Each coin's movement creates a new transaction record with a unique ID, ensuring traceability and security. **Physical coins**, like pound coins, do not have unique identifiers; they are fungible and indistinguishable from one another within the same denomination. **Similarity to banknotes**: Physical banknotes often have unique serial numbers, making each note traceable and identifiable. This is similar to digital coins' transactions, where each transaction is uniquely identified, though the purpose and method of identification differ. ### Question 3: Cryptocurrency Ledger A **cryptocurrency ledger** is a digital record of all the transactions that have taken place across a cryptocurrency network. It is maintained across multiple computers in a distributed manner. This ledger ensures that all transactions are recorded and accessible to all users, providing transparency and security. The decentralized nature of the ledger makes it resistant to tampering and fraud. ### Question 4: Blockchain and Merkle Tree **Blockchain**: A blockchain is a type of distributed ledger technology (DLT) consisting of a chain of blocks, each containing multiple transactions. Every new block is linked to the previous block via cryptographic hashes, making the blockchain secure and altering any part of it computationally impractical. **Merkle Tree**: A Merkle tree is a data structure used in computer science to efficiently summarize and verify the integrity of large sets of data. In blockchain, Merkle trees aggregate all transactions in a block into a single hash. This technique allows quick and secure verification of whether a particular transaction is included in a block. **Usefulness**: Both are crucial for ensuring data integrity and security in distributed systems like cryptocurrencies. The blockchain provides a tamper-evident, append-only record of transactions, while Merkle trees allow for efficient and secure verification of the contents of large data sets. These foundational technologies facilitate the operation of decentralized digital currencies and numerous other applications in distributed computing and data integrity verification. ![image](https://hackmd.io/_uploads/Hk7GwaUf0.png =750x) ### Attack ![image](https://hackmd.io/_uploads/SyAlTzdM0.png =750x) ### Question 1: Examples of SQL Injection and Coding Standards **Example 1: Tautology Based SQL Injection** - **Attack**: The attacker inputs `admin' OR '1'='1` into a username field in a login form. - **SQL Query**: `SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'input_password'`. - **Result**: The condition `'1'='1'` is always true, thus bypassing the password check and granting unauthorized access. - **Defense**: Use parameterized queries that prevent the SQL code from being altered by user input. **Example 2: Comment-Based SQL Injection** - **Attack**: The attacker inputs `admin' --` into a username field. - **SQL Query**: `SELECT * FROM users WHERE username = 'admin' --' AND password = 'input_password'`. - **Result**: The `--` comments out the rest of the SQL statement, effectively ignoring the password check. - **Defense**: Employ input validation that sanitizes inputs by escaping special characters and removing SQL comment sequences. **Necessary Coding Standards**: - **Parameterized Queries**: Use prepared statements which separate SQL logic from the data, inherently neutralizing injected SQL code. - **Input Sanitization**: Apply strict input validation rules to detect and remove harmful SQL patterns or use whitelist validation to only allow known good inputs. ### Question 2: UNION SELECT and Sub Queries **Using UNION SELECT**: - **Scenario**: An attacker wants to extract user information from a database. - **Attack**: The attacker inputs into a search field: `1 UNION SELECT username, password FROM users`. - **SQL Query**: `SELECT product_name FROM products WHERE id = 1 UNION SELECT username, password FROM users`. - **Result**: This will return both product names and user credentials, exploiting the UNION operation to combine results from two different queries. **Using Sub Queries**: - **Scenario**: An attacker aims to extract sensitive data through a sub-query. - **Attack**: The attacker manipulates an input field to include a sub-query: `'1; SELECT password FROM users WHERE username = 'admin'`. - **SQL Query**: `SELECT email FROM users WHERE id = '1; SELECT password FROM users WHERE username = 'admin'`. - **Result**: The sub-query could potentially execute if dynamic SQL execution is enabled, leading to unauthorized disclosure of passwords. ### Question 3: Discovering Database Schema Details **Methods to Find Database Tables and Columns**: - **Error-Based SQL Injection**: - **Description**: Trigger SQL errors that disclose schema information. - **Example**: Inputting `' ORDER BY 10--` might result in an error message indicating how many columns are in the table if there are fewer than ten columns. - **Information Schema Queries**: - **Attack**: Use SQL injection to access the `INFORMATION_SCHEMA` tables that store metadata about all other tables and columns in the database. - **SQL Query**: `1 UNION SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = 'database_name'`. - **Result**: This could list all table names and column names in the database, providing a roadmap for further attacks. These approaches emphasize the necessity for robust security measures in web application development, including both front-end and back-end validations, the use of secure coding practices, and regular security audits to mitigate potential vulnerabilities. ![image](https://hackmd.io/_uploads/rkZ1bNufA.png =750x) Let's dive into the questions regarding the execution of JavaScript on a target machine and how sessions can be hijacked using Cross-Site Scripting (XSS). ### Question 4: How can JavaScript be run on a target machine? JavaScript can be executed on a target machine primarily through web browsers when a user visits a website containing JavaScript code. Here are a few common scenarios: 1. **Web Pages**: Most websites use JavaScript to enhance user interactivity. When a user accesses such websites, their browser automatically processes and executes the JavaScript code embedded in the webpage. 2. **Emails and Messages**: If an email client or messaging application supports HTML content and is not properly configured to restrict JavaScript execution, malicious JavaScript embedded in emails or messages can run when viewed. 3. **Malvertising**: Attackers can inject malicious JavaScript into ads displayed on legitimate websites. When users visit these sites, the JavaScript runs without the user's explicit consent. 4. **Cross-Site Scripting (XSS)**: Attackers can exploit XSS vulnerabilities in web applications to inject malicious scripts into web pages viewed by other users. The script runs when the user accesses the compromised page. 5. **Drive-by Downloads**: By visiting a malicious website, users can inadvertently trigger JavaScript that exploits browser vulnerabilities to install malware on their computers. The execution of JavaScript can be controlled by browser settings, extensions like NoScript, or security configurations in email clients and web applications to prevent unauthorized JavaScript execution. ### Question 5: How can a session be hijacked using Cross Site Scripting? Session hijacking via XSS occurs when an attacker exploits a vulnerability in a web application to inject a script that can steal session cookies or session tokens. Here’s how it generally works: 1. **Identify XSS Vulnerability**: The attacker finds a vulnerability within a website where input from users is included in the output without adequate sanitization. 2. **Craft Malicious Script**: The attacker creates a script intended to access cookies or session tokens. This script is crafted to be triggered when another user accesses the compromised page. 3. **Inject Script**: The script is injected through mechanisms like posting it in a user comment, a forum post, or any other user input that is reflected on the webpage. 4. **Execution of Script**: When another user visits the infected page, their browser executes the script unknowingly. The script accesses the user’s session cookies, which typically contain authentication tokens. 5. **Send Cookies to Attacker**: The script sends these cookies to a server controlled by the attacker, often via an HTTP request embedded within the script. 6. **Session Hijacking**: With the stolen cookies, the attacker can impersonate the user, gaining unauthorized access to the user’s account on the application. To mitigate XSS and prevent session hijacking, web developers need to ensure proper input sanitization, employ Content Security Policy (CSP) headers, use HttpOnly and Secure flags on cookies to prevent access via client-side scripts, and implement other security best practices in web application development. --- ## Past paper ### 1 ![image](https://hackmd.io/_uploads/rJAvHWtG0.png =750x) EARTH A E H R T A 03 22 15 09 20 ... E 21 04 24 17 16... use the number in the column as the key ![image](https://hackmd.io/_uploads/rJ0KB-KfR.png =750x) ### 2 ![image](https://hackmd.io/_uploads/rywnrWtf0.png =750x) ![image](https://hackmd.io/_uploads/SkBVLbYMC.png =750x) As a professional cryptographer and cryptoanalyst, I can explain the concepts of confusion and diffusion and provide a more detailed answer to the question. Confusion and diffusion are two fundamental principles of secure cipher design, as introduced by Claude Shannon in his 1949 paper "Communication Theory of Secrecy Systems." Confusion refers to the complexity of the relationship between the key and the ciphertext. A cipher with good confusion ensures that each bit of the ciphertext depends on several parts of the key, making it difficult for an attacker to determine the key from the ciphertext. In practice, confusion is often achieved through substitution operations, such as S-boxes in block ciphers like DES. Diffusion, on the other hand, refers to the spreading of the influence of each plaintext or key bit over many ciphertext bits. A cipher with good diffusion ensures that changing a single bit of the plaintext or key results in significant changes to the ciphertext. Diffusion is typically achieved through permutation operations, such as P-boxes in DES, which shuffle the bits around. Calculating confusion and diffusion values can be done through various methods, such as: 1) Avalanche effect: Measuring the average number of ciphertext bits that change when a single plaintext or key bit is flipped. 2) Bit independence criterion: Analyzing the statistical independence between plaintext, key, and ciphertext bits. 3) Linear and differential cryptanalysis: Assessing the cipher's resistance to these specific attacks, which exploit weaknesses in confusion and diffusion. Now, let's revisit the question of why we don't stop the DES algorithm at Round 4 or Round 10, even though the confusion and diffusion values are quite high at those points. While the provided table shows that confusion and diffusion values are high at Rounds 4 and 10, it is important to note that these values alone do not guarantee the overall security of the cipher. The full 16 rounds of DES were chosen based on a comprehensive security analysis considering various factors: 1) Resistance to known attacks: The 16-round DES is designed to resist specific cryptanalytic attacks, such as differential and linear cryptanalysis. Stopping at an earlier round might make the cipher more vulnerable to these attacks, even with high confusion and diffusion values. 2) Key size and exhaustive search: The 56-bit key size of DES was chosen to balance security and performance. With fewer rounds, the effective key size might be reduced, making the cipher more susceptible to exhaustive key search attacks. 3) Iterative structure: The iterative nature of DES, with 16 rounds, helps to ensure that any patterns or weaknesses in the cipher are not easily exploitable. Stopping at an earlier round might not provide sufficient iterations to eliminate such vulnerabilities. 4) Cryptanalytic effort: The 16-round DES has undergone extensive cryptanalysis by the cryptographic community over decades. While some theoretical weaknesses have been identified, no practical attacks have been found that significantly undermine its security when used with the full 16 rounds. Changing the number of rounds would require reevaluating the cipher's security against known and potential attacks. 5) Standardization and interoperability: DES is a standardized cipher, and its 16-round structure is part of the specification. Modifying the number of rounds would result in a non-standard implementation, which could lead to compatibility issues when communicating with other systems using the standard DES algorithm. In conclusion, while the high confusion and diffusion values at Rounds 4 and 10 are notable, they do not provide a complete picture of the cipher's security. The decision to use 16 rounds in DES is based on a thorough security analysis that considers resistance to known attacks, key size, iterative structure, cryptanalytic effort, and standardization. Deviating from the specified number of rounds could potentially weaken the cipher's overall security and lead to interoperability issues. As a cryptographer and cryptoanalyst, I recommend adhering to the full 16 rounds of DES as specified in the standard to maintain its proven security properties. > The confusion and diffusion values at Rounds 4 and 10 in DES are high, but the full 16 rounds are necessary to ensure overall security. The 16-round structure is based on comprehensive analysis considering resistance to attacks, key size, iterative structure, and standardization. Deviating from the specified rounds could weaken DES and cause compatibility issues. Adhering to the standard 16 rounds maintains the cipher's proven security. ### 3 ![image](https://hackmd.io/_uploads/Bk1HIbYfC.png =750x) a) We pre-calculate the possible values of y and y2 mod 5 in the following table. (y can be between 0 and 4 as we use the field F5.) | | | | | | | | --------- | --- | --- | --- | ----------- | ------------ | | y | 0 | 1 | 2 | 3 | 4 | | y^2 mod 5 | 0 | 1 | 4 | 9 mod 5 = 4 | 16 mod 5 = 1 | y^2 = x^3 + 7 x = * 0: y^2 = 7 mod 5 = 2 => no solution * 1: y^2 = 8 mod 5 = 3 => no solution * 2: y^2 = 15 mod 5 = 0 => y = 0 * 3: y^2 = 34 mod 5 = 4 => y= 2 or y=3 (mod 5) * 4: y^2 = 71 mod 5 = 1 => y= 1 or y=4 (mod 5) Thus, points on the elliptic curve are `(2, 0), (3, 2), (3, 3), (4, 1), (4, 4)` and the point at infinity: infty. b) by formula of EC: * x_3 = ((y_2 – y_1)/(x_2 – x_1))^2 – x_1 – x_2 * y_3 = ((y_2 – y_1)/(x_2 – x_1))(x_1 – x_3) – y_1 Substituting with the points P and Q we get x3 = ((2 – 0)/(3 – 2))2 – 2 – 3 mod 5 = 22 – 2 – 3 mod 5 = 4 – 2 – 3 mod 5 = -1 mod 5 = 4 mod 5 and y3 = ((2 – 0)/(3 – 2)) (2 – 4) – 0 mod 5 = 2 (2 – 4) – 0 mod 5 = 2 (-2) mod 5 = -4 mod 5 = 1 mod 5 Therefore, the point R = (4, 1). c)Similarly, we can use the point doubling equations from the assigned reading to solve 2P as follows: x2p = ((3 xp 2 + a)/(2 yp))2 – 2xp y2p = ((3 xp 2 + a)/(2 yp)) (xp – x2p) – yp Assuming we are using the EC from question part a) where the term Ax is not present and so a=0, then x2p = ((3 * 42 + 0)/(2 * 1)) 2 – 2 * 4 mod 5 = (48 / 2)2 - 8 mod 5 = 42 – 8 mod 5 = 16 - 8 mod 5 = 8 mod 5 = 3 mod 5 and y2p = (48/2) (4 – 3) – 1 mod 5 = 4 * (4 – 3) – 1 mod 5 = 4 – 1 mod 5 = 3 mod 5 Therefore, the point R = 2 P(4,1) is (3,3). ### 4 ![image](https://hackmd.io/_uploads/HyaIL-FMR.png =750x) As a Java expert in cryptography, I'll provide an outline of the program structure and discuss the key Java security classes to use. Program Outline: 1. Read passphrase from user 2. Generate message digest from passphrase using SHA-256 3. Prompt user to choose Encryption or Decryption mode 4. Read plaintext file (Encryption) or ciphertext file (Decryption) 5. Perform AES encryption or decryption using the message digest as the key 6. Write the output to a new file 7. Erase the original file securely Important Java Security Classes: For cryptographic hashing (message digest): - java.security.MessageDigest: Provides functionality to generate hash values from input data. Use the "SHA-256" algorithm. For symmetric encryption (AES): - javax.crypto.Cipher: Provides encryption and decryption functionality. Use "AES" as the algorithm. - javax.crypto.spec.SecretKeySpec: Constructs a secret key from a byte array, which can be the message digest. For secure file erasure: - java.nio.file.Files: Provides methods for file I/O. Use the newOutputStream() method with the WRITE and TRUNCATE_EXISTING options to overwrite the file with random data before deletion. - java.security.SecureRandom: Generates cryptographically secure random bytes for overwriting files. Other important classes: - java.io.File and java.io.FileInputStream/FileOutputStream for file I/O. - java.util.Scanner for user input. - java.util.Arrays to clear sensitive data from memory after use. Key methods to consider: - MessageDigest.getInstance("SHA-256") and digest() to hash the passphrase - Cipher.getInstance("AES") and init()/doFinal() for encryption/decryption - SecretKeySpec to create an AES key from the hashed passphrase - Files.newOutputStream() with WRITE and TRUNCATE_EXISTING to securely erase files - SecureRandom.nextBytes() to generate random data for overwriting files Remember to handle exceptions, clear sensitive data from memory after use, and ensure that the user is aware of the destructive nature of file erasure. Let me know if you have any other questions! --- Here is a similar style question involving a polyalphabetic cipher and rotor machine: 1. (a) Consider a polyalphabetic cipher with a key length of 6 for a plaintext alphabet of 26 letters A-Z. The key is "CIPHER". Given that the encryption follows a standard tabula recta (Vigenère square), decrypt the following ciphertext: ``` KZURY YONSE CYOSE ``` (a.1) What is the plaintext message? [5] (a.2) If the ciphertext was instead encrypted using an autokey variant where the key is used for the first 6 letters and the plaintext itself is used as the key for subsequent letters, what would be the resulting ciphertext? [5] (b) A rotor machine consists of 3 rotors and a reflector. The rotor wirings are as follows: ``` Rotor 1: BDFHJLNPRTVXZACEGIKMOQSUWY Rotor 2: DEFEICBMRQPGHKMLONTSXUZWVY Rotor 3: DZPMSHXBLNCOQEJVRTGWIYUKAF Reflector: EKMFLGDQVZNTOWYHXUSPAIBRCJ ``` If the rotors start at positions (1, 1, 1) and stepping is odometer style (rotor 1 steps every letter, rotor 2 steps when rotor 1 completes a rotation, rotor 3 steps when rotor 2 completes a rotation), encrypt the plaintext "ENIGMA". Show the state (rotor positions and ciphertext generated) after encrypting each letter. [10] Explanation: For part (a), a polyalphabetic cipher with key "CIPHER" would use 6 shifted alphabets cyclically based on the key letter positions (C=2, I=8, P=15, H=7, E=4, R=17). Decrypting the given ciphertext using these shifts (subtract key values mod 26) would reveal the plaintext. For the autokey variant, the first 6 letters are encrypted the same way, but subsequent letters use the plaintext itself as the shifting key rather than repeating "CIPHER". In part (b), the rotor machine encryption follows the signal path from the keyboard, through the rotors in forward order, bouncing off the reflector, then back through the rotors in reverse order to light up a ciphertext letter. The odometer stepping causes the rotors to rotate and change the wiring paths with each key press. Tracing the letter-by-letter encryption and keeping track of the rotor state changes is required. Let me know if you would like me to provide the complete solution! I tried to design a question hitting on the key concepts you mentioned at a reasonable difficulty level. Feel free to modify as needed. Here's a question designed around the running key cipher: 2. A running key cipher is a variant of the Vigenère cipher that uses a long piece of text as the key, such as a passage from a book, instead of a short repeated keyword. (a) Suppose the following passage from "The Adventures of Sherlock Holmes" by Arthur Conan Doyle is used as the running key (spaces and punctuation removed, all uppercase): ``` INASMUCHASTHEPRODUCTIONOFMRSHERLOCKHOLMESYOUHAVEBEENAGOODFRIENDT OMEIHAVEBEENAGOODFRIENDTOMRHERLOCKHOLMESHEHASFRE QUENTLYTRUST EDME ``` Encrypt the plaintext message "MEET ME AT THE PARK" using this running key. [5] (b) One weakness of the running key cipher is that if the same key text is reused, it may be possible to deduce the key through frequency analysis and cribs (guessed plaintext fragments). Suppose an adversary intercepts two ciphertexts known to be encrypted with the same running key, and suspects the plaintext fragments "SHERLOCK" and "HOLMES" appear in the messages. ``` Ciphertext 1: ZOYHKGMKPVDVMULFZRWGZXLAL Ciphertext 2: HGODZUHOVYYZOUGFNSYYLHVKZ ``` By attempting to align the cribs with the ciphertexts and looking for repeated patterns, try to recover as much of the original plaintexts and key as possible. [15] Explanation: In part (a), the running key cipher encryption proceeds by converting both the plaintext and key passage to numbers (A=0, B=1, ..., Z=25), adding them together mod 26, and converting the result back to letters. This is similar to a Vigenère cipher but with a much longer non-repeating key. For part (b), the cribs "SHERLOCK" and "HOLMES" can be tentatively aligned with the ciphertexts at various positions, and the resulting key fragment can be checked against the other ciphertext to see if a plausible plaintext emerges. Through trial and error and leveraging the fact that the same key was reused, portions of the key and original plaintexts may be recovered. This question tests understanding of the running key cipher mechanics as well as a common cryptanalytic attack on it when key material is reused. The open-ended nature of part (b) allows for some flexibility in the amount of key and plaintext recovered. ## Codes for java security: ### Crypto ```java package filesEncryptionApp; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; import java.util.zip.*; /*================*/ public class Crypto /*================*/ { /****************/ /* Encryption */ /****************/ /*---------------------------------------------------*/ public static byte[] encrypt(String key, byte[] in) /*---------------------------------------------------*/ { return do_crypt(Cipher.ENCRYPT_MODE, key, in); } /*---------------------------------------------------*/ public static byte[] decrypt(String key, byte[] in) /*---------------------------------------------------*/ { return do_crypt(Cipher.DECRYPT_MODE, key, in); } /*--------------------------------------------------------------*/ private static byte[] do_crypt(int mode, String key, byte[] in) /*--------------------------------------------------------------*/ { // pad key to 16 characters int klen = key.length(); for (int i = klen; i < 16; i++) key += 'z'; // initialise cipher Key k = new SecretKeySpec(key.getBytes(), "AES"); Cipher c = null; try { c = Cipher.getInstance("AES"); } catch (NoSuchPaddingException e) { System.err.println("No Such Padding Exception"); System.exit(0); } catch (NoSuchAlgorithmException e) { System.err.println("No Such Algorithm Exception"); System.exit(0); } try { c.init(mode, k); } catch (InvalidKeyException e) { System.err.println("Invalid Key Exception"); System.exit(0); } // encrypt or decrypt try { return c.doFinal(in); } catch (BadPaddingException e) { System.err.println("Bad Padding Exception"); System.exit(0); } catch (IllegalBlockSizeException e) { System.err.println("Bad Padding Exception"); System.exit(0); } return null; } /*****************/ /* Compression */ /*****************/ /*---------------------------------------*/ public static byte[] compress(byte[] b) /*---------------------------------------*/ { Deflater d = new Deflater(); d.setInput(b); d.finish(); byte[] tmp = new byte[b.length]; // big enough, assume gets smaller int n = d.deflate(tmp); byte[] out = new byte[n+4]; // put length in first 4 bytes // add length to first 4 bytes int len = b.length; for (int i = 0; i < 4; i++) { out[i] = (byte) (len & 0x7f); len >>= 7; } // copy data bytes for (int i = 0; i < n; i++) out[i+4] = tmp[i]; return out; } /*-----------------------------------------*/ public static byte[] uncompress(byte[] b) /*-----------------------------------------*/ { // extract the length from the first 4 bytes int a0 = b[0]; int a1 = b[1]; int a2 = b[2]; int a3 = b[3]; int len = a0 | (a1 << 7) | (a2 << 14) | (a3 << 21); Inflater u = new Inflater(); u.setInput(b, 4, b.length-4); byte[] out = new byte[len]; try { u.inflate(out); } catch(DataFormatException x) { System.err.println("Inflate Error"); System.exit(0); } u.end(); return out; } } ``` ### FileEntry ```java package filesEncryptionApp; import java.awt.*; import java.io.*; import java.util.*; import javax.swing.*; /*===============*/ public class FileEntry { public File f; // null indicates entry is closed public byte[] content; public JPanel pan; public JButton bopen, bclose, bup, bdown, bsize, bdel; public JTextField tf_filename, tf_comment; public JLabel lab_size; /*--------------------*/ public FileEntry(File fin) /*--------------------*/ { f = fin; content = null; startup(fin.getName(), (int) fin.length(), "Add Comment"); } /*--------------------------------------------*/ public FileEntry(byte[] fn, byte[] co, byte[] con) /*--------------------------------------------*/ { f = null; content = con; startup(new String(fn), content.length, new String(co)); } /*-------------------------------------------------------------------*/ public void startup(String filename, int filesize, String comment) /*-------------------------------------------------------------------*/ { pan = new JPanel(); bopen = new JButton("Open"); bclose = new JButton("Close"); bup = new JButton("^"); bdown = new JButton("v"); bdel = new JButton("Delete"); tf_filename = new JTextField(filename, 30); tf_comment = new JTextField(comment, 90); lab_size = new JLabel(String.format("%8d", filesize / 1024)); lab_size.setPreferredSize(new Dimension(50, 20)); pan.add(bopen); pan.add(bclose); pan.add(bup); pan.add(bdown); pan.add(lab_size); pan.add(tf_filename); pan.add(bdel); pan.add(tf_comment); } /*----------------------*/ public void do_open() /*----------------------*/ { // assume have valid content // check if file exists f = new File(tf_filename.getText()); if (f.exists()) { if (JOptionPane.showConfirmDialog(null, "File " + f.getName() + " exists. Overwrite?", "Open File", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) return; } // create real file FileIO.write(f, content); } /*-----------------------*/ public void do_close() /*-----------------------*/ { // read contents into program and then erase file content = FileIO.read(f); lab_size.setText(String.format("%8d", content.length / 1024)); erase_file(); } /*-------------------------*/ public void erase_file() /*-------------------------*/ { // erase content of real file Random rand = new Random(); byte[] b = new byte[(int)f.length()]; rand.nextBytes(b); FileIO.write(f, b); // delete real file f.delete(); f = null; } /*-------------------------------------------------------*/ public void set_state(File ff, byte[] cont, String fn, String sz, String com) /*-------------------------------------------------------*/ { f = ff; content = cont; tf_filename.setText(fn); lab_size.setText(sz); tf_comment.setText(com); if (f == null) { bopen.setEnabled(true); bclose.setEnabled(false); } else { bopen.setEnabled(false); bclose.setEnabled(true); } } } ``` ### FileIO ```java package filesEncryptionApp; import java.io.*; /*================*/ public class FileIO /*================*/ { /*---------------------------------*/ static public byte[] read(File f) /*---------------------------------*/ { FileInputStream fin = null; try { fin = new FileInputStream(f); } catch (FileNotFoundException x) { System.err.println("File ["+f.getName()+ "] Not Found Exception"); System.exit(0); } byte[] b = new byte[(int)f.length()]; try { fin.read(b); fin.close(); } catch (IOException x) { System.err.println("File ["+f.getName()+ "] IOException"); System.exit(0); } return b; } /*--------------------------------------------*/ static public boolean write(File f, byte[] b) /*--------------------------------------------*/ { FileOutputStream fout = null; try { fout = new FileOutputStream(f); } catch (FileNotFoundException x) { System.err.println("File ["+f.getName()+ "] Not Found Exception"); return false; } try { fout.write(b); fout.close(); } catch (IOException x) { System.err.println("File ["+f.getName()+ "] IOException"); return false; } return true; } } ``` ### Index ```java package filesEncryptionApp; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; /*=======================================================*/ public class Index extends JFrame implements ActionListener /*=======================================================*/ { /** * */ private static final long serialVersionUID = 1L; /*--------------------------------------------------------------*/ public Index(MainApp k, MinWin mw, String in, String ip, File findex) /*--------------------------------------------------------------*/ { mainApp = k; minwin = mw; iname = in; ipwd = ip; setSize(1800, 1000); setLocation(100, 20); setLayout(new GridLayout(31, 1)); // action widgets pbuttons = new JPanel(); badd = new JButton("Add File"); bclose = new JButton("Close Index"); bquit = new JButton("Quit"); bminwin = new JButton("Minimise"); tf_filename = new JTextField("Input File Name", 30); tf_index_desc = new JTextField("Add Index Comments", 70); bminwin.addActionListener(this); badd .addActionListener(this); bclose .addActionListener(this); bquit .addActionListener(this); pbuttons.add(new JLabel("File Name")); pbuttons.add(tf_filename); pbuttons.add(badd); pbuttons.add(bclose); pbuttons.add(bquit); pbuttons.add(bminwin); pbuttons.add(tf_index_desc); add(pbuttons); // entry rows nentry = 0; maxentry = 30; fileEntry = new FileEntry[maxentry]; for (int i = 0; i < maxentry; i++) fileEntry[i] = null; // will later reuse entries // read in data if opening an index if (findex != null) read_index(findex); setVisible(true); mainApp.setVisible(false); } /*--------------------------------------------*/ public void actionPerformed(ActionEvent ae) /*--------------------------------------------*/ { Object b = ae.getSource(); if (b == bminwin) minwin.activate(this); else if (b == badd) add_file(); else if (b == bclose) { mainApp.setVisible(true); setVisible(false); write_index(); } else if (b == bquit) { write_index(); System.exit(0); } else for (int i = 0; i < nentry; i++) // an entry { FileEntry e = fileEntry[i]; if (b == e.bopen) { e.do_open(); e.bopen.setEnabled(false); e.bclose.setEnabled(true); e.tf_filename.setEnabled(false); setVisible(true); break; } else if (b == e.bclose) { e.do_close(); e.bopen.setEnabled(true); e.bclose.setEnabled(false); e.tf_filename.setEnabled(true); if (isVisible()) setVisible(true); break; } else if (b == e.bup) do_up(i); else if (b == e.bdown) do_down(i); else if (b == e.bdel) do_del(i); } } /*-----------------------*/ private void add_file() /*-----------------------*/ { // check if filename already there String filename = tf_filename.getText(); File f = new File(filename); for (int i = 0; i < nentry; i++) if (filename.equals(fileEntry[i].tf_filename.getText())) { JOptionPane.showMessageDialog(null, "File " + filename + " already in index", "Error", JOptionPane.ERROR_MESSAGE); return; } // check enough space if (nentry >= maxentry) { JOptionPane.showMessageDialog(null, "Maximum Number of Entries Reached", "Error", JOptionPane.ERROR_MESSAGE); return; } // check can access file if (!(f.exists() && f.canRead() && f.canWrite())) { JOptionPane.showMessageDialog(null, "Cant Open " + f.getName(), "Error", JOptionPane.ERROR_MESSAGE); return; } // add new entry if (fileEntry[nentry] == null) { FileEntry e = new FileEntry(f); fileEntry[nentry++] = e; e.bopen .addActionListener(this); e.bclose.addActionListener(this); e.bup .addActionListener(this); e.bdown .addActionListener(this); e.bdel .addActionListener(this); add(e.pan); e.bopen.setEnabled(false); e.tf_filename.setEnabled(false); } else // reuse existing entry { FileEntry e = fileEntry[nentry++]; e.f = f; e.content = null; e.bopen.setVisible(true); e.bopen.setEnabled(false); e.bclose.setVisible(true); e.bclose.setEnabled(true); e.bup.setVisible(true); e.bdown.setVisible(true); e.bdel.setVisible(true); e.tf_filename.setText(f.getName()); e.tf_filename.setVisible(true); e.tf_filename.setEnabled(false); e.tf_comment.setText("Add Comment"); e.tf_comment.setVisible(true); } setVisible(true); } /*--------------------------*/ public void write_index() /*--------------------------*/ { // find out how many bytes int nbytes = 38; // 37 byte initial block + 1 nentries nbytes += 4 + tf_index_desc.getText().length(); for (int i = 0; i < nentry; i++) { FileEntry e = fileEntry[i]; if (e.f != null) e.do_close(); nbytes += 12 + e.content.length + e.tf_filename.getText().length() + e.tf_comment.getText().length(); } index_bytes = new byte[nbytes]; ib = 0; // initial block Random rand = new Random(); for (; ib < 37; ib++) // initial block index_bytes[ib] = (byte) ('a' + Math.abs(rand.nextInt()) % 26); add_bytes(tf_index_desc.getText().getBytes()); // entries index_bytes[ib++] = (byte) nentry; for (int i = 0; i < nentry; i++) { FileEntry e = fileEntry[i]; add_bytes(e.tf_filename.getText().getBytes()); add_bytes(e.tf_comment.getText().getBytes()); add_bytes(e.content); } // write to the index file byte[] icomp = Crypto.compress(index_bytes); byte[] icrypt = Crypto.encrypt(ipwd, icomp); File f = new File(iname); File f2 = new File(iname+"_bak"); f.renameTo(f2); if (FileIO.write(f, icrypt)) f2.delete(); } /*-------------------------------*/ private void read_index(File f) /*-------------------------------*/ { byte[] icrypt = FileIO.read(f); byte[] icomp = Crypto.decrypt(ipwd, icrypt); index_bytes = Crypto.uncompress(icomp); ib = 0; // check initial block for (; ib < 37; ib++) { int c = index_bytes[ib]; if (c < 'a' || c > 'z') { System.err.println("Invalid Initial Block"); System.exit(0); } } // index description byte[] b = get_bytes(); tf_index_desc.setText(new String(b)); // entries nentry = (int) index_bytes[ib++]; for (int i = 0; i < nentry; i++) { byte[] b1 = get_bytes(); byte[] b2 = get_bytes(); byte[] b3 = get_bytes(); FileEntry e = new FileEntry(b1, b2, b3); fileEntry[i] = e; e.bopen .addActionListener(this); e.bclose.addActionListener(this); e.bup .addActionListener(this); e.bdown .addActionListener(this); e.bdel .addActionListener(this); add(e.pan); e.bclose.setEnabled(false); } setVisible(true); } /*--------------------------------*/ private void add_bytes(byte[] b) /*--------------------------------*/ { int len = b.length; int n = len; for (int i = 0; i < 4; i++) { index_bytes[ib++] = (byte) (len & 0x7f); len >>= 7; } for (int i = 0; i < n; i++) index_bytes[ib++] = b[i]; } /*------------------------*/ private byte[] get_bytes() /*------------------------*/ { int a0 = index_bytes[ib]; int a1 = index_bytes[ib+1]; int a2 = index_bytes[ib+2]; int a3 = index_bytes[ib+3]; ib += 4; int len = a0 | (a1 << 7) | (a2 << 14) | (a3 << 21); byte[] b = new byte[len]; for (int i = 0; i < len; i++) b[i] = index_bytes[ib++]; return b; } /*************/ /* Entries */ /*************/ /*-------------------------*/ private void do_up(int i) /*-------------------------*/ { if (i == 0) // already at top return; swap(i-1, i); } /*---------------------------*/ private void do_down(int i) /*---------------------------*/ { if (i == nentry-1) // already at bottom return; swap(i, i+1); } /*-------------------------------*/ private void swap(int i, int j) /*-------------------------------*/ { FileEntry ei = fileEntry[i]; FileEntry ej = fileEntry[j]; // save state for i File tmp_f = ei.f; byte[] tmp_content = ei.content; String tmp_filename = ei.tf_filename.getText(); String tmp_size = ei.lab_size.getText(); String tmp_comment = ei.tf_comment.getText(); // copy j to i, then tmp to j ei.set_state(ej.f, ej.content, ej.tf_filename.getText(), ej.lab_size.getText(), ej.tf_comment.getText()); ej.set_state(tmp_f, tmp_content, tmp_filename, tmp_size, tmp_comment); setVisible(true); } /*--------------------------*/ private void do_del(int i) /*--------------------------*/ { // erase file if open if (fileEntry[i].f != null) fileEntry[i].erase_file(); // copy them upwards for (int j = i+1; j < nentry; j++) { FileEntry e = fileEntry[j]; fileEntry[j-1].set_state(e.f, e.content, e.tf_filename.getText(), e.lab_size.getText(), e.tf_comment.getText()); } // hide the last entry nentry--; FileEntry e = fileEntry[nentry]; e.bopen.setVisible(false); e.bclose.setVisible(false); e.bup.setVisible(false); e.bdown.setVisible(false); e.bdel.setVisible(false); e.tf_filename.setVisible(false); e.tf_comment.setVisible(false); setVisible(true); } private MainApp mainApp; private MinWin minwin; private String iname, ipwd; private JPanel pbuttons; private JButton badd, bclose, bquit, bminwin; private JTextField tf_filename, tf_index_desc; private FileEntry[] fileEntry; private int nentry, maxentry; // next free one private byte[] index_bytes; private int ib; // running index } ``` ### MAinApp ```java package filesEncryptionApp; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.File; /*=======================================================*/ public class MainApp extends JFrame implements ActionListener /*=======================================================*/ { /** * */ private static final long serialVersionUID = 1L; /*-----------------------------------*/ public static void main(String[] args) /*-----------------------------------*/ { new MainApp(); } /*----------*/ public MainApp() /*----------*/ { minwin = new MinWin(); setTitle("Files Encryption App"); setSize(600, 130); setLocation(600, 500); // action buttons pbuttons = new JPanel(new GridLayout(1, 3)); bnew = new JButton("New"); bopen = new JButton("Open"); bquit = new JButton("Quit"); bnew .addActionListener(this); bopen.addActionListener(this); bquit.addActionListener(this); pbuttons.add(bnew); pbuttons.add(bopen); pbuttons.add(bquit); add(pbuttons, "South"); // text fields ptfs = new JPanel(new GridLayout(3, 3)); tf_name = new JTextField(20); tf_pwd = new JPasswordField(20); ptfs.add(new JLabel(" Index Name:")); ptfs.add(tf_name); ptfs.add(new JLabel(" Index Password:")); ptfs.add(tf_pwd); add(ptfs, "Center"); setVisible(true); tf_name.requestFocus(); } /*-------------------------------------------*/ public void actionPerformed(ActionEvent e) /*-------------------------------------------*/ { Object b = e.getSource(); if (b == bnew) do_index(true); else if (b == bopen) do_index(false); else if (b == bquit) System.exit(0); } /*-------------------------------------*/ private void do_index(boolean is_new) /*-------------------------------------*/ { String iname = tf_name.getText(); String ipwd = tf_pwd .getText(); if (iname.length() == 0) { JOptionPane.showMessageDialog(null, "Enter Index Name", "Index Error", JOptionPane.ERROR_MESSAGE); return; } if (ipwd.length() == 0) { JOptionPane.showMessageDialog(null, "Enter Index Password", "Index Error", JOptionPane.ERROR_MESSAGE); return; } if (ipwd.length() > 16) { JOptionPane.showMessageDialog(null, "Enter Password less than 16 characters", "Index Error", JOptionPane.ERROR_MESSAGE); return; } File f = new File (iname); if (is_new) { if (!f.exists()) new Index(this, minwin, iname, ipwd, null); else { JOptionPane.showMessageDialog(null, f.getName() + " exists", "Error", JOptionPane.ERROR_MESSAGE); return; } } else { if (f.exists() && f.canRead() && f.canWrite()) new Index(this, minwin, iname, ipwd, f); else { JOptionPane.showMessageDialog(null, "Cant Open Index " + f.getName(), "Error", JOptionPane.ERROR_MESSAGE); return; } } } private MinWin minwin; private JPanel pbuttons, ptfs; private JButton bnew, bopen, bquit; private JTextField tf_name, tf_pwd; } ``` ### MinWin ```java package filesEncryptionApp; import javax.swing.*; //import java.awt.*; import java.awt.event.*; /*=========================================================*/ public class MinWin extends JFrame implements ActionListener /*=========================================================*/ { /** * */ private static final long serialVersionUID = 1L; /*-----*/ MinWin() /*-----*/ { setSize(100, 100); setLocation(10, 10); bmax = new JButton("Max"); bquit = new JButton("Quit"); bmax .addActionListener(this); bquit.addActionListener(this); add(bmax, "West"); add(bquit, "East"); } /*-----------------------*/ void activate(Index in) /*-----------------------*/ { index = in; index.setVisible(false); setVisible(true); } /*-------------------------------------------*/ public void actionPerformed(ActionEvent e) /*-------------------------------------------*/ { Object b = e.getSource(); if (b == bmax) { index.setVisible(true); setVisible(false); } else // must be quit { index.write_index(); System.exit(0); } } private Index index; private JButton bmax, bquit; } ``` ### BufferOverflow ```cpp #include <cstring> #include <iostream> int main( void ) { int authentication = 0; char cUsername[ 10 ]; char cPassword[ 10 ]; std::cout << "Username: "; std::cin >> cUsername; std::cout << "Pass: "; std::cin >> cPassword; if( std::strcmp( cUsername, "admin" ) == 0 && std::strcmp( cPassword, "Nguyen" ) == 0 ) { authentication = 1; } if( authentication ) { std::cout << "Access granted\n"; } else { std::cout << "Wrong username and password\n"; } return ( 0 ); } ``` ### Java demo ```java package JavaSecurityDemo; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; /*==============*/ public class MainJavaCrypto { /*-------------------------------------*/ public static void main(String[] args) /*-------------------------------------*/ { /* * AES key */ SecretKey aes_key = null; try { KeyGenerator kg = KeyGenerator.getInstance("AES"); kg.init(128); // key length 128 aes_key = kg.generateKey(); } catch (NoSuchAlgorithmException e) { System.err.println("NoSuchAlgorithmException"); System.exit(1); } System.err.print("AES key = "); print_bytes(aes_key.getEncoded()); /* * RSA keys */ PublicKey pk = null; PrivateKey sk = null; try { KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA"); kg.initialize(2048); KeyPair kp = kg.generateKeyPair(); pk = kp.getPublic(); sk = kp.getPrivate(); } catch (NoSuchAlgorithmException e) { System.err.println("NoSuchAlgorithmException"); System.exit(1); } System.err.print("RSA public key = "); print_bytes(pk.getEncoded()); System.err.print("RSA secret key = "); print_bytes(sk.getEncoded()); /* * RSA encryption */ byte[] ciphertext = rsa_encdec(Cipher.ENCRYPT_MODE, pk, "This is Java Security Demo!".getBytes()); System.err.print("ciphertext = "); print_bytes(ciphertext); byte[] plaintext = rsa_encdec(Cipher.DECRYPT_MODE, sk, ciphertext); System.err.println("plaintext = " + new String(plaintext)); /* * Message Digests */ String mdin = new String("Message Digest long string example, more stuff, and more!!!"); byte[] digest = null; try { MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(mdin.getBytes()); digest = md.digest(); System.err.print("digest = "); print_bytes(digest); } catch (NoSuchAlgorithmException e) { System.err.println("NoSuchAlgorithmException"); System.exit(1); } /* * Digital signature of message digest */ // sign the digest byte[] signature = rsa_encdec(Cipher.ENCRYPT_MODE, sk, digest); System.err.print("signature = "); print_bytes(signature); // undo the signature byte[] undosig = rsa_encdec(Cipher.DECRYPT_MODE, pk, signature); System.err.print("undosig = "); print_bytes(undosig); // compare the two if (MessageDigest.isEqual(digest, undosig)) System.err.println("equal"); else System.err.println("DIFFERENT!!!"); /* to comment out some code */ } /*-------------------------------------------------------------*/ public static byte[] rsa_encdec(int mode, Key key, byte[] in) /*-------------------------------------------------------------*/ { Cipher c = null; try { c = Cipher.getInstance("RSA"); c.init(mode, key); return c.doFinal(in); } catch (NoSuchAlgorithmException e) { System.err.println("NoSuchAlgorithmException"); System.exit(1); } catch (NoSuchPaddingException e) { System.err.println("NoSuchPaddingException"); System.exit(1); } catch (InvalidKeyException e) { System.err.println("InvalidKeyException"); System.exit(1); } catch (IllegalBlockSizeException e) { System.err.println("IllegalBlockSizeException"); System.exit(1); } catch (BadPaddingException e) { System.err.println("BadPaddingException"); System.exit(1); } return null; } /*------------------------------------------*/ public static void print_bytes(byte[] b) /*------------------------------------------*/ { System.err.print(" [" + b.length + "] "); for (int i = b.length - 1; i >= 0; i--) { int k = (int) b[i] & 0xff; // make unsigned int k1 = k & 0xf; int k2 = (k >> 4) & 0xf; System.err.print(String.format("%x%x", k1, k2)); } System.err.print("\n"); } } ``` ```shell AES key = [16] fb2d08767cdf4fac8d00bcfb5f05fc8d RSA public key = [294] 1000103020fa26fc4a238e78c6a83ca155c7ec8fddfe5a501e8dfe2139677e9951fc197c70c6aa26d9147ccb1cf5d8668f33c39df0cbe090783b4b2d79a0c76d61b8b3bf25001877151d70ad8274d9a1cf636d95bb9e74a20efff0995d6cd7ea15a5208cf7150ab0bf9136297f49d5434c0a1f44f82a080f68b07ad656df73c513061954faa62c9007e4fe8265de954c3c6759376d6910c39c1d392c82ec938d5cc0ae752d0d71dca7674da140dea5ccc97c0aecf4a0498a56e69e9299167764a7dd9cdd8ed39d11707da825d0613d9f4a58f5c3af18dd18497b6843b617d9035b155cfb32df9600134416ed19774244c454e695cc570863743484643a5f220c894ebb2e8b0010102820a010280300f01028300050101010d07f688468a29060d00322102803 RSA secret key = [1217] 83f697f914584ca5bae637c3ba3ad1128cab7597ea2dd5c14d38250513fc56e9d942c0d22df9142d4c2730ae1e3a414dd6ab2de31c641a22b2b3199919b565f397b9efbf20df4c8d37866d8186d43ffa2768a6f94f91e885a296ffa59f8f5a9c08a1bc0ab6e046ab3a45e5bea24c2ba19567c18bd17e655ab8714824adb38487081820de9f2b8eda67209c0f368d7122ccb7e8a24ac1ce1e6e8b96a1dcb44fad1837f3d37b5f60c186240856b3e0857f2309c394510b7dcaea0ff11e5c72ef2100d7326dd882ad7e0f8e733dbdf79fd803fc87627e339dc557a04f6f074cd98df196b0f2c75a31a3e4b1c017c106cd9d69d76a6e20cc66ed88fa5789df0742ec33c4f408182096b3653d953ad78bdabaa69851680123a4858772566f3eea529896b2668924f7c940bc2d020b1f09c7c78897eda25068e95443c13d9529dcce9caca31063f6be8075ae86b823551524079fb918cd4c0ab3b4d70f362eb93c5cf879a34ca5822c6064e4d6f825bcc8905f659205e801fb009b5aca1c21881b4a30d07dcbd28a5d00181820b86b5c960ab532592421138b5616afbcce4aa7dd270935a152bedfdbe12e3ec364855caa628d908dfd28c279818ba59941a96261d9ce664ecc73c217d45e75bbc8ad9a0d21a8e438c1be50aa5c3c1d93491a4541ee2513d08ed64bbac8193351358e200c02ace3ac8aeb86429c1c7ff54d3bdbfa2c552e51b98999bb2abc229d00181820deca06a0e44651ed23cd7aa5ebb632004cafd9502c844e7daf4b35ccc511eb3063f3f43dac6777c0dfe062cca8493c275c7a0d2811a88329a1ae0655261fda7ff299ac35623eb85230ad32ca02fc0e7bea3114f4f6488a4a276d3d543749331b9702044f610e67b78d815d999c26a65543a90c2a09b2d40f7f125a9bf1a3af9d00181820d654d36aa1f7f7a9ec029bc1e63099620e7babc956fcb2fd3cdbbb4cc46e8f07b1574f3c1ce1ad679204b4b92956c449b30873cc1183c71b6ba5502a404a63765a24da6b4bf31285ef0c663cddd6bd290a8d5ae3a8ac75f6a6365b24007c99e26baa065c914bde0764deaec4f09688252cc7401ae5f0fcd56c513bb7a9bf42a1ee12bb75aeeb83a39c7db77573612219a022cd1934fd3b2d8197f67d7d8ca8901bf293b76fdf4f3721daf664e0cd5b0936371ba28ff8785b03511f2ebcb1c81155989ecc98b7653a3edfdb3b1afa681540f1206c1124f8f4936473b79ac6befb09290bfd50f91c23158d502d93bf9ed158e499fcd96eaeee1e8bf569ac4ec860001028201000103020fa26fc4a238e78c6a83ca155c7ec8fddfe5a501e8dfe2139677e9951fc197c70c6aa26d9147ccb1cf5d8668f33c39df0cbe090783b4b2d79a0c76d61b8b3bf25001877151d70ad8274d9a1cf636d95bb9e74a20efff0995d6cd7ea15a5208cf7150ab0bf9136297f49d5434c0a1f44f82a080f68b07ad656df73c513061954faa62c9007e4fe8265de954c3c6759376d6910c39c1d392c82ec938d5cc0ae752d0d71dca7674da140dea5ccc97c0aecf4a0498a56e69e9299167764a7dd9cdd8ed39d11707da825d0613d9f4a58f5c3af18dd18497b6843b617d9035b155cfb32df9600134416ed19774244c454e695cc570863743484643a5f220c894ebb2e8b00101028200010203a4028037a4028400050101010d07f688468a29060d003001020db402803 ciphertext = [256] ff87e41c4e7ee7cddb40d0ff04bd6ab0095e170128ec5e7135444ee609301afede5bbbc01e533c007fa9c6a5417ca2395d4ba09eecbf4b5b7a4fbc9fc6a96d1433e88d00df4a0cad5a94fe4c4e3db0059472a88bd20c3970145eb2f345f99246c5bfb205ddf1025819946078536669074dc182ab7883d2503949f21280c93d9dde5c4882fee91e68f0dcbca38184c028d4c985b51271db5c0b689fb049f8467de225c2ef340bcf2a54c74727cf938584c3facd2900ddd072ced069345e6890e0558f28be83c72005b7eb41e9685cb6f80074968ab409d2a09643370b9d963cba2d80241999f5fda2ec8c3305a547240700f7e057906806163af47deb2df16726 plaintext = This is Java Security Demo! digest = [32] 93651f3e721b06bd099626e49de6ba120fec49f791e907131513044cf8a81107 signature = [256] 380b5b338c9fcc0d0a16acb3a3cc715c019aef31b6b0046d64e55f6ca6369b0e80899c607ca1d6f38eb724a1a0530e51f323c200fcb745ad264de126f1979c7bda2e9ccf6aada22b29d6aee7a1d556b43d848ef3af42c549a9aead2e973f31144000f85c03a6643d909f6783f227805e7b21ed7807646e09ca5b61bfef81c73faf975413e4e59a6cfd0e632707107433d0da5170170a684f1323a551b0ce7d01131f7d03d9cfd7fe729007fdaa94ca59f1c962408cdff16303da3df4a110847efa789fa25f6f67425e47b01599206722dfb7f40f9e06fb09a76982968fe081e3ab1e8a2a7db73f772759deb32310dff0236d2879af85a26006b488b58a619496 undosig = [32] 93651f3e721b06bd099626e49de6ba120fec49f791e907131513044cf8a81107 equal ```