Diffie-Hellman key exchange ,theory and practice with node.js
Preface
say that you are developing an application in which you send and receive confidential information to and from your server ,for example you are developing an application which provides payment service for users and need to be aware of user’s payment credentials ,and say that ,for example , you are using a js based technology for developing front-end of your application (such as react ,react-native ,vue.js ,angular ,…) ,the most primitive (and most disastrous!)way to do so is by the below sample code
fetch(/*path to your backend service*/,{
method:'post',
body:/*your user financial credentials*/
}
).then(response=>{
/*callback code*/
}
)
the problem with the foregoing code is that every body can easily eavesdrop it and steal your user’s financial info which is going to be held surreptitious and as a result within a month you will face with lots of users complaining about emptying their account and you will be bankrupted less than a month .
so here’s where security measures came in and that’s why you should send information such that if someone would spy on the messages being transferred ,he or she get meaningless info .furthermore the message should be so that can be reverted back to its original form in the receiver side ,this is informal explanation of cryptography .
more about cryptography process
for cryptography you need to specify two things ,the first one is a secure enough and unpredictable key ,the second one is choosing an appropriate cryptography algorithm .the algorithm combines key and your message ,which from now on we name it plain text and convert it to a meaningless string ,which we name it cipher text .
the next important stage happens in receiver and here’s the metric by which we classify cryptography algorithm . if we use the same key in receiver to revert the encrypted message to its original form ,or decrypt it ,we are said to use a symmetric cryptography algorithm .because an appropriate image worth thousands of words and because we’re not going to deep dive in symmetric cryptography details ,to represent the process we represent the process by an image¹
at the first glance to the picture ,you may ask ”If there exist a secure channel ,why we should use insecure channel an encrypt the message at all?” the answer to the question is that the secure channel is ,in the most primitive form ,something like pen and paper or a shared file on which you write your secret key ,which obviously can not be used for TCP connections, or can be gained by establishing asymmetric cryptography ,which will be discussed soon and is the subject of this article .
Theoretical basics
in this section we are going to introduce some elementary definitions related to number theory ,it should be emphasized that we are not going to go through all mathematical details of the concepts, because its mathematical tools is beyond the scope of this writing furthermore this is going to be an article for programmers not mathematicians :)
prime number: any natural number which its divisors is only 1 and itself .
modular arithmetic: two numbers a and b are said to be congruent modulo n, if their difference a − b is an integer multiple of n and we wright :
primitive root a primitive root of a prime number p is one whose powers modulo p generate all the integers from 1 to p - 1 .for example if b is primitive root of p then the set defined below includes all integers between 1 and p-1
Diffie-Hellman algorithm is used for the purpose expressed above ,as its name suggests ,its used for establishing encryption key .the best way to explain that is using a diagram which comes below
there are a few things to mention about above figure
- the only thing that each participant should hold for himself is the selected private keys ,all other parameters can be known by anyone
- ultimate calculated keys are the same for both of participants
- we are able to produce very very large prime numbers ,so iterating over all possible candidates for secret key ,which is named as brute force attack is computationally impossible(a typical prime number which we deal with is 25757958126374652770626413355438366985352135325629930149975855419805792464394189968289166861729794211463892760254868001659868682717358770945855620587250595224515756824943786125312792393485258129044248679185412029449638590943165189867107164837632501350715030639024593712798327467855571507830689053001603224600744804605135161750607174852109947444135390002447314130073024877965669638386599723881140871859390266920698526164463604781411312976555050443198628792037805853975960757547183708694604328870633301530055071659993908737001167912867803850184451432695924336370765419976860117228597918528841684670985466108583529833883 )
How to implement that
let’s recap what we learned so far :
- if we choose a very big prime number ,q ,one of it’s primitive roots ,t and generate a pair of public and private keys , y_of_a and x_of_a respectively , we only need to keep one of four parameters for ourselves and three other parameters are publicly known
- each encryption procedure needs to be computationally intensive to be broke and there should be at least one operation which solving that for attacker requires a great deal of cpu cycles ,a good metric to measure security level is bit security level . solving discrete logarithm problem is the very difficult problem and key point of diffie-hellman problem
in the following we use a simple node.js code to represent how to implement key-exchange algorithm .the library used for generating required argument is the built in crypto library which provides the programmer with tons of encryption tools .
const crypto = require('crypto')// the argument in paranthesis show length of the prime number// the bigger number ,the more difficult to break the cypher ,the more clock cycle needed to generate it
const alice = crypto.createDiffieHellman(1024);alice.generateKeys();let key_exchange_arguments = {prime_number :null, //which is q in our notationprimitive_root:null , //which is t in our notationx_of_a:null ,//the only secret parameter for each of its participanty_of_a:null,//the public key which each of participant exchange with other part}key_exchange_arguments.prime_number =alice.getPrime().toString('hex')key_exchange_arguments.primitive_root=alice.getGenerator().toString('hex')key_exchange_arguments.x_of_a = alice.getPrivateKey().toString('hex')key_exchange_arguments.y_of_a = alice.getPublicKey().toString('hex')/*** after logging the variable we have*** prime_number:'8d13beca6787cae7b74fe114312acd598d9a52ebfb53644ce154c4256fa9fca6e5b76d1129b5f8917ccf2ce7a11f1c6dfa4bcf8e2bca5bb78395d3118848e2a565398fb9f8d1ae35f78cd7abb9386c44f792617fb8ae19dd347f2cb8730040205ee71589e474abe4e1dc0f80c70ba68006f9772b24446633ba1f5844c52a5ab3',primitive_root: '02',x_of_a:'7f67dffb02def0f6f5ed34547b2c0eff6e7cee8eaa4f3d9b647fb9dee10e0a657f35f0ca8072666a487b8ef248ed82e460d4a768de36276bc507b74897d1b44042269fb8369b9517a320629127ca601744abb51ff37c76c9f48961819f626a991f74e76c6ec32824bfe053998f93d72966ab6ede115ec09798dfac36f54772c8',y_of_a:'0e40d04d9d113d0c9386e23c3f633710292f5971367c649d42d03affb9371b4246a94444088b5c782beaf5686d4b9f39853c6af1fe1cb45df71d557fb0c473f6d22cb3dc19ac6243aed2f1a73ab777b3768a304ee47291ba91a3c0b5956f88bad236e89b67423461b9f667d6fbcd1fd8677d608d312884d3f1e47f8dce410db5'**/
in a realistic application ,both client and server ,should implement the aforementioned procedure ,at the beginning of communication , server can store the key of cryptography in session and client can store it in local storage .
after you received y_of_a ,or aliceKey ,in server, you can compute the final secret key in other side ,client or Bob with the following code
const finalSecret = bob.computeSecret(aliceKey);
thereafter participants encrypt the message using a symmetric algorithm ,like AES ,to get that done we first install aes-js library and then we have the following
var aesjs = require('aes-js')let fe = aesjs.utils.utf8.toBytes(key_exchang_arguments.y_of_a);var aesCbc = new aesjs.ModeOfOperation.cbc(key, iv);var encryptedBytes = aesCbc.encrypt(textBytes);
finally encryptedBytes is the message that you can send to your participant .
Vulnerabilities
although diffie-hellman is secure against passive eavesdropping ,we can eavesdrop exchanging messages using man-in-the-middle-attack ,the reader is encouraged to study the step-by-step details of the process in Cryptography and Network Security: Principles and Practice by the way we just present a figure from that mentioned source which explains the summary of the attack in which you can witness somebody else pretends to be the real participant and begin to send messages ,
the solution to this vulnerability is authentication and use of digital signature so that Bob ,ensures that it is really alice that sends him the message .
Conclusion
cryptography algorithms can be classified into two major types ,those which use the same key on both sides,symmetric ,and those which use different keys on two sides ,asymmetric cryptography, although asymmetric cryptography accompanies with advantages ,for example it reduces number of required keys considerably , it is computationally intensive ,so the better approach is to use an asymmetric cryptography to share key ,and then use a secure symmetric encryption which in this article we went through that .
[1]:the picture is taken from Data Communications and Networking 5th Edition