Search

An Unstructured, Random Python Cipher That Seems Unbreakable

Today, we will be cracking codes with python. While researching on this post, I came up on an article about Caesar’s cipher. Caesar’s cipher is a means of encrypting messages using a mapping from the original alphabets to the encrypted alphabets with the original alphabets shifted by some keys either to the left or the right to produce the encrypted alphabets. The author said that Caesar’s cipher, which was one of the earliest forms of cryptography, could be broken by a brute force method. I said to myself: “That’s cool. It could be broken because Caesar’s cipher has a key with a structure. What about if the key has no definite structure?” So, I decided to write a program that is inspired by Caesar’s cipher but with a random key that has no structure. Rather than use the python chr and ord functions, I decided that a better way for my concept to work was to randomize a translation table. But to have a random translation table, I needed to first create it.

 

keys to a cipher in python

How do you create a translation table that has no structure when mapping from source to destination strings and is random? Well, before I begin explaining how, I should explain the functions we are going to use. The functions are python’s randint, maketrans and translate functions.

The python randint function.

The python randint function is a random number generator in python and one of the methods of the python random module. It generates a random integer each time it runs. To use it, you have to import the python random module. The syntax of the randint function is random.randint(a, b) where randint generates integers between a and b inclusive. If you want an indepth coverage of the python randint function and other functions of the python random module, you could do well to read it up on an earlier post. So in my solution today, I will be using the randint function to generate python random numbers.

The next function is the maketrans function.

What is the python maketrans function?

Python has two types of maketrans functions - the static byte.maketrans method and the static str.maketrans method. The earlier belongs to byte objects and the latter to string objects. Both are used to make translation tables for mapping characters.

  • Bytes.maketrans:
  • The syntax is bytes.maketrans(from, to). It will map each python character in the from string of bytes to its equivalent python character in the to string of bytes while making a translation table to be used by the python translate function. From and to must be bytes objects with the same length. To create a translation table that maps ‘a’ to ‘e’, ‘b’ to ‘f’, and ‘c’ to ‘g’, in bytes, we could write the following code:

    
    original = b'abc'
    end = b'efg'
    translation_table = bytes.maketrans(original, end)
    

    When we have a translation table, the work of doing the actual translation is nearly complete.

  • Str.maketrans:
  • The syntax is str.maketrans(x[, y[, z]]) where y and z are optional arguments. When using the python str.maketrans function you are making translation tables that maps python characters or Unicode ordinals to other python characters, Unicode ordinals or None. Note that Unicode ordinals are mappings of characters as integers. For example, ordinal 97 is character ‘a’ while ordinal 98 is character ‘b’.

    When only x is used as the argument in the python str.maketrans method, you must supply a dictionary to str.maketrans method to make a translation table. Note that all translation tables are dictionaries that maps the source to the destination. Here is an example:

    Like before, we are mapping ‘a’ to ‘e’, ‘b’ to ‘f’, and ‘c’ to ‘g’. In the translation table, the Unicode ordinals for the characters are used to identify the characters.

    What if you specify two parameters to maketrans i.e x and y. When you do so, both x and y must be python strings of equal length. You need to specify a string that contains the keys in order for maketrans to properly understand how to create the translation table. Maketrans will create a translation table mapping characters in x, the source, to characters in y at the same index. An example is below:

    If you want some characters to be mapped to None in the translation table, then you have to specify the third argument, z, when calling str.maketrans. Any character in z is mapped to None. Here is an example where d is mapped to None. Any character mapped to None is deleted during the translation of the actual message.

So, I believe you now understand how to create translation tables and you know that the translation tables uses the Unicode ordinals for the characters. Therefore, instead of specifying characters, you could just write out the Unicode ordinals if you know them.

The next step is to do the translation. You use the python translate function to do the actual translation.

How to use the python translate function.

To do the actual translation from the translate table, you use the python translate function. There are two types of python translate functions, the bytes.translate and str.translate, but I suggest you stick to just str.translate because most of the messages you will be translating will be python strings.

The syntax for str.translate is str.translate(map) where str is the message you want to translate and map is the translation table you will be using to do the mapping of the characters in the message. Notice from above that the translation table is a dictionary of Unicode ordinals to Unicode ordinals, strings, or None.

What the translate function does is to take each character in the message, look for its corresponding key in the translation table. If it exists, it replaces that character in the message with its value in the translation table. If the character does not exist in the translation table, the character in the message is left as it is. If in the translation table the character is mapped to None, it is deleted in the message.

Now, that’s a mouthful. Let’s illustrate all the above with examples.

First, let’s translate a message containing the characters in the source above. For example, supposing our message is ‘abccbaaaab’, how would it be translated?

When you run the above you would notice that ‘abccbaaaab’ is translated to be ‘efggfeeeef’ since we are replacing all ‘a’ with ‘e’, all ‘b’ with ‘f’ and all ‘c’ with ‘g’.

Let’s take another example where some characters in the message do not appear in the translation table and also some characters in the translation table are mapped to None.

If you look closely at the code, you will notice that the message has four characters but the translation has just three characters. ‘a’ and ‘b’ were translated as per the translation table to ‘e’ and ‘f’ respectively. In the translation table, ‘d’ is mapped to None so in the translation it is removed. While there is an ‘e’ in the message but there is no key ‘e’ in the translation table so the ‘e’ character is left as is, untranslated.

