When we are building programs which communicate over a network, how can we keep our data private? The last thing we want is actually some different lousy hacker sniffing our packets, so how do we stop them? The easy answer: encryption. However, This specific is actually a very wide-ranging answer. Today we’re going to look specifically at how to encrypt data in Python with dynamically generated encryption keys using what is actually known as the Diffie-Hellman key exchange.
Encrypting data is actually a fairly straightforward process. You simply generate a key, run an encryption algorithm against some information using which key, in addition to send the idea to whoever the idea is actually intended for. The only requirement is actually which both parties must contain the encryption key. Typically, the encryption key will be predefined in some way. the idea might be hard-coded into a program or delivered physically to the intended recipient. The problem is actually, these methods of encryption key sharing are hardly secure. Digging through a program disassembler or even digging through someone’s trash can be used to retrieve these keys, thus creating the encryption process worthless.
What if we could dynamically generate a key? What if there was some way which both a client in addition to a server could agree upon an encryption key without ever having to tell each different the actual key? Enter the Diffie-Hellman key exchange.
According to Dr. Bill Young, a lecturer in addition to researcher in computer science by the University of Texas at Austin, “The Diffie-Hellman key agreement protocol (1976) was the first practical method for establishing a shared secret over an unsecured communication channel.” Sounds perfect. the idea also sounds impossible. Let’s dive in in addition to discover exactly how the Diffie-Hellman key exchange works.
The Wikipedia page for the D-H key exchange includes a great graphic which explains the process simply:
As seen inside the picture above, Alice in addition to Bob both start with the same common paint. Later on, we’ll recognize This specific as a set of variables in a Python program. For right now, the idea’s just paint. Alice in addition to Bob each pick another unique “secret” shade of paint which only they know in addition to add the idea to the common paint, forming a fresh “public” mixture of shade.
Alice in addition to Bob then exchange their paint mixtures, keeping their secret shade secret. Each adds their own secret colors to the mixture they just received by the different, ending up with the same “secret” shade of paint on both sides.
Bingo! A common secret which only Alice in addition to Bob know. How does This specific work mathematically though? The above concept is actually essentially an illustration of This specific formula:
(g^a)^b = (g^b)^a
When dealing with exponents raised to another exponent, the idea doesn’t matter which order you calculate the final result in. This specific is actually part of the magic of the Diffie-Hellman method.
Don’t Miss: How to Encrypt an Decrypt Text in Python
The different part is actually which handy-dandy little tool we call the modulus. When doing modulus division, the result is actually the remainder after dividing the first number by the second number. For example, 25 modulus 3 is actually 1, because after you divide 25 by 3, there is actually a remainder of 1.
The reason the modulus is actually important is actually because while the idea is actually easy to calculate the modulus of two numbers, the idea is actually hard to use the result to find which two numbers were used to calculate the idea. For instance, while 25 modulus 3 is actually 1, so is actually 27 modulus 2. There’s no way to simply “undo” a modulus like there is actually division, therefore the secrecy of the two numbers used remains in-tact.
Having said all of This specific, the Diffie-Hellman formula we’ll be using is actually This specific:
(g^a mod p)^b mod p = (g^b mod p)^a mod p
In This specific formula, “g” represents a predefined base number. This specific number should be a primitive root modulo of the prime number “p,” which is actually also predefined. Don’t let the term primitive root modulo scare you.
While finding the idea by hand is actually a process, there are plenty of resources online where you can punch in a prime number in addition to see all of the primitive roots. I’ve found the Blue Tulip works very well just for This specific. by there, just do modular division with the prime number divided by the primitive root. The result will be our primitive root modulo which we call “g,” (P % Pr = g).
Don’t Miss Cryptography Basics for the Aspiring Hacker
Yes, which’s a lot of math, yet the rest is actually simple. While “p” is actually a prime number in addition to “g” is actually a base, “a” in addition to “b” are simply random integers which the client in addition to server pick. right now which we’ve got our formula, let’s get into some programming!
Implementing the Diffie-Hellman Key Exchange into Python
Instead of trying to implement the key exchange method in a network setting, let’s first write a program which will prove which the above formula works.
Open up a fresh Python project in your favorite IDE (integrated development environment) I’ll be using the Geany IDE. Name the project whatever you want. I’m naming my file “cryptonet.py” because the idea sounded cool to me.
right now which we’ve got our environment up in addition to running, let’s start writing some code!
Step 1: Importing the Necessary Modules
First, we need to import the “random” Python module. This specific module comes that has a default installation of Python, so there’s no need to install the idea. The random module will come in handy when the idea comes to picking our two values which we’ll exchange between clients. On the first line of your program, type:
This specific will import all of the functions by the random module. just for This specific example, we could’ve also typed:
by random import randint
This specific would likely only import the randint function instead of the entire random module. yet because the program isn’t going to be very resource intensive, we can just import the entire module.
right now let’s create a function in addition to assign all of the variables we are going to need:
As you can see above, we simply declared a function called “generate” in addition to assigned four variables. As you might have guessed, modulus is actually going to be our prime modulus which we divide everything by. The “base” is actually going to be equivalent to the variable “g” inside the above example of the formula. We picked 9 because the idea is actually the result of modulus division between 23 in addition to one of its primitive roots (in This specific case, the root is actually 14).
The next two variables, “a” in addition to “b,” are going to be our two secret values which will be randomly selected. We randomly select integer values using the “randint” function provided by the random module we imported earlier. With This specific function, we specify a range of numbers (in This specific case 1 in addition to 9999) by which the function will randomly select an integer. I selected the top limit of 9999 simply to prove which This specific algorithm does, in fact, work for any value of “a” in addition to “b.”
Once we have all of our variables, the idea’s time to implement the math. This specific truly isn’t which difficult since all we’re doing is actually typing out a formula we already know.
I’ve broken the equation down into a few parts so we can understand the idea more clearly. Both “side1” in addition to “side2” represent one side of the equation. On lines 10 in addition to 12, we are taking our base (9) in addition to raising the idea to the power of “a” in addition to “b,” respectively. Notice how we used the “**” operator to do This specific. Using math.pow() will not work. Math.pow treats the numbers as floating point numbers instead of integers in addition to creates inaccuracies inside the equation. So just use “**” instead.
After we assign “side1” in addition to “side2” with the first part of the equation, we would likely exchange “side1” in addition to “side2” with the different party. Since we are just testing the formula locally, though, we’ll create two fresh variables, “Bob” in addition to “Alice.” On lines 14 in addition to 16, we assign these variables with the value of “side1” in addition to “side2” raised to the power of the secret variable which the idea has not yet been raised to. This specific is actually where the properties of exponents we talked about earlier come into play. After we do which, we Again take the modulus of the result in addition to assign the idea to “Bob” in addition to “Alice,” respectively.
At This specific point, regardless of the values of “a” in addition to “b,” our two secret key values (Bob in addition to Alice) should be the same. To check This specific, we’ll put a couple print calls at the end of the function:
right now we add a call to the function we created at the end of the script on line 22, in addition to we can test out the Diffie-Hellman key exchange!
the idea works! right now, by only exchanging the values of “a” in addition to “b” between two clients, we can generate a secret encryption key.
A Few Notes About the Example
While the example presented is actually definitely more secure than simply hard-coding an encryption key into a program, the idea is actually not completely secure. This specific is actually because we used some relatively tiny numbers (23, 9, in addition to the range of 1 to 9999) in order to generate our key. Because of This specific, someone could brute-force the encryption key fairly easily. By using much larger prime numbers, a much larger base, in addition to increasing the range of our random variables, we could make the key space for brute forcing the encryption key much more difficult. The larger the numbers, the more difficult the key will be to brute force.
Also, the “secret number” which we’ve generated here should not be used as an encryption key itself. Instead, the idea should be used to help generate a much larger encryption key. which, however, would likely be a whole different article itself.
The last thing you should know is actually which the random module isn’t completely secure. In theory, someone could brute force the randomization seed (the data which the program uses to select a random number) in addition to use the idea to predict the two integers we picked above. This specific truly isn’t too much of a security concern unless the attacker has the source code though. Otherwise, they’ll have no idea what operations are being done to the random numbers. We could be multiplying, subtracting, or doing any number of things to the integer before we pass the idea into the D-H algorithm. If you want a more secure method of randomization, you could instead use the secrets module like This specific:
a = secrets.randbelow(9999)
b = secrets.randbelow(9999)
#Note: randbelow by default starts the range at 0 in addition to goes to the positive number specified.
There are different functions you could use inside the module as well, yet This specific one is actually the one most comparable to the example we used above.
Thanks for reading! If you have any questions, comment below or ask me on Twitter @xAllegiance. For right now, give those dirty network snoopers Diffie-Hell, man!
Screenshots by allegiance/Null Byte