{"id":818,"date":"2024-06-02T12:25:29","date_gmt":"2024-06-02T12:25:29","guid":{"rendered":"https:\/\/baldsolutions.com\/?p=818"},"modified":"2024-06-02T12:33:29","modified_gmt":"2024-06-02T12:33:29","slug":"breaking-diffie-hellman-key-exchange-even-in-c","status":"publish","type":"post","link":"https:\/\/baldsolutions.com\/index.php\/2024\/06\/02\/breaking-diffie-hellman-key-exchange-even-in-c\/","title":{"rendered":"Breaking Diffie-Hellman key exchange &#8211; even in C#"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Introduction<\/h1>\n\n\n\n<p>C# is a great and mature programming language. In general, the whole .NET environment which I work with on a daily basis is extremely developer friendly &#8211; things like <a href=\"https:\/\/www.jetbrains.com\/rider\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Rider<\/a> (IDE), <a href=\"https:\/\/www.nuget.org\/\" target=\"_blank\" rel=\"noopener\" title=\"\">NuGet<\/a>  (package manager) etc. work like a charm. However, few weeks ago I started to get into details of cryptography stuff and corresponding math related topics (I even completed Stanford Online <a href=\"https:\/\/coursera.org\/share\/7ae6ff481b206af26309c555f5d30c3b\" target=\"_blank\" rel=\"noopener\" title=\"\">course<\/a> in this regard). The math behind cryptography schemes  tends to rely on  large numbers (hundreds of digits) and uncommon math topics like modulo arithmetic and discrete logarithms. As I am most familiar with C# it was my first choice when it came to solve different puzzles and challenges.  Thankfully, apart from standard integral types like int, long, ulong (ulong has the greatest possible positive value = 18,446,744,073,709,551,615) there is  a struct called <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.numerics.biginteger?view=net-8.0\" target=\"_blank\" rel=\"noopener\" title=\"\">BigInteger<\/a> which I used  to  learn how the Diffie-Hellman key exchange protocol can be broken. The protocol strength relies on the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Discrete_logarithm\" target=\"_blank\" rel=\"noopener\" title=\"\">discrete logarithm problem<\/a> (DLP). Of course this is for educational purposes only!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Diffie-Hellman key exchange <\/h1>\n\n\n\n<p>The <a href=\"https:\/\/en.wikipedia.org\/wiki\/Diffie%E2%80%93Hellman_key_exchange\" target=\"_blank\" rel=\"noopener\" title=\"\">Diffie-Hellman key exchange protocol<\/a> was published in 1976. Long story shorts it was designed to establish a secret key between two parties over a public communication channel (public means that it could be eavesdropped &#8211; I don&#8217;t cover the exact details of the algorithm as there are many many well written explanation over the Internet). The protocol more or less looks like the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fix a large prime P (e.g. 600 digits).<\/li>\n\n\n\n<li>Fix an integer G such that G &lt; P.<\/li>\n\n\n\n<li>Then:<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"948\" height=\"373\" src=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2024\/06\/image-1.png\" alt=\"\" class=\"wp-image-822\" srcset=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2024\/06\/image-1.png 948w, https:\/\/baldsolutions.com\/wp-content\/uploads\/2024\/06\/image-1-300x118.png 300w, https:\/\/baldsolutions.com\/wp-content\/uploads\/2024\/06\/image-1-768x302.png 768w\" sizes=\"auto, (max-width: 948px) 100vw, 948px\" \/><\/figure>\n<\/div>\n\n\n<p>To sum up, private component of the Diffie-Hellman protocol are: a, b, K, whereas public components are: P, G, A, B.<\/p>\n\n\n\n<p>To find out what is the secret key K (remember, K = G<sup>a*b<\/sup> mod P) we must find private values a and b. The a and b were used to generate publicly available A and B so maybe it would be a good idea to break them. To extract a from A and b from B we must win through a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Discrete_logarithm\" target=\"_blank\" rel=\"noopener\" title=\"\">discrete logarithm problem<\/a>. It basically states that if you know a, m and c it is hard to find b such that:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><strong>a<sup>b<\/sup>=c mod m<\/strong><\/p>\n\n\n\n<p>If you look closer that is exactly what we want to get: a and b  from A and B, i.e. G<sup>a<\/sup> = A mod P and G<sup>b<\/sup> = B mod P assuming we know G, B, A and P (which are publicly available).<\/p>\n\n\n\n<p>Once we have the background of the problem the question is, how we can solve discrete logarithm problem? The most obvious idea is to brute force by checking a and b values starting from 1 up to the P-1. This method, however, is not feasible if we are talking about hundreds digit numbers. One way to ease the problem is to use <a href=\"https:\/\/en.wikipedia.org\/wiki\/Baby-step_giant-step\" target=\"_blank\" rel=\"noopener\" title=\"\">baby step giant step algorithm<\/a>.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Baby step giant step algorithm<\/h1>\n\n\n\n<p>The baby step giant step algorithm could be used to reduce the time complexity of the DLP from the linear complexity (O(N)) to the square root complexity (O(\u221aN)) hence the time decreases dramatically. However, the algorithm is based on a space-time trade-off  (there&#8217;s no such thing as a free lunch).  You can find quite good explanation in the wiki page among others: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Baby-step_giant-step\" target=\"_blank\" rel=\"noopener\" title=\"\">baby step giant step algorithm<\/a> so I don&#8217;t put it here. Instead, I present the implementation in C# and show some interesting benchmark. <\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Breaking DLP in C#<\/h1>\n\n\n\n<p>You can find the implementation of baby step giant step algorithm alongside the brute force implementation and benchmark of both on my GitHub: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/dotnet\/baby-step-giant-step\" target=\"_blank\" rel=\"noopener\" title=\"\">Implementation<\/a>,<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/tglowka\/baldsolutions\/tree\/master\/dotnet\/baby-step-giant-step-benchmark\" target=\"_blank\" rel=\"noopener\" title=\"\">Benchmark<\/a>.<\/li>\n<\/ul>\n\n\n\n<p>One thing that is unusual in my implementation is the <code>limit<\/code> argument in the <code>Compute<\/code> methods. This is a simplification of the algorithm because of my laptop limitation. For the sake of the blog post I limited the solution space by the <code>limit<\/code> argument so that is computationally feasible (the value of <code>limit<\/code> was chosen randomly, just to be greater than the solution of the DLP).<\/p>\n\n\n\n<p>If you run the <code>baby-step-giant-step<\/code> (dotnet run, it takes ~30 sec) you can see that both algorithms (baby step giant step and brute force) find a solution.<\/p>\n\n\n\n<p>If you run the <code>baby-step-giant-step-benchmark<\/code> (dotnet run -c Release, it takes ~20 mins) you can see the following results:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"478\" height=\"112\" src=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2024\/06\/image-3.png\" alt=\"\" class=\"wp-image-833\" srcset=\"https:\/\/baldsolutions.com\/wp-content\/uploads\/2024\/06\/image-3.png 478w, https:\/\/baldsolutions.com\/wp-content\/uploads\/2024\/06\/image-3-300x70.png 300w\" sizes=\"auto, (max-width: 478px) 100vw, 478px\" \/><\/figure>\n<\/div>\n\n\n<h1 class=\"wp-block-heading\">Summary<\/h1>\n\n\n\n<p>In this post I presented the <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.numerics.biginteger?view=net-8.0\" target=\"_blank\" rel=\"noopener\" title=\"\">BigInteger<\/a> API for dealing with really large numbers and the practical usage of the API &#8211;  breaking the discrete logarithm problem. One thing I missed in the BigInteger API is a method for computing modulo inverse. I had to implement the extended Euclidean algorithm (<code>BigIntegerExtensions<\/code> class) to get such a modulo inverse (I followed this <a href=\"https:\/\/en.wikipedia.org\/wiki\/Extended_Euclidean_algorithm\" target=\"_blank\" rel=\"noopener\" title=\"\">wiki page<\/a>). Nevertheless, I am more than happy that there is such an API so that I can play with large number stuff in the language I am most familiar with. As always I encourage all of you to try it on your own!<\/p>\n\n\n\n<p>Have a nice day, bye!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction C# is a great and mature programming language. In general, the whole .NET environment which I work with on a daily basis is extremely&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/baldsolutions.com\/index.php\/2024\/06\/02\/breaking-diffie-hellman-key-exchange-even-in-c\/\">Continue reading<span class=\"screen-reader-text\">Breaking Diffie-Hellman key exchange &#8211; even in C#<\/span><\/a><\/div>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2,18,6],"tags":[],"class_list":["post-818","post","type-post","status-publish","format-standard","hentry","category-net","category-cryptography","category-cybersecurity","entry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/818","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/comments?post=818"}],"version-history":[{"count":24,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/818\/revisions"}],"predecessor-version":[{"id":846,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/posts\/818\/revisions\/846"}],"wp:attachment":[{"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/media?parent=818"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/categories?post=818"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/baldsolutions.com\/index.php\/wp-json\/wp\/v2\/tags?post=818"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}