Skip to main content

Problem 59 Project Euler Solution with python

XOR decryption

Each character on a computer is assigned a unique code and the preferred standard is ASCII (American Standard Code for Information Interchange). For example, uppercase A = 65, asterisk (*) = 42, and lowercase k = 107.
A modern encryption method is to take a text file, convert the bytes to ASCII, then XOR each byte with a given value, taken from a secret key. The advantage with the XOR function is that using the same encryption key on the cipher text, restores the plain text; for example, 65 XOR 42 = 107, then 107 XOR 42 = 65.
For unbreakable encryption, the key is the same length as the plain text message, and the key is made up of random bytes. The user would keep the encrypted message and the encryption key in different locations, and without both "halves", it is impossible to decrypt the message.
Unfortunately, this method is impractical for most users, so the modified method is to use a password as a key. If the password is shorter than the message, which is likely, the key is repeated cyclically throughout the message. The balance for this method is using a sufficiently long password key for security, but short enough to be memorable.
Your task has been made easy, as the encryption key consists of three lower case characters. Using cipher.txt (right click and 'Save Link/Target As...'), a file containing the encrypted ASCII codes, and the knowledge that the plain text must contain common English words, decrypt the message and find the sum of the ASCII values in the original text.


This question has a lot of ambiguity! Finally I have solved it and the algorithm is as follows:

Instead of finding if combinations of a-z will match with the given cipher text, we will find each and every character of the key.

We know that the first character will correspond to the first element in the cipher text, then the 4th, then 7th and so on. So we will take a character from a-z and check if any of the character when xor with the given 1st, 4th, 7th..... character will give commonly used english characters. In a similar way we will find it for second character and third character separately.

Writing the algorithm in steps, is as follows:

1) Create a function to check if xor of two ascii numbers is a commonly used english letter. Remember that the ASCII values for commonly used english letters is in the range of 32 - 90 and 97 - 122.
Screenshot of ascii characters in english. Source: Wikipedia
Screenshot of ASCII characters in english. Source: Wikipedia
2) Create a function, which will take a list of three ASCII characters(a part of cipher text) and the encryption key(three characters-password), xor them together and find the original message.

3) Start with opening the file(cipher.txt) given.

4) Split each and every number in the file to make a list.

5) As the list contains numbers in string format, convert each and every entry to an integer.

6) Create a variable to store all the small letters in english in the form of ASCII. The range of ASCII for small letters is 97-122. You can also use a direct xrange in the for loop if you want.

7) Now we will start by finding the first letter. Create a python set to store the values of the letters that can form the first letter in the password. 

8) Create a for loop to loop through small letters in english. Create a nested for loop to loop through 1st(index 0), 4nd(index 3), 7th(index 6)..... elements in the cipher text. Now the condition that should be satisfied is, the given letter when xor with the elements in the cipher text till the end should give a value which is in the commonly used english letters range(Use the function created in Step 1). If the given letter when xor at any point is out of the range, then this will not be the first value. Go on iterating till the end and store all the possible values. We will only get one character that satisfies the condition.

9) Similar to step 8 find the second character by doing xor for 2nd(index 1), 5th(index 4), 8th(index 7)...... elements in the cipher text.

10) Again for elements 3rd(index 2), 6th(index 5), 9th(index 8).... in the cipher text you will find the third character in the password.

11) Now we have three python sets with the first, second, third letters of the password. At this point only one element will be in each of the list. Now change the variables from list to string, just by assigning the first element of the list to the corresponding variables.

12) Concatenate all the strings that we have found in Step 11, and this will give us the password.

13) Create a variable to store plain text that we are going to decrypt using the key we have got. Slice the cipher text with 3 elements each time and send it to the function which we have created in step 2. Add the returned value to the plain text. Do this till you have exhausted with the cipher text. At the end we will have the plain text with the decrypted message.

14) Convert each and every character in the string to ASCII values and find the sum. This will give us the result.

Program

Actually I have written the algorithm seeing the program, so that it will be easy for you to understand. Have a look at the algorithm if you haven't understood the program.

You can download the source code from GitHub Gist 59.py

Output

Summary

To be frank, this problem(question) took 2 days for me to understand. Actually when I read the question for the first time, I thought that the password was of three characters and we will have to find each and every character in the cipher text by xor-ing the three character password with each and every character. I started searching if we can xor one character with three character. LOL! Finally I understood that the question is based on stream cipher and then found the solution. There is still some scope for improvement in this solution. First place we can improve is, where we find the letters. But as I am satisfied with the algorithm I have written and the execution time, I have not tried optimizing the code. Also the optimized code might be difficult for few beginners. Anyways this problem is related to real world again(second problem after poker). I personally liked this problem.

Please excuse me and correct me if my grammar is wrong or in an ambiguous way.

As always you can comment in the comment box below if you have any doubt or haven't understood anything. I will be glad to help you.

Please do comment in the comment box below if you have found a typo or have a better program of have a different program. Please do to comment if you have any suggestion. I will be very happy to view each of them.

You can also contact me.

Thank you. Have a nice day😃!

Popular posts from this blog

Making a quiz web app with python and flask

Edit : When you are creating a web app with h tml templates, then y ou will have to sa ve the html file in templates folder in the Current Wor ki ng Directory( CWD). If you save the file in the C W D directl y you will get a TemplateNotFound error. Thank you Udhay for pointing it out.   In this post we will create a quiz website using python . I will be using the flask framework . After reading this tutorial you will learn form submission , flask templates , python code in flask templates , shuffling the questions and options with the random module and few others.  Please note that this tutorial is not big as it seems to be. Some of the code has been rewritten to maintain consistency and also font size is somewhat big so that your eyes won't get stressed reading this tutorial. Also the content has not occupied the full width of the page. In this tutorial I am assuming that you are having a very basic understanding of the flask framework . Please refer the documentation

Problem 11 Project Euler Solution with python

Largest product in a grid In the 20×20 grid below, four numbers along a diagonal line have been marked in red. 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 04 52 08 83 97 35 99 16 07

Problem 60 Project Euler Solution with python

Prime pair sets The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property. Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime. This problem is j u st a brute force problem. If you have come here because you don't know the limit upto which you will h ave to gener ate the prime numbers t hen go ahe ad and t r y with 10,000 . When I first start ed solving the problem I chose 1 million(beca use most of the problem s on project E uler have this limit ), but it took very long for the computer to fin d the solution. After searching on the internet then I found many people choosing 10, 000 so I have changed my in put f rom 1 million to 10000 and the output was f ast. He