{"id":395454,"date":"2024-06-29T12:14:05","date_gmt":"2024-06-29T12:14:05","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=395454"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=395454","title":{"rendered":"<span>How to exchange a secret key over an insecure network (EC-Diffie-Hellman algorithm)<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>Let\u2019s say you want to send an encrypted message to your friend in order to avoid it being intercepted and read by a third party. You just generate a random secret key and encrypt the message with it. Let\u2019s say you use <a href=\"https:\/\/en.wikipedia.org\/wiki\/Advanced_Encryption_Standard\" rel=\"noopener noreferrer nofollow\">AES<\/a>. But how do you let your friend know the key to decrypt it?<\/p>\n<p>You could give the key to your friend offline. Just write it on paper and give it to him\/her. But what if it\u2019s not an option?\u00a0<\/p>\n<p>What if you can only use an <strong>insecure<\/strong> data communication channel with a middleman intercepting the messages?<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/679\/bfa\/5c9\/679bfa5c9d9e0047ab073a54c927fc54.png\" alt=\"Source: https:\/\/www.treinaweb.com.br\/blog\/termos-comuns-de-seguranca-man-in-the-middle\" title=\"Source: https:\/\/www.treinaweb.com.br\/blog\/termos-comuns-de-seguranca-man-in-the-middle\" width=\"1366\" height=\"768\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/679\/bfa\/5c9\/679bfa5c9d9e0047ab073a54c927fc54.png\"\/><figcaption>Source: https:\/\/www.treinaweb.com.br\/blog\/termos-comuns-de-seguranca-man-in-the-middle<\/figcaption><\/figure>\n<p>There is a way to securely exchange secret keys even in the presence of a third party!<br \/>You just exchange some information with your friend and <strong>both of you come up with the same key<\/strong>. The middleman also sees the messages you\u2019ve exchanged. But he will never be able to guess the secret key. Does it sound exciting? Let\u2019s see how it\u2019s possible.<\/p>\n<h4>Diffie-Hellman Algorithm<\/h4>\n<p>The algorithm is based on an extremely simple algebraic feature that we are all familiar with.<br \/>The <strong>commutative property of multiplication<\/strong>. In other words:<\/p>\n<p>A * B * C = B * A * C = C * A * B,\u00a0\u2026<\/p>\n<p>I know, it doesn\u2019t yet seem relevant to anything yet.<\/p>\n<h3>A very rough (and incomplete) example<\/h3>\n<ul>\n<li>\n<p>Let\u2019s <strong>imagine<\/strong>, the <strong>division<\/strong> operation <strong>doesn\u2019t exist<\/strong>.<\/p>\n<\/li>\n<li>\n<p>You and your friend<strong> both know<\/strong> some number, let\u2019s say, <strong>12345<\/strong>.<\/p>\n<\/li>\n<li>\n<p>You generate some random Private key, let\u2019s say, <strong>23456<\/strong><\/p>\n<\/li>\n<li>\n<p>Your friend generates a random Private key too, let\u2019s say <strong>34567<\/strong><\/p>\n<\/li>\n<li>\n<p>You multiply your Private key <strong>23456 <\/strong>by<strong> 12345 = 289564320 (Public key)<\/strong><\/p>\n<\/li>\n<li>\n<p>Your friend multiplies his\/her Private key <strong>34567 by 12345 = 426729615 (Public key)<\/strong><\/p>\n<\/li>\n<li>\n<p><em>!!! at this point, we just imagine the division operation doesn\u2019t exist\u00a0!!!<\/em><\/p>\n<\/li>\n<li>\n<p>You and your friend send the results of multiplication (the Public keys) to each other (<strong>289564320<\/strong> and <strong>426729615<\/strong>)<\/p>\n<\/li>\n<li>\n<p>Your friend multiplies your Public key <strong>289564320<\/strong> by his Private key <strong>34567 = 10009369849440<\/strong><\/p>\n<\/li>\n<li>\n<p>You multiply your friend\u2019s <strong>Public key<\/strong> <strong>426729615<\/strong> by your Private key <strong>23456 = 10009369849440, and this is the shared key<\/strong><\/p>\n<\/li>\n<li>\n<p><em>Profit! You came up with the same value!<\/em><\/p>\n<\/li>\n<\/ul>\n<p>But\u2026 the only problem is that the division operation actually exists, so it\u2019s extremely easy to extract the Private key from a Public key.\u00a0<\/p>\n<p>A middleman could just divide Public keys by <strong>12345,<\/strong> and extract the Private keys<strong>: 289564320\/12345 = 23456, 426729615\/12345 = 34567<\/strong>, and then  just multiply the private keys by the shared number: <strong>23456 * 34567 * 12345 = 10009369849440.<\/strong><\/p>\n<p>That was the general idea of the Diffie Hellman, and now let\u2019s focus on an actual form.<\/p>\n<p>Let\u2019s combine the Diffie-Hellman idea with <strong>Elliptic Curve Cryptography<\/strong> as it\u2019s the most used implementation nowadays.\u00a0<\/p>\n<blockquote>\n<p>To fully understand the topic, I highly recommend checking <a href=\"https:\/\/habr.com\/en\/post\/692072\/\" rel=\"noopener noreferrer nofollow\">my article on Elliptic Curve Cryptography<\/a>. It requires no more than middle-school math.<\/p>\n<\/blockquote>\n<h4>Very short: Essentials of Elliptic Curves cryptography<\/h4>\n<p>I don\u2019t think it\u2019s possible to explain how the Elliptic curves are used in cryptography briefly. But here are the most important properties:<\/p>\n<ul>\n<li>\n<p>We can multiply any point lying on a curve by a scalar value<\/p>\n<\/li>\n<li>\n<p>There is no feasible way to extract the scalar value back (to divide a point by a scalar value or by another point)<\/p>\n<\/li>\n<li>\n<p>A private key in elliptic curve cryptography is just a random value that\u2019s kept secret<\/p>\n<\/li>\n<li>\n<p>The corresponding Public key is just a result of the multiplication of some certain point <strong>G<\/strong> by the Private key (PublicKey = PrivateKey * G)<\/p>\n<\/li>\n<li>\n<p>The <strong>G<\/strong> point is standardized and everyone uses it<\/p>\n<\/li>\n<\/ul>\n<h4>How to securely exchange the keys over a public\u00a0network?<\/h4>\n<p>Let\u2019s suppose we have two parties: Alice and Bob (<a href=\"http:\/\/cryptocouple.com\/\" rel=\"noopener noreferrer nofollow\">why again these names?<\/a>).<\/p>\n<blockquote>\n<p><em>Here is a <\/em><strong><em>[way too] colorful<\/em><\/strong><em> explanation of the Diffie-Hellman key exchange mechanism. It may not look too pretty, but the colors which occur as the results of multiplication are actually the mixes of original colors.\u00a0<\/em><strong><em>Squares<\/em><\/strong><em> indicate <\/em><strong><em>scalar<\/em><\/strong><em> values, and the <\/em><strong><em>circles<\/em><\/strong><em> indicate <\/em><strong><em>points<\/em><\/strong><em> on an Elliptic curve.<\/em><\/p>\n<\/blockquote>\n<p>Both Alice and Bob generate <strong>big random numbers<\/strong>, and we call these numbers the <strong>Private Keys<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b7a\/d7f\/e0c\/b7ad7fe0c77cbc81f4be018235ffe6a8.png\" alt=\"\" title=\"\" width=\"1600\" height=\"537\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b7a\/d7f\/e0c\/b7ad7fe0c77cbc81f4be018235ffe6a8.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Then Alice <strong>multiplies<\/strong> her <strong>Private Key<\/strong> by the publicly known <strong>G point<\/strong> in order to get her <strong>Public Key<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/963\/db4\/af8\/963db4af8199c6f94e8f42b8cf4401ca.png\" alt=\"\" title=\"\" width=\"1600\" height=\"852\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/963\/db4\/af8\/963db4af8199c6f94e8f42b8cf4401ca.png\"\/><figcaption><\/figcaption><\/figure>\n<p>And Bob multiplies his <strong>Private Key<\/strong> by the same <strong>point G<\/strong> to get his <strong>Public Key<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0eb\/b52\/727\/0ebb527271811878768314c477881cdb.png\" alt=\"\" title=\"\" width=\"1600\" height=\"852\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0eb\/b52\/727\/0ebb527271811878768314c477881cdb.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Now they both have their pairs of PrivateKey-PublicKey:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/200\/4a1\/e15\/2004a1e150c373e5f1ebcabf9dd86c3d.png\" alt=\"\" title=\"\" width=\"1600\" height=\"535\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/200\/4a1\/e15\/2004a1e150c373e5f1ebcabf9dd86c3d.png\"\/><figcaption><\/figcaption><\/figure>\n<p>The next step is to exchange the public keys.\u00a0<\/p>\n<p>Alice <strong>sends<\/strong> her <strong>Public<\/strong> Key to Bob. And Bob <strong>sends<\/strong> his <strong>Public<\/strong> Key to Alice:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d9a\/b72\/10c\/d9ab7210c4adba522445e1ac2c3a256c.png\" alt=\"\" title=\"\" width=\"1600\" height=\"679\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d9a\/b72\/10c\/d9ab7210c4adba522445e1ac2c3a256c.png\"\/><figcaption><\/figcaption><\/figure>\n<p>After that, Alice and Bob have each other\u2019s <strong>Public<\/strong> keys, but a middleman <strong>also<\/strong> potentially knows their Public keys:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f01\/89d\/922\/f0189d922d7a4ade14669dd11787f86f.png\" alt=\"\" title=\"\" width=\"1600\" height=\"756\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f01\/89d\/922\/f0189d922d7a4ade14669dd11787f86f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>If you remember, <strong>Private<\/strong> Key <strong>can\u2019t be extracted<\/strong> back from the <strong>Public<\/strong> key. So knowing the <strong>Public keys<\/strong> is <strong>of no use<\/strong> to a middleman.<\/p>\n<h4>Then the magic\u00a0happens.<\/h4>\n<p><strong>Alice<\/strong> takes <strong>Bob\u2019s Public Key<\/strong> (a point on an Elliptic curve) and <strong>multiplies<\/strong> it into <strong>her Private Key<\/strong>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6e0\/a6a\/b5c\/6e0a6ab5cbfee3ed0511b0e5052eb8c8.png\" alt=\"\" title=\"\" width=\"1600\" height=\"1029\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6e0\/a6a\/b5c\/6e0a6ab5cbfee3ed0511b0e5052eb8c8.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>Bob<\/strong> does the same. He <strong>takes<\/strong> <strong>Alice\u2019s Public Key<\/strong> and <strong>multiplies<\/strong> it into <strong>his<\/strong> own <strong>Private Key:<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4a5\/792\/217\/4a5792217bd3019d4779c9821923e9fd.png\" alt=\"\" title=\"\" width=\"1600\" height=\"1015\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4a5\/792\/217\/4a5792217bd3019d4779c9821923e9fd.png\"\/><figcaption><\/figcaption><\/figure>\n<h4>They end up with the same Secret key without explicitly exchanging it<\/h4>\n<p>Actually, it\u2019s a very simple math trick.\u00a0<br \/>Let\u2019s take a look at how their Public keys are calculated:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b1e\/25f\/72e\/b1e25f72e6d3e92b3ce1cbc95bb9a7d8.png\" alt=\"\" title=\"\" width=\"1446\" height=\"272\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b1e\/25f\/72e\/b1e25f72e6d3e92b3ce1cbc95bb9a7d8.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Not let\u2019s look at how both parties calculate the shared keys:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dc4\/faf\/1db\/dc4faf1dbfc8488b590e516e0481399b.png\" alt=\"\" title=\"\" width=\"1600\" height=\"238\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/dc4\/faf\/1db\/dc4faf1dbfc8488b590e516e0481399b.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s see if <strong>BobSecretKey<\/strong> = <strong>AliceSecretKey<\/strong> by comparing their definitions:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c9c\/12f\/aaa\/c9c12faaa4bc8de35dd9cf0827d56aff.png\" alt=\"\" title=\"\" width=\"1600\" height=\"156\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c9c\/12f\/aaa\/c9c12faaa4bc8de35dd9cf0827d56aff.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s substitute <strong>AlicePublicKey <\/strong>and<strong> BobPublicKey<\/strong> with their definitions:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6f4\/9d8\/5b3\/6f49d85b3d6ce7a269ecc9fe277b08a8.png\" alt=\"\" title=\"\" width=\"1600\" height=\"136\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6f4\/9d8\/5b3\/6f49d85b3d6ce7a269ecc9fe277b08a8.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>The expressions are the same.<\/strong><\/p>\n<blockquote>\n<p><em>If you don\u2019t yet understand why and how we are able to multiply points on Elliptic curves like numbers, I recommend <\/em><a href=\"https:\/\/habr.com\/en\/post\/692072\/\" rel=\"noopener noreferrer nofollow\"><em>reading the article<\/em><\/a><em>.<\/em><\/p>\n<\/blockquote>\n<p>Both Alice and Bob now have ended up with the same <strong>SecretKey<\/strong> (point on a curve), which they didn\u2019t expose to a middleman.<\/p>\n<p>And the middleman can do nothing with their <strong>Public Keys<\/strong> which he has potentially intercepted.<\/p>\n<h4>Let\u2019s implement it in\u00a0Python<\/h4>\n<p>In my <a href=\"https:\/\/habr.com\/en\/post\/692072\/\" rel=\"noopener noreferrer nofollow\">article on Elliptic curves<\/a>, I have a code snippet for using the secp256k1 elliptic curve, written in Python. For more details on how it works, check the article&#8217;s PART V.<\/p>\n<p>What\u2019s important is that we have the <code>g_point<\/code> instance, which has the\u00a0.multiply method for multiplying the point by any scalar value. The return value of this method is also a point.<\/p>\n<p>Let\u2019s pick random private keys for Alice and bob:<\/p>\n<pre><code class=\"python\">alice_private_key = 4115217275797054326758545175592171983915694080873854598446270747 #any random number bob_private_key = 4954095651507529369947464574074855803473979998363142920136936367 #any random number<\/code><\/pre>\n<p>Then let\u2019s calculate the public keys for both of them:<\/p>\n<pre><code class=\"python\">alice_public_key = g_point.multiply(alice_private_key) bob_public_key = g_point.multiply(bob_private_key)<\/code><\/pre>\n<p>Now let\u2019s imagine they have sent the public keys to each other. Alice calculates the secret key on her side:<\/p>\n<pre><code class=\"python\">alice_secret_key = bob_public_key.multiply(alice_private_key)<\/code><\/pre>\n<p>Bob calculates his secret key on his side:<\/p>\n<pre><code class=\"python\">bob_secret_key = alice_public_key.multiply(bob_private_key)<\/code><\/pre>\n<p>Now let\u2019s print the secret keys:<\/p>\n<pre><code class=\"python\">print(bob_secret_key.x, bob_secret_key.y) print(alice_secret_key.x, alice_secret_key.y)<\/code><\/pre>\n<p>The result:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fad\/aab\/332\/fadaab33284dd8effd93071a82bd3697.png\" alt=\"\" title=\"\" width=\"1600\" height=\"95\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fad\/aab\/332\/fadaab33284dd8effd93071a82bd3697.png\"\/><figcaption><\/figcaption><\/figure>\n<p>It works!<\/p>\n<h4>Here is the complete Python code using zero dependencies for you to try it\u00a0yourself<\/h4>\n<pre><code class=\"python\">def find_inverse(number, modulus):     return pow(number, -1, modulus)   class Point:     def __init__(self, x, y, curve_config):         a = curve_config['a']         b = curve_config['b']         p = curve_config['p']          if (y ** 2) % p != (x ** 3 + a * x + b) % p:             raise Exception(\"The point is not on the curve\")          self.x = x         self.y = y         self.curve_config = curve_config      def is_equal_to(self, point):         return self.x == point.x and self.y == point.y      def add(self, point):         p = self.curve_config['p']          if self.is_equal_to(point):             slope = (3 * point.x ** 2) * find_inverse(2 * point.y, p) % p         else:             slope = (point.y - self.y) * find_inverse(point.x - self.x, p) % p          x = (slope ** 2 - point.x - self.x) % p         y = (slope * (self.x - x) - self.y) % p         return Point(x, y, self.curve_config)      def multiply(self, times):         current_point = self         current_coefficient = 1          pervious_points = []         while current_coefficient &lt; times:             # store current point as a previous point             pervious_points.append((current_coefficient, current_point))             # if we can multiply our current point by 2, do it             if 2 * current_coefficient &lt;= times:                 current_point = current_point.add(current_point)                 current_coefficient = 2 * current_coefficient             # if we can't multiply our current point by 2, let's find the biggest previous point to add to our point             else:                 next_point = self                 next_coefficient = 1                 for (previous_coefficient, previous_point) in pervious_points:                     if previous_coefficient + current_coefficient &lt;= times:                         if previous_point.x != current_point.x:                             next_coefficient = previous_coefficient                             next_point = previous_point                 current_point = current_point.add(next_point)                 current_coefficient = current_coefficient + next_coefficient          return current_point   secp256k1_curve_config = {     'a': 0,     'b': 7,     'p': 115792089237316195423570985008687907853269984665640564039457584007908834671663 } x = 55066263022277343669578718895168534326250603453777594175500187360389116729240 y = 32670510020758816978083085130507043184471273380659243275938904335757337482424 n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 g_point = Point(x, y, secp256k1_curve_config)  ##############################  alice_private_key = 4115217275797054326758545175592171983915694080873854598446270747 #any random number bob_private_key = 4954095651507529369947464574074855803473979998363142920136936367 #any random number   alice_public_key = g_point.multiply(alice_private_key) bob_public_key = g_point.multiply(bob_private_key)  alice_secret_key = bob_public_key.multiply(alice_private_key) bob_secret_key = alice_public_key.multiply(bob_private_key)   print(bob_secret_key.x, bob_secret_key.y) print(alice_secret_key.x, alice_secret_key.y) <\/code><\/pre>\n<p>In case you might need it, here is an <a href=\"https:\/\/www.programiz.com\/python-programming\/online-compiler\/\" rel=\"noopener noreferrer nofollow\">online tool for running Python code right in your browser<\/a><\/p>\n<hr\/>\n<p><a href=\"mailto:exemak@gmail.com\" rel=\"noopener noreferrer nofollow\">exemak@gmail.com<\/a><\/p>\n<p><a href=\"https:\/\/t.me\/exemak\" rel=\"noopener noreferrer nofollow\">t.me\/exemak<\/a><\/p>\n<p>Mikhail Karavaev<\/p>\n<p><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/705832\/\"> https:\/\/habr.com\/ru\/articles\/705832\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>Let\u2019s say you want to send an encrypted message to your friend in order to avoid it being intercepted and read by a third party. You just generate a random secret key and encrypt the message with it. Let\u2019s say you use <a href=\"https:\/\/en.wikipedia.org\/wiki\/Advanced_Encryption_Standard\" rel=\"noopener noreferrer nofollow\">AES<\/a>. But how do you let your friend know the key to decrypt it?<\/p>\n<p>You could give the key to your friend offline. Just write it on paper and give it to him\/her. But what if it\u2019s not an option?\u00a0<\/p>\n<p>What if you can only use an <strong>insecure<\/strong> data communication channel with a middleman intercepting the messages?<\/p>\n<figure class=\"full-width\"><figcaption>Source: https:\/\/www.treinaweb.com.br\/blog\/termos-comuns-de-seguranca-man-in-the-middle<\/figcaption><\/figure>\n<p>There is a way to securely exchange secret keys even in the presence of a third party!<br \/>You just exchange some information with your friend and <strong>both of you come up with the same key<\/strong>. The middleman also sees the messages you\u2019ve exchanged. But he will never be able to guess the secret key. Does it sound exciting? Let\u2019s see how it\u2019s possible.<\/p>\n<h4>Diffie-Hellman Algorithm<\/h4>\n<p>The algorithm is based on an extremely simple algebraic feature that we are all familiar with.<br \/>The <strong>commutative property of multiplication<\/strong>. In other words:<\/p>\n<p>A * B * C = B * A * C = C * A * B,\u00a0\u2026<\/p>\n<p>I know, it doesn\u2019t yet seem relevant to anything yet.<\/p>\n<h3>A very rough (and incomplete) example<\/h3>\n<ul>\n<li>\n<p>Let\u2019s <strong>imagine<\/strong>, the <strong>division<\/strong> operation <strong>doesn\u2019t exist<\/strong>.<\/p>\n<\/li>\n<li>\n<p>You and your friend<strong> both know<\/strong> some number, let\u2019s say, <strong>12345<\/strong>.<\/p>\n<\/li>\n<li>\n<p>You generate some random Private key, let\u2019s say, <strong>23456<\/strong><\/p>\n<\/li>\n<li>\n<p>Your friend generates a random Private key too, let\u2019s say <strong>34567<\/strong><\/p>\n<\/li>\n<li>\n<p>You multiply your Private key <strong>23456 <\/strong>by<strong> 12345 = 289564320 (Public key)<\/strong><\/p>\n<\/li>\n<li>\n<p>Your friend multiplies his\/her Private key <strong>34567 by 12345 = 426729615 (Public key)<\/strong><\/p>\n<\/li>\n<li>\n<p><em>!!! at this point, we just imagine the division operation doesn\u2019t exist\u00a0!!!<\/em><\/p>\n<\/li>\n<li>\n<p>You and your friend send the results of multiplication (the Public keys) to each other (<strong>289564320<\/strong> and <strong>426729615<\/strong>)<\/p>\n<\/li>\n<li>\n<p>Your friend multiplies your Public key <strong>289564320<\/strong> by his Private key <strong>34567 = 10009369849440<\/strong><\/p>\n<\/li>\n<li>\n<p>You multiply your friend\u2019s <strong>Public key<\/strong> <strong>426729615<\/strong> by your Private key <strong>23456 = 10009369849440, and this is the shared key<\/strong><\/p>\n<\/li>\n<li>\n<p><em>Profit! You came up with the same value!<\/em><\/p>\n<\/li>\n<\/ul>\n<p>But\u2026 the only problem is that the division operation actually exists, so it\u2019s extremely easy to extract the Private key from a Public key.\u00a0<\/p>\n<p>A middleman could just divide Public keys by <strong>12345,<\/strong> and extract the Private keys<strong>: 289564320\/12345 = 23456, 426729615\/12345 = 34567<\/strong>, and then  just multiply the private keys by the shared number: <strong>23456 * 34567 * 12345 = 10009369849440.<\/strong><\/p>\n<p>That was the general idea of the Diffie Hellman, and now let\u2019s focus on an actual form.<\/p>\n<p>Let\u2019s combine the Diffie-Hellman idea with <strong>Elliptic Curve Cryptography<\/strong> as it\u2019s the most used implementation nowadays.\u00a0<\/p>\n<blockquote>\n<p>To fully understand the topic, I highly recommend checking <a href=\"https:\/\/habr.com\/en\/post\/692072\/\" rel=\"noopener noreferrer nofollow\">my article on Elliptic Curve Cryptography<\/a>. It requires no more than middle-school math.<\/p>\n<\/blockquote>\n<h4>Very short: Essentials of Elliptic Curves cryptography<\/h4>\n<p>I don\u2019t think it\u2019s possible to explain how the Elliptic curves are used in cryptography briefly. But here are the most important properties:<\/p>\n<ul>\n<li>\n<p>We can multiply any point lying on a curve by a scalar value<\/p>\n<\/li>\n<li>\n<p>There is no feasible way to extract the scalar value back (to divide a point by a scalar value or by another point)<\/p>\n<\/li>\n<li>\n<p>A private key in elliptic curve cryptography is just a random value that\u2019s kept secret<\/p>\n<\/li>\n<li>\n<p>The corresponding Public key is just a result of the multiplication of some certain point <strong>G<\/strong> by the Private key (PublicKey = PrivateKey * G)<\/p>\n<\/li>\n<li>\n<p>The <strong>G<\/strong> point is standardized and everyone uses it<\/p>\n<\/li>\n<\/ul>\n<h4>How to securely exchange the keys over a public\u00a0network?<\/h4>\n<p>Let\u2019s suppose we have two parties: Alice and Bob (<a href=\"http:\/\/cryptocouple.com\/\" rel=\"noopener noreferrer nofollow\">why again these names?<\/a>).<\/p>\n<blockquote>\n<p><em>Here is a <\/em><strong><em>[way too] colorful<\/em><\/strong><em> explanation of the Diffie-Hellman key exchange mechanism. It may not look too pretty, but the colors which occur as the results of multiplication are actually the mixes of original colors.\u00a0<\/em><strong><em>Squares<\/em><\/strong><em> indicate <\/em><strong><em>scalar<\/em><\/strong><em> values, and the <\/em><strong><em>circles<\/em><\/strong><em> indicate <\/em><strong><em>points<\/em><\/strong><em> on an Elliptic curve.<\/em><\/p>\n<\/blockquote>\n<p>Both Alice and Bob generate <strong>big random numbers<\/strong>, and we call these numbers the <strong>Private Keys<\/strong>:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Then Alice <strong>multiplies<\/strong> her <strong>Private Key<\/strong> by the publicly known <strong>G point<\/strong> in order to get her <strong>Public Key<\/strong>:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>And Bob multiplies his <strong>Private Key<\/strong> by the same <strong>point G<\/strong> to get his <strong>Public Key<\/strong>:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Now they both have their pairs of PrivateKey-PublicKey:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>The next step is to exchange the public keys.\u00a0<\/p>\n<p>Alice <strong>sends<\/strong> her <strong>Public<\/strong> Key to Bob. And Bob <strong>sends<\/strong> his <strong>Public<\/strong> Key to Alice:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>After that, Alice and Bob have each other\u2019s <strong>Public<\/strong> keys, but a middleman <strong>also<\/strong> potentially knows their Public keys:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>If you remember, <strong>Private<\/strong> Key <strong>can\u2019t be extracted<\/strong> back from the <strong>Public<\/strong> key. So knowing the <strong>Public keys<\/strong> is <strong>of no use<\/strong> to a middleman.<\/p>\n<h4>Then the magic\u00a0happens.<\/h4>\n<p><strong>Alice<\/strong> takes <strong>Bob\u2019s Public Key<\/strong> (a point on an Elliptic curve) and <strong>multiplies<\/strong> it into <strong>her Private Key<\/strong>.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>Bob<\/strong> does the same. He <strong>takes<\/strong> <strong>Alice\u2019s Public Key<\/strong> and <strong>multiplies<\/strong> it into <strong>his<\/strong> own <strong>Private Key:<\/strong><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h4>They end up with the same Secret key without explicitly exchanging it<\/h4>\n<p>Actually, it\u2019s a very simple math trick.\u00a0<br \/>Let\u2019s take a look at how their Public keys are calculated:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Not let\u2019s look at how both parties calculate the shared keys:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s see if <strong>BobSecretKey<\/strong> = <strong>AliceSecretKey<\/strong> by comparing their definitions:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s substitute <strong>AlicePublicKey <\/strong>and<strong> BobPublicKey<\/strong> with their definitions:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>The expressions are the same.<\/strong><\/p>\n<blockquote>\n<p><em>If you don\u2019t yet understand why and how we are able to multiply points on Elliptic curves like numbers, I recommend <\/em><a href=\"https:\/\/habr.com\/en\/post\/692072\/\" rel=\"noopener noreferrer nofollow\"><em>reading the article<\/em><\/a><em>.<\/em><\/p>\n<\/blockquote>\n<p>Both Alice and Bob now have ended up with the same <strong>SecretKey<\/strong> (point on a curve), which they didn\u2019t expose to a middleman.<\/p>\n<p>And the middleman can do nothing with their <strong>Public Keys<\/strong> which he has potentially intercepted.<\/p>\n<h4>Let\u2019s implement it in\u00a0Python<\/h4>\n<p>In my <a href=\"https:\/\/habr.com\/en\/post\/692072\/\" rel=\"noopener noreferrer nofollow\">article on Elliptic curves<\/a>, I have a code snippet for using the secp256k1 elliptic curve, written in Python. For more details on how it works, check the article&#8217;s PART V.<\/p>\n<p>What\u2019s important is that we have the <code>g_point<\/code> instance, which has the\u00a0.multiply method for multiplying the point by any scalar value. The return value of this method is also a point.<\/p>\n<p>Let\u2019s pick random private keys for Alice and bob:<\/p>\n<pre><code class=\"python\">alice_private_key = 4115217275797054326758545175592171983915694080873854598446270747 #any random number bob_private_key = 4954095651507529369947464574074855803473979998363142920136936367 #any random number<\/code><\/pre>\n<p>Then let\u2019s calculate the public keys for both of them:<\/p>\n<pre><code class=\"python\">alice_public_key = g_point.multiply(alice_private_key) bob_public_key = g_point.multiply(bob_private_key)<\/code><\/pre>\n<p>Now let\u2019s imagine they have sent the public keys to each other. Alice calculates the secret key on her side:<\/p>\n<pre><code class=\"python\">alice_secret_key = bob_public_key.multiply(alice_private_key)<\/code><\/pre>\n<p>Bob calculates his secret key on his side:<\/p>\n<pre><code class=\"python\">bob_secret_key = alice_public_key.multiply(bob_private_key)<\/code><\/pre>\n<p>Now let\u2019s print the secret keys:<\/p>\n<pre><code class=\"python\">print(bob_secret_key.x, bob_secret_key.y) print(alice_secret_key.x, alice_secret_key.y)<\/code><\/pre>\n<p>The result:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>It works!<\/p>\n<h4>Here is the complete Python code using zero dependencies for you to try it\u00a0yourself<\/h4>\n<pre><code class=\"python\">def find_inverse(number, modulus):     return pow(number, -1, modulus)   class Point:     def __init__(self, x, y, curve_config):         a = curve_config['a']         b = curve_config['b']         p = curve_config['p']          if (y ** 2) % p != (x ** 3 + a * x + b) % p:             raise Exception(\"The point is not on the curve\")          self.x = x         self.y = y         self.curve_config = curve_config      def is_equal_to(self, point):         return self.x == point.x and self.y == point.y      def add(self, point):         p = self.curve_config['p']          if self.is_equal_to(point):             slope = (3 * point.x ** 2) * find_inverse(2 * point.y, p) % p         else:             slope = (point.y - self.y) * find_inverse(point.x - self.x, p) % p          x = (slope ** 2 - point.x - self.x) % p         y = (slope * (self.x - x) - self.y) % p         return Point(x, y, self.curve_config)      def multiply(self, times):         current_point = self         current_coefficient = 1          pervious_points = []         while current_coefficient &lt; times:             # store current point as a previous point             pervious_points.append((current_coefficient, current_point))             # if we can multiply our current point by 2, do it             if 2 * current_coefficient &lt;= times:                 current_point = current_point.add(current_point)                 current_coefficient = 2 * current_coefficient             # if we can't multiply our current point by 2, let's find the biggest previous point to add to our point             else:                 next_point = self                 next_coefficient = 1                 for (previous_coefficient, previous_point) in pervious_points:                     if previous_coefficient + current_coefficient &lt;= times:                         if previous_point.x != current_point.x:                             next_coefficient = previous_coefficient                             next_point = previous_point                 current_point = current_point.add(next_point)                 current_coefficient = current_coefficient + next_coefficient          return current_point   secp256k1_curve_config = {     'a': 0,     'b': 7,     'p': 115792089237316195423570985008687907853269984665640564039457584007908834671663 } x = 55066263022277343669578718895168534326250603453777594175500187360389116729240 y = 32670510020758816978083085130507043184471273380659243275938904335757337482424 n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 g_point = Point(x, y, secp256k1_curve_config)  ##############################  alice_private_key = 4115217275797054326758545175592171983915694080873854598446270747 #any random number bob_private_key = 4954095651507529369947464574074855803473979998363142920136936367 #any random number   alice_public_key = g_point.multiply(alice_private_key) bob_public_key = g_point.multiply(bob_private_key)  alice_secret_key = bob_public_key.multiply(alice_private_key) bob_secret_key = alice_public_key.multiply(bob_private_key)   print(bob_secret_key.x, bob_secret_key.y) print(alice_secret_key.x, alice_secret_key.y) <\/code><\/pre>\n<p>In case you might need it,<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-395454","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/395454","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=395454"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/395454\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=395454"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=395454"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=395454"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}