So, we have what it takes for us to do our unstructured, random python cipher.

This is the source code. You can run the code before understanding the logic stated below just to see how it works. Run it more than once and see that each time you get a different encryption scheme.

This is the logic behind the code. We will first create our source string for the translation table. That will be all the lower case alphabets. We will then cast this source string to a list and use it as a list of values we are going to use for the destination string or replacement string. Since all the alphabets are 26 characters, we enter a loop in line 7 which will create a replacement string 26 times. For each iteration of the loop, we will create a random index between 0 and 25. The index variable serves as an index to the values_list which will be used to create the replacement strings or destination strings. When we have a random index, we will then check if that index has a value in the values_list (line 9). If it has a value, we place that value in the destination_list, adding it as a stack. That means the first value will be the replacement for ‘a’ in the source string. After placing that value in the destination_list, we then substitute its corresponding value in the values_list with None; to tell the code that we have come to that index. Each time that the index gets a value in the values_list that is None (we have already used it), it moves one step in the values_list modulo 26, looking for an unused value in the values_list until it finds one. When it finds one, it stops looking (lines 12 -19). This step of stepping through the values_list looking for a value makes the arrangement of the replacement strings unstructured or without any pattern. That makes it difficult to use a mathematical formula to crack the code. I was thinking about this when I wrote a blog post on the unbreakable code and internet security that describes one-way functions. One-way functions are unbreakable codes; they are functions that go one way and cannot be reversed. Making my replacement strings unstructured mimics this behavior.

When the destination_list is completely populated, we then convert the list to a string (line 20). So, right now, we have our source and destination or replacement strings which makes it possible to create the translation tables for encryption and decryption. (Lines 24 – 28). With the translation tables created, we do the actual encryption and decryption using a specified message and voila, it works. (Lines 31 – 36)

You will notice that each time you run the code, you will get a different encryption scheme because the translation tables are randomized. That makes it difficult to break. What anyone using the code would have to do is to run it once, save the state of the translation tables in a database and use the translation tables for encryption and decryption. The weak point of my code is protecting the translation tables from hackers laying a hold on it, otherwise I think it would be very difficult to hack this scheme.

I challenge anyone to hack it without peeking at the translation tables.

If you want the source code for the unstructured, random python cipher, you can download it here.

Using Python Lambda, All, And Any Functions To Verify A Food Menu

It was recently reported that the Russian opposition leader, Alexei Navalny, was in coma from suspected food poisoning. That was a disturbing news that made me start thinking of how to create a function that verifies a menu for good and bad foods. I did some thinking and decided that the right functions to use for the verification process were the python all, any and lambda functions.

verifying menu using python lambda, all and any functions
 

But before I start describing the verification process, let us talk a little about these functions.

The Python All Function

The Python all function will return True if all the elements in an iterable are True or if the iterable is empty. The syntax for the python all function is all(iterable). If you want to know what an iterable means, you can check out this post on iterables.

Let us take some examples to demonstrate how it works. We will use a python list for the python all examples.

As you can see when you run the example above, all the elements need to be True or it needs to be an empty list for the python all function to return True.

Note that on a dictionary, the function works on the keys of the dictionary. You can make out examples of your own and try them out.

Also, on numbers, when the number is 0, it is evaluated to be False as a Boolean expression in python and True on all other numbers.

The Python Any Function

The python any function will return True if any element of the iterable is True and will return False if none of the elements is True. For an empty list it will return False. The syntax of the any function is any(iterable).

Here is a python any function example using a python list.

You can try it out on another iterable like a string or dictionary. In dictionaries, the python any function iterates through the keys.

One more python function you need to know about for us to write this code beautifully are python lambda functions.

What are python lambda functions?

Python lambda functions are anonymous python functions which are created with the lambda keyword. They can be used to replace function objects but are restricted in syntax to a single expression. Lambda expressions are just semantic sugar for a normal function definition. They also have scopes like normal functions through which they reference variables.

The syntax of a lambda function or lambda expression is “lambda parameters: expression”. The expression is first followed by the lambda keyword, parameters represent what is passed to the function and the expression is the code that you want to implement in the function. The parameter and expression are separated by a colon.

Given the attributes of python lambda functions above, let me demonstrate how we can create one. For example, if we want to write a single expression that cubes some numbers. Instead of resorting to a normal function, since it is a single expression, we can use a lambda expression inside another function, this time, the python map function. This is an example of a python function inside another function.


cubed = list(map(lambda x: x ** 3,  [1, 2,3,4]))
print(cubed)

You can see from above that the lambda function is used inside the map function and cubes each of the numbers in the list. The lambda function contains just a single expression, x ** 3.

Now that we have all we need to carry out the menu verification program, let’s begin.

The menu verification program

So, we want to write a program that when given a list of recommended foods we want to verify each of the menu for the day whether that menu should be accepted or not. For a menu to be accepted, all the foods have to be in the recommended_foods list and none of the foods should be in the junk_foods list. So, let’s have a go at a menu and see what happens as we write the code.

Elegant, not so? Be creative. Try out your own food test for the recommended and junk foods. Use the all, any, and lambda functions to test out your skills in python.

Happy pythoning.

Matched content