{"id":397172,"date":"2024-06-29T13:17:32","date_gmt":"2024-06-29T13:17:32","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=397172"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=397172","title":{"rendered":"<span>Elliptic curves and ECDSA: everything to know to sign a transaction in Bitcoin from scratch<\/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>Elliptic curves are very simple.\u00a0The Elliptic Curves Digital Signature Algorithm (ECDSA), which works on top of their properties, is used in most blockchains like Bitcoin, Ethereum, etc., and is even simpler. But it\u2019s challenging to find a good explanation on the internet and build all the pieces together. But here it is! In this article, we will.<\/p>\n<p>We will go through all the concepts needed to understand and implement this algorithm \u2014 one by one. By the end of this article, we will have a fully functioning demo\u00a0<strong>from scratch<\/strong>, which can extract the\u00a0<strong>public key<\/strong>\u00a0from the\u00a0<strong>private key<\/strong>,\u00a0<strong>sign<\/strong>\u00a0a message, and\u00a0<strong>verify<\/strong>\u00a0that the signature is correct. This implementation will\u00a0<strong>only<\/strong>\u00a0use the concepts described in this article. Moreover, it will take less than 100 lines of code.<\/p>\n<p>This article is targeted mainly at developers like myself, who want to finally understand ECDSA, but it will also be very useful for everyone else. It requires knowing no more than middle school math.<\/p>\n<p>I highly recommend following it step by step. If you want, you can grab a piece of paper and a pen and repeat all the steps in this article. It would be even better! If you\u2019re not a programmer, you can ignore some pieces of code. If you are, I recommend re-writing the code on your own and practicing!<\/p>\n<p>The article consists of 6 parts; each part uses the concepts of the previous parts (except part 2):<\/p>\n<ul>\n<li>\n<p>I: The essentials of elliptic curves<\/p>\n<\/li>\n<li>\n<p>II: The essentials of finite fields<\/p>\n<\/li>\n<li>\n<p>III: Elliptic curves over finite fields<\/p>\n<\/li>\n<li>\n<p>IV: Practical use of it: ECDSA<\/p>\n<\/li>\n<li>\n<p>V: The implementation<\/p>\n<\/li>\n<li>\n<p>VI: Live Demo<\/p>\n<\/li>\n<\/ul>\n<p>Let\u2019s start here!<\/p>\n<h2>PART I: The Essentials of Elliptic Curves<\/h2>\n<p>We\u2019re all probably familiar with all those graphs on coordinate grids where the\u00a0<strong>y<\/strong>\u00a0variable somehow depends on\u00a0<strong>x<\/strong>. For example,\u00a0<strong>y = x<\/strong>,\u00a0<strong>y = x\u00b2<\/strong>, and so on. Most probably, we all have some experience with it. Let\u2019s look at them:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/690\/dde\/91c\/690dde91c81c26f3f0c7ca95a53042da.png\" alt=\"\" title=\"\" width=\"1400\" height=\"674\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/690\/dde\/91c\/690dde91c81c26f3f0c7ca95a53042da.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>The equation for an elliptic curve is not much different!<\/strong>\u00a0It has the form of\u00a0<strong>y\u00b2 = x\u00b3 + ax + b<\/strong>. What are\u00a0<strong>a<\/strong>\u00a0and\u00a0<strong>b<\/strong>? Just some arbitrary constants. Let\u2019s see how it looks with\u00a0<strong>a = 0<\/strong>,\u00a0<strong>b = 7<\/strong>, just like in the Bitcoin curve:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1c\/bef\/873\/c1cbef873dc61f723acb1c52b18cf990.png\" alt=\"\" title=\"\" width=\"1400\" height=\"682\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c1c\/bef\/873\/c1cbef873dc61f723acb1c52b18cf990.png\"\/><figcaption><\/figcaption><\/figure>\n<h2>It has the following three super important properties upon which everything works:<\/h2>\n<blockquote>\n<p><em>This is where it may get hard to follow and understand\u00a0<\/em><a href=\"https:\/\/www.youtube.com\/watch?v=6eZQu120A80\" rel=\"noopener noreferrer nofollow\"><em><u>why<\/u><\/em><\/a><em>. You may even think this is something incoherent and irrelevant. But please trust me. These properties will lead us to a very amazing result! But now let\u2019s pretend that we\u2019re just having fun without a purpose.<\/em><\/p>\n<\/blockquote>\n<ol>\n<li>\n<p>The elliptic curve is symmetric along the\u00a0<strong>x-axis<em>. <\/em><\/strong>It means that for any point on the curve A, we can get its mirror point, called -A, by simply mirroring its y coordinate:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/75a\/310\/a22\/75a310a2273093875634caf2a660efc2.png\" alt=\"\" title=\"\" width=\"1400\" height=\"685\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/75a\/310\/a22\/75a310a2273093875634caf2a660efc2.png\"\/><figcaption><\/figcaption><\/figure>\n<ol start=\"2\">\n<li>\n<p> If we draw a line through\u00a0<strong>any of two points not lying on a vertical line<\/strong>, it will\u00a0<a href=\"https:\/\/www.youtube.com\/watch?v=6eZQu120A80\" rel=\"noopener noreferrer nofollow\"><strong><u>intersect<\/u><\/strong><\/a>\u00a0the\u00a0<strong>curve at exactly one more point<\/strong>! Let\u2019s draw a line through the\u00a0<strong>A<\/strong>\u00a0and\u00a0<strong>B<\/strong>\u00a0points and call the third point\u00a0<strong>\u2014 C<\/strong>. Then, let\u2019s reflect it to get the point\u00a0<strong>C<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2ed\/bfa\/4cb\/2edbfa4cb8d7f0f4e2271a889ea18776.png\" alt=\"\" title=\"\" width=\"1400\" height=\"675\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2ed\/bfa\/4cb\/2edbfa4cb8d7f0f4e2271a889ea18776.png\"\/><figcaption><\/figcaption><\/figure>\n<p><em>Another example:<\/em><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/54a\/846\/daf\/54a846dafae1ee1e34dd0586ae000d37.png\" alt=\"\" title=\"\" width=\"1400\" height=\"680\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/54a\/846\/daf\/54a846dafae1ee1e34dd0586ae000d37.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>This C point is called the sum of A and B. So A + B = C.<\/strong><\/p>\n<ol start=\"3\">\n<li>\n<p>If we draw a\u00a0<strong>tangent<\/strong>\u00a0<strong>line<\/strong>\u00a0through any point\u00a0<strong>A<\/strong>\u00a0lying on a curve, it will intersect the curve at\u00a0<strong>exactly one point<\/strong>. We will call this point\u00a0<strong>-2A.<\/strong>\u00a0We already know how to get\u00a0<strong>2A<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0a6\/285\/531\/0a6285531ebb4517797a484d5152560f.png\" alt=\"\" title=\"\" width=\"1400\" height=\"683\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0a6\/285\/531\/0a6285531ebb4517797a484d5152560f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>The easiest way to think about a tangent line is to imagine it intersecting\u00a0<strong>A<\/strong>\u00a0point twice. As if it intersects the curve not at two points but three: A, A, -2A.<\/p>\n<h3>That\u2019s it! We defined three mathematical operations on the elliptic curve: multiplying a point by -1, adding two points together, and doubling a point.<\/h3>\n<h4>And here is where the algebra of elliptic curves starts working.<\/h4>\n<p>Now we have the following picture with points\u00a0<strong>A<\/strong>,\u00a0<strong>2A<\/strong>, and\u00a0<strong>-2A<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f26\/248\/56d\/f2624856d1ccdf2d4525b65b55868b5c.png\" alt=\"\" title=\"\" width=\"1400\" height=\"671\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f26\/248\/56d\/f2624856d1ccdf2d4525b65b55868b5c.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s draw a line through\u00a0<strong>A<\/strong>\u00a0and\u00a0<strong>2A<\/strong>. The third point that we\u2019ll get is\u00a0<strong>-3A<\/strong>. Then just reflect it to get\u00a0<strong>3A<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4c1\/a49\/08b\/4c1a4908b4a04ca9e47492762d9c02de.png\" alt=\"\" title=\"\" width=\"1400\" height=\"687\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4c1\/a49\/08b\/4c1a4908b4a04ca9e47492762d9c02de.png\"\/><figcaption><\/figcaption><\/figure>\n<p>You probably don\u2019t yet understand why we\u2019re doing all of it. Just look at one more step. What if we try drawing a line between\u00a0<strong>3A<\/strong>\u00a0and\u00a0<strong>-2A<\/strong>?<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fb9\/7d0\/6ba\/fb97d06ba99429d57e47b3dc29f4e663.png\" alt=\"\" title=\"\" width=\"1400\" height=\"679\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fb9\/7d0\/6ba\/fb97d06ba99429d57e47b3dc29f4e663.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>Do you see the magic?<\/strong>\u00a0By drawing a line between\u00a0<strong>3A<\/strong>\u00a0and\u00a0<strong>-2A<\/strong>\u00a0we\u2019re getting the\u00a0<strong>-A<\/strong>\u00a0point, which is the reflection of our original\u00a0<strong>A<\/strong>\u00a0point along the x-axis!<\/p>\n<h3>What we just defined in the three clauses above, is the algebra of elliptic curves.<\/h3>\n<p>Just try to understand the power of those three operations: essentially now we can perform operations on the points lying on a curve\u00a0<strong>as if they\u2019re not points, but just numbers<\/strong>!<\/p>\n<p>What we\u00a0<strong>can<\/strong>\u00a0do with points on a curve:<\/p>\n<ul>\n<li>\n<p>Addition of two points\u00a0<strong>(A + B)<\/strong><\/p>\n<\/li>\n<li>\n<p>Subtraction of two points\u00a0<strong>A \u2014 B<\/strong>\u00a0=\u00a0<strong>(A + (-B))<\/strong><\/p>\n<\/li>\n<li>\n<p>Doubling of a point (multiplication by two)\u00a0<strong>2A<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>Multiplying by any integer (by combining the previous operations together, we can get any integer * Point)<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>What we\u00a0<strong>can\u2019t<\/strong>\u00a0do:<\/p>\n<ul>\n<li>\n<p>Multiplication of two points<\/p>\n<\/li>\n<li>\n<p>Division of a point over another point<\/p>\n<\/li>\n<li>\n<p><strong>Division of a point over a scalar value<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>For example, to get\u00a0<strong>10A<\/strong>:<br \/><em>2A = A + A<br \/>4A = 2A + 2A<br \/>8A = 4A + 4A<br \/>10A = 8A + 2A<\/em><\/p>\n<p>It\u2019s also good to notice that the calculation may be performed in a logarithmic amount of operations. So the approximate amount of operations needed for calculating\u00a0<strong>n * Point<\/strong>\u00a0is\u00a0<strong>O(log2(n))<\/strong>!<\/p>\n<h3>Eventually, we can multiply a point by any integer, but there is no way to get the integer back! This is the gist of it! And this is what makes the elliptic curves very good for cryptography. And it works for infinitely large numbers.<\/h3>\n<h3>The only drawback, for now, is the need to draw it. But of course, there are mathematical formulas for reflecting a point, for addition, and for doubling a point:<\/h3>\n<ol>\n<li>\n<p><strong>Multiplying the point by -1<\/strong>. If we have a point <strong>A(x, y),<\/strong> we can easily get <strong>-A<\/strong> by multiplying its <strong>y<\/strong> coordinate by <strong>-1.<\/strong> -A(x, -y). <strong>Example: <br \/>-1 * A(2, 2) \u2192 -A(2, -2) <br \/>-1 * A(1, -1) \u2192 -A(1, 1) <br \/>-1 * A(5, 8) \u2192 -A(5, -8) <br \/>-1 * A(5, -8) \u2192 -A(5, 8)<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>Adding two points together.<\/strong> We can add two points together, but with one condition: they should not lie on a vertical line (their x coordinates should not be equal). This is the formula for adding <strong>A<\/strong> and <strong>B (A + B = C)<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ff3\/95e\/676\/ff395e6768a1d2da228db34d32cc90b8.png\" alt=\"\" title=\"\" width=\"1400\" height=\"673\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ff3\/95e\/676\/ff395e6768a1d2da228db34d32cc90b8.png\"\/><figcaption><\/figcaption><\/figure>\n<ol start=\"3\">\n<li>\n<p><strong>Adding a point to itself<\/strong>\u00a0(multiplying a point by 2). This is a very similar operation to the addition of two points but slightly different:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cb6\/b3c\/c5a\/cb6b3cc5a157b8f73185c10ccb6dea2f.png\" alt=\"\" title=\"\" width=\"1400\" height=\"839\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cb6\/b3c\/c5a\/cb6b3cc5a157b8f73185c10ccb6dea2f.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>That\u2019s it! Time to practice!<\/h3>\n<p>Let\u2019s try adding A and B here (let\u2019s use approximation to 3 points after a comma):<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2d4\/97f\/b67\/2d497fb6734b4c47b928b6464a7d7c96.png\" alt=\"\" title=\"\" width=\"1400\" height=\"695\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2d4\/97f\/b67\/2d497fb6734b4c47b928b6464a7d7c96.png\"\/><figcaption><\/figcaption><\/figure>\n<p>According to the formula defined above for adding two points,<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6c2\/845\/6b0\/6c28456b0c10013cbce012128c83bbdb.png\" alt=\"\" title=\"\" width=\"1400\" height=\"456\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6c2\/845\/6b0\/6c28456b0c10013cbce012128c83bbdb.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Now let\u2019s find our point\u00a0<strong>C<\/strong>\u00a0graphically:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bdd\/824\/23c\/bdd82423c4660a9bb7eb46267bab34ef.png\" alt=\"\" title=\"\" width=\"1400\" height=\"674\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bdd\/824\/23c\/bdd82423c4660a9bb7eb46267bab34ef.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>It works!<\/strong>\u00a0Yes, with a minor proximity issue, because of rounding. But it works! For better understanding, I recommend you try to perform all those operations on your own.<\/p>\n<h3>This was all we needed to know about elliptic curves and the operations on them that we need to be able to perform!<\/h3>\n<p>Everything is fine, but we need a couple more properties for building a cryptography system.<\/p>\n<h2>Part II: Finite fields<\/h2>\n<p>We don\u2019t need to study everything about\u00a0<a href=\"http:\/\/web.stanford.edu\/~marykw\/classes\/CS250_W19\/readings\/Forney_Introduction_to_Finite_Fields.pdf\" rel=\"noopener noreferrer nofollow\"><u>finite fields<\/u><\/a>. All we need here is to understand a couple of essential properties to move on and be able to operate on a certain \u201calgebra\u201d of finite fields.<\/p>\n<p>Have you heard of the\u00a0<strong>modulus<\/strong>\u00a0operation? If you\u2019re a programmer, you probably did. This is just a\u00a0<strong>reminder of division<\/strong>, and in programming languages, it\u2019s usually expressed as a\u00a0<strong>%<\/strong>\u00a0(or\u00a0<strong>mod<\/strong>) operator. For example:<\/p>\n<p><strong>2 mod 11 = 2<br \/>10 mod 11 = 10<br \/>11 mod 11 = 0<br \/>13 mod 11 = 2<br \/>14 mod 11 = 3<\/strong><\/p>\n<p>If we try numbers from\u00a0<strong>0<\/strong>\u00a0to\u00a0<strong>33 mod 11<\/strong>, we will get these numbers:<strong>0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0<\/strong><\/p>\n<p><em>It works\u00a0<\/em><strong><em>like a clock<\/em><\/strong><em>.\u00a0<\/em><code>We can call it a finite field of order 11<\/code>.<\/p>\n<h3>We need to know just four properties:<\/h3>\n<ol>\n<li>\n<p><strong>The order of multiplication doesn\u2019t matter. <br \/>a * b * c<\/strong>\u00a0mod n\u00a0<strong>is the same as<\/strong>\u00a0(<strong>a<\/strong>\u00a0mod n) * (<strong>b<\/strong>\u00a0mod n) * (<strong>c<\/strong>\u00a0mod n) mod n,\u00a0<strong>which is the same as<\/strong>\u00a0(<strong>a * b<\/strong>\u00a0mod n) * <strong>c<\/strong>\u00a0mod n.<br \/>Example:<br \/><strong>6 * 7 * 8<\/strong>\u00a0mod 11 =\u00a0<strong>336<\/strong>\u00a0mod 11 =\u00a0<strong>6, same as:<\/strong>\u00a0<br \/>(<strong>6 * 7<\/strong>\u00a0mod 11) \u00a0<strong>8<\/strong>\u00a0mod 11 = (<strong>42<\/strong>\u00a0mod 11) \u00a0<strong>9<\/strong>\u00a0mod 11 =\u00a0<strong>9 * 8<\/strong>\u00a0mod 11 =\u00a0<strong>72<\/strong>\u00a0mod 11 =\u00a0<strong>6<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>Negative number<\/strong>\u00a0<strong>mod n is the<\/strong>\u00a0<strong>same as n-(|negative number| mod n<\/strong>). <br \/>Examples:<br \/>1)\u00a0<strong>-4 mod 11<\/strong>\u00a0= 11-(4 mod 11) =\u00a0<strong>11\u20134 = 7<br \/><\/strong>2)<strong> -7 mod 11<\/strong>\u00a0= 11 \u2014 (7 mod 11) =\u00a0<strong>11\u20137 = 4<br \/><\/strong>3)<strong>\u00a0-9 mod 11<\/strong>\u00a0= 11 \u2014 (9 mod 11) =\u00a0<strong>11\u20139 = 2<br \/><\/strong>4)\u00a0<strong>-2 mod 11<\/strong>\u00a0= 11 \u2014 (2 mod 11) =\u00a0<strong>11\u20132 = 9<br \/><\/strong>5)<strong>\u00a0-13 mod 11<\/strong>\u00a0= 11 \u2014 (13 mod 11) =\u00a0<strong>11\u20132 = 9<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u201c<\/strong><a href=\"https:\/\/en.wikipedia.org\/wiki\/Multiplicative_inverse\" rel=\"noopener noreferrer nofollow\"><strong><u>Multiplicative inverse<\/u><\/strong><\/a><strong>\u201d: for any a, there is a number b, such as ab mod n = 1.<br \/>If a * b mod 11 = 1,<\/strong>\u00a0<strong>a<\/strong>\u00a0is called the\u00a0<strong>multiplicative inverse of b<\/strong>\u00a0<strong>modulo<\/strong>\u00a0<strong>n<\/strong>, and\u00a0<strong>vice versa<\/strong>:\u00a0<strong>b<\/strong>\u00a0is called the multiplicative inverse of\u00a0<strong>a<\/strong>\u00a0modulo n.<br \/>Examples:<br \/>1)\u00a0<strong>5 * x mod 11<\/strong>\u00a0= 1. Let\u2019s try values for x one by one, and we will find out\u00a0<strong>x = 9,\u00a0<\/strong>because 5 * 9 = 45, 45 mod 11 = 1. So\u00a0<strong>9\u00a0<\/strong>is the<strong>\u00a0multiplicative inverse of 5 modulo 11<\/strong>.<br \/>2)\u00a0<strong>7 * x mod 11 = 1<\/strong>. Let\u2019s try our brute force again, and we will find out\u00a0<strong>x = 8<\/strong>. 8 is the multiplicative inverse of 7 modulo 11.<br \/>3)\u00a0<strong>10 * x mod 11 = 1. x = 10.<\/strong>\u00a0So 10 is the multiplicative inverse of 10 modulo 11.<\/p>\n<p>Usually, the multiplicative inverse is found by the\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Extended_Euclidean_algorithm\" rel=\"noopener noreferrer nofollow\"><u>extended Euclidean algorithm<\/u><\/a>, but it\u2019s a matter of a separate article. So, for now, let\u2019s just use brute force. Also,\u00a0<strong>n<\/strong>\u00a0must be a prime number!<\/p>\n<\/li>\n<li>\n<p><strong>The division is the same operation as multiplication by the multiplicative inverse!<\/strong>\u00a0The last and most important property:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2cb\/abb\/671\/2cbabb671d9aa1850b67e933e87b298f.png\" alt=\"\" title=\"\" width=\"1400\" height=\"248\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2cb\/abb\/671\/2cbabb671d9aa1850b67e933e87b298f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>So, when we need to deal with division mod n, we can easily calculate it. Let\u2019s see an example:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/08a\/875\/e80\/08a875e80c11b9c569b26b0cc9bd1166.png\" alt=\"\" title=\"\" width=\"1400\" height=\"334\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/08a\/875\/e80\/08a875e80c11b9c569b26b0cc9bd1166.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>That\u2019s it! Now we know how to operate on finite fields \u201calgebra\u201d.<\/strong><\/p>\n<h2>Part III: Elliptic curves over finite fields<\/h2>\n<p>Here\u2019s where it becomes less obvious and a little harder to understand.\u00a0<strong>But this is exactly how elliptic curves are used in cryptography<\/strong>. What we need to do is exactly what is said in the title: put our elliptic curve over a finite field.<\/p>\n<p>So, here is how our formula changes:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4bd\/425\/4b5\/4bd4254b5d26c33c898f1f39930dcb3b.png\" alt=\"\" title=\"\" width=\"1400\" height=\"108\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4bd\/425\/4b5\/4bd4254b5d26c33c898f1f39930dcb3b.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Everything is the same as in the original formula but now both parts of the equation are now under the\u00a0<strong>modulo p<\/strong>.<\/p>\n<p>Let\u2019s use the elliptic curve with the following configuration for our examples:<\/p>\n<ul>\n<li>\n<p><em>a = 0<\/em><\/p>\n<\/li>\n<li>\n<p><em>b = 7<\/em><\/p>\n<\/li>\n<li>\n<p><em>p = 11<\/em><\/p>\n<\/li>\n<\/ul>\n<p>Let\u2019s find all the points on this curve running this code:<\/p>\n<pre><code class=\"javascript\">const a = 0; const b = 7; const p = 11;   for (let x = 0; x &lt;= p; x ++) {   for (let y = 0; y &lt;= p; y ++) {     if (y**2 % p === (x**3 + a * x + b) % p) {       console.log(`(${x}, ${y})`);     }   } }<\/code><\/pre>\n<p>It\u2019s\u00a0<strong>javascript<\/strong>, so you can run it even in the browser.<\/p>\n<p>Here is the result: <strong>(2, 2), (2, 9), (3, 1), (3, 10), (4, 4), (4, 7), (5, 0), (5,11), (6, 5), (6, 6), (7, 3), (7, 8)<\/strong><\/p>\n<p>Let\u2019s see what it looks like on a coordinate grid:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/919\/bb9\/e43\/919bb9e43934a902985619e0c7d15722.png\" alt=\"\" title=\"\" width=\"1400\" height=\"683\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/919\/bb9\/e43\/919bb9e43934a902985619e0c7d15722.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s try a=0, b=7, p=23:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ecb\/7fc\/050\/ecb7fc0501600647cb6d322e784a38d5.png\" alt=\"\" title=\"\" width=\"1400\" height=\"678\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ecb\/7fc\/050\/ecb7fc0501600647cb6d322e784a38d5.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong><em>Doesn\u2019t look like anything, right? No distinguishable shape.<\/em><\/strong><\/p>\n<h3>But! What turns out is that it preserves all the properties and formulas of the \u201coriginal\u201d elliptic curve!<\/h3>\n<p>So now we\u2019ve got an elliptic curve that\u00a0<strong>doesn\u2019t look like an elliptic curve.<\/strong>\u00a0But! It has a finite set of points and most importantly,\u00a0<strong>works like an elliptic curve<\/strong>.<\/p>\n<h3>We need to slightly modify our formulas from PART I with respect to mod p:<\/h3>\n<ol>\n<li>\n<p><strong>Multiplying a point by -1<\/strong>:<br \/>If we have a point\u00a0<strong>A(x, y),<\/strong>\u00a0we can easily get\u00a0<strong>-A<\/strong>\u00a0by multiplying its\u00a0<strong>y<\/strong>\u00a0coordinate by\u00a0<strong>-1 modulo p<\/strong>.<br \/><strong>Example:<br \/><\/strong>1)\u00a0<strong>-1 * A(2, 2) \u2192 -A(2, -2 mod 11) = -A(2, 9)<br \/><\/strong>2)<strong>\u00a0-1 * A(2, 9) \u2192 -A(2, -9 mod 11) = -A(2, 2)<br \/><\/strong>3)<strong>\u00a0-1 * A(6, 5) \u2192 -A(6, -5 mod 11) = -A(6, 6)<br \/><\/strong>4)<strong>\u00a0-1 * A(6, 6) \u2192 -A(6, -6 mod 11) = -A(6, 5)<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>Adding two points together<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/79c\/0f3\/15e\/79c0f315e765c7115c8434590b17c828.png\" alt=\"\" title=\"\" width=\"1400\" height=\"808\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/79c\/0f3\/15e\/79c0f315e765c7115c8434590b17c828.png\"\/><figcaption><\/figcaption><\/figure>\n<ol start=\"3\">\n<li>\n<p><strong>Adding a point to itself<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e76\/c1c\/bb6\/e76c1cbb6cdefaadbe08d57c40c94f8d.png\" alt=\"\" title=\"\" width=\"1400\" height=\"859\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e76\/c1c\/bb6\/e76c1cbb6cdefaadbe08d57c40c94f8d.png\"\/><figcaption><\/figcaption><\/figure>\n<p><em>If you don\u2019t yet understand the concept of multiplicative inverse, please, go back to PART II and check it once more.<\/em><\/p>\n<h3>That\u2019s it! Time to practice!<\/h3>\n<p>For our examples, we will use the elliptic curve with\u00a0<strong>a=0, b=7, and order p=11<\/strong>. Let\u2019s pick a point\u00a0<strong>C(7, 8)<\/strong>\u00a0and calculate\u00a0<strong>2C<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/84b\/7d7\/b03\/84b7d7b0324b6eac3f1904d1c77f8020.png\" alt=\"\" title=\"\" width=\"1400\" height=\"664\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/84b\/7d7\/b03\/84b7d7b0324b6eac3f1904d1c77f8020.png\"\/><figcaption><\/figcaption><\/figure>\n<p>We can now easily calculate 4C:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e4f\/135\/4d1\/e4f1354d13ed9ac6450355cea750bd0a.png\" alt=\"\" title=\"\" width=\"1400\" height=\"575\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e4f\/135\/4d1\/e4f1354d13ed9ac6450355cea750bd0a.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Now let\u2019s calculate\u00a0<strong>4C \u2014 C<\/strong>, which is essentially\u00a0<strong>3C = 4C + (-C)<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f63\/fd3\/2c4\/f63fd32c4d3ebca02edaba2da9d36d15.png\" alt=\"\" title=\"\" width=\"1400\" height=\"745\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f63\/fd3\/2c4\/f63fd32c4d3ebca02edaba2da9d36d15.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Then let\u2019s add\u00a0<strong>3C = C + 2C<\/strong>\u00a0and see if the result is the same:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/478\/90c\/c99\/47890cc995454ac85daa72df93955203.png\" alt=\"\" title=\"\" width=\"1400\" height=\"619\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/478\/90c\/c99\/47890cc995454ac85daa72df93955203.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>The math perfectly works here!<\/h3>\n<p><strong>One super important property<\/strong>: Every point on a curve has its own\u00a0<strong>order n<\/strong>! It works like a modulo. For example, if the\u00a0<strong>order n<\/strong>\u00a0of point\u00a0<strong>C<\/strong>\u00a0is\u00a0<strong>12<\/strong>, it means that 12C = 0 (the point doesn\u2019t exist),\u00a0<strong>13C = C<\/strong>,\u00a0<strong>16C = 4C<\/strong>,\u00a0<strong>27C = 3C<\/strong>. This property is\u00a0<strong>predefined<\/strong>\u00a0for a point.<\/p>\n<p>You can practice and make sure it works.<\/p>\n<p><strong>The order of our point C is actually 12.<\/strong>\u00a0I suggest a task for you: try calculating\u00a0<strong>8C<\/strong>\u00a0by adding\u00a0<strong>4C + 4C<\/strong>. Then try adding\u00a0<strong>8C + 8C<\/strong>. You will get\u00a0<strong>16C<\/strong>, which will be the same point as\u00a0<strong>4C<\/strong>.<\/p>\n<p>It works like a clock:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/80f\/c3c\/18b\/80fc3c18b4ea09c4feaf3a7f8521a7ff.png\" alt=\"\" title=\"\" width=\"1400\" height=\"682\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/80f\/c3c\/18b\/80fc3c18b4ea09c4feaf3a7f8521a7ff.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Now we know\u00a0<strong>absolutely everything essential<\/strong>\u00a0for using the elliptic curves in cryptography.<\/p>\n<h2>To recap<\/h2>\n<ul>\n<li>\n<p>All formulas work fine. We can still calculate\u00a0<strong>any integer x * Point<\/strong>. We still need approximately log2(x) operations!<\/p>\n<\/li>\n<li>\n<p>Elliptic curves now have a finite set of points.<\/p>\n<\/li>\n<li>\n<p>Points now have their own\u00a0<strong>order n<\/strong>, so they tend to repeat themselves like in a clock.<\/p>\n<\/li>\n<li>\n<p>To define an elliptic curve, we now need three variables:\u00a0<strong>a<\/strong>,\u00a0<strong>b<\/strong>, and\u00a0<strong>p<\/strong>.\u00a0<strong>p<\/strong>\u00a0is called the order of an elliptic curve.<\/p>\n<\/li>\n<\/ul>\n<p>How do we know which\u00a0<strong>a<\/strong>,\u00a0<strong>b<\/strong>, and\u00a0<strong>p<\/strong>\u00a0to use? It\u2019s standardized! There are many standards out there.<\/p>\n<h3>What do Bitcoin and Ethereum use?<\/h3>\n<p>They use the\u00a0<strong>standardized elliptic curve<\/strong>\u00a0called\u00a0<strong>secp256k1<\/strong>. It has the following variables:<\/p>\n<ul>\n<li>\n<p>a=<strong>0<\/strong><\/p>\n<\/li>\n<li>\n<p>b=<strong>7<\/strong><\/p>\n<\/li>\n<li>\n<p>p=<strong>115792089237316195423570985008687907853269984665640564039457584007908834671663<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>Quite a big number! I think you\u2019re starting to guess why elliptic curves are so good for cryptography.<\/p>\n<p>Now that we know everything important, let\u2019s apply it somewhere!<\/p>\n<h2>Part IV: Practical use of it: ECDSA<\/h2>\n<p>The\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Elliptic_Curve_Digital_Signature_Algorithm\" rel=\"noopener noreferrer nofollow\"><strong><u>Elliptic Curves Digital Signature Algorithm<\/u><\/strong><\/a>\u00a0works exactly over the algebra that we\u2019ve just discovered in the previous parts.<\/p>\n<p>This algorithm allows a person to\u00a0<strong>sign<\/strong>\u00a0a\u00a0<strong>message<\/strong>\u00a0using their\u00a0<strong>PrivateKey<\/strong>, so that anyone else can\u00a0<strong>verify<\/strong>\u00a0that the\u00a0<strong>signature<\/strong>\u00a0actually\u00a0<strong>belongs<\/strong>\u00a0to that person, also knowing their\u00a0<strong>PublicKey<\/strong>.<\/p>\n<h3>This is what actually happens when you sign a message in blockchains:<\/h3>\n<p>You just generate some\u00a0<strong>message<\/strong>\u00a0like \u201c<strong>I want to send X amount of crypto to address Y<\/strong>\u201d, and then you\u00a0<strong>sign<\/strong>\u00a0that message (using exactly the algorithm discovered in this article). Other parties can\u00a0<strong>verify<\/strong>\u00a0that the\u00a0<strong>message<\/strong>\u00a0was actually\u00a0<strong>signed<\/strong>\u00a0by you.<\/p>\n<h3>How it works<\/h3>\n<p>Everything spins around one certain\u00a0<strong>predefined<\/strong>\u00a0<strong>point<\/strong>\u00a0<strong>G<\/strong>, lying on a\u00a0<strong>predefined<\/strong>\u00a0<strong>elliptic curve<\/strong>.<\/p>\n<p>We can generate any\u00a0<strong>random integer<\/strong>\u00a0and call it our\u00a0<strong>PrivateKey.If we multiply this PrivateKey to point G, we will get the PublicKey. So PublicKey = PrivateKey * G:<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f9a\/0bf\/f2f\/f9a0bff2f067c39051139f83851a58eb.png\" alt=\"\" title=\"\" width=\"1400\" height=\"853\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f9a\/0bf\/f2f\/f9a0bff2f067c39051139f83851a58eb.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Yes,\u00a0<strong>PublicKey<\/strong>\u00a0is just a point on a curve.<\/p>\n<p>As we already know, we can\u2019t divide point by point or point by a scalar value. All possible operations are listed at the end of PART I.<\/p>\n<p>So, there is\u00a0<strong>no<\/strong>\u00a0<strong>efficient way<\/strong>\u00a0to extract\u00a0<strong>PrivateKey<\/strong>\u00a0from\u00a0<strong>PublicKey<\/strong>, even though we know point\u00a0<strong>G<\/strong>.<\/p>\n<p>We can\u2019t divide\u00a0<strong>PublicKey<\/strong>\u00a0by\u00a0<strong>G<\/strong>. This\u00a0<strong>operation doesn\u2019t exist<\/strong>. Brute-forcing potentially works, but when there are really giant amount of possible points, for example, that giant:<br \/><strong>115792089237316195423570985008687907852837564279074904382605163141518161494337<\/strong><\/p>\n<h3>Even if someone uses all the existing computing power in the world, this will take billions of billions of billions\u2026 of years to find the PrivateKey.<\/h3>\n<p>In ECDSA, we have this set of \u201cglobal\u201d public variables.\u00a0<strong>They are specified by standards<\/strong>:<\/p>\n<ul>\n<li>\n<p>Elliptic curve with some config (<strong>a<\/strong>,\u00a0<strong>b<\/strong>,\u00a0<strong>p<\/strong>)<\/p>\n<\/li>\n<li>\n<p>Point\u00a0<strong>G<\/strong>, which lies on the curve (its\u00a0<strong>x<\/strong>\u00a0and\u00a0<strong>y<\/strong>\u00a0coordinates). This is called the\u00a0<strong>Generator Point<\/strong>. This point is standardized.<\/p>\n<\/li>\n<li>\n<p>Order\u00a0<strong>n<\/strong>\u00a0of point\u00a0<strong>G<\/strong>. As we know, order\u00a0<strong>n<\/strong>\u00a0is the property for point\u00a0<strong>G<\/strong>, such<strong>\u00a0<\/strong>as G*(n+1) = G, G*(n+2) = 2G, and so on.<\/p>\n<\/li>\n<\/ul>\n<p>Here are the variables that belong to a certain owner:<\/p>\n<ul>\n<li>\n<p><strong>PrivateKey<\/strong>\u00a0\u2014 kept secret by the owner<\/p>\n<\/li>\n<li>\n<p><strong>PublicKey<\/strong>\u00a0\u2014 shared with the public<\/p>\n<\/li>\n<\/ul>\n<p>And variables that are specific to one\u00a0<strong>signing<\/strong>\u00a0operation:<\/p>\n<ul>\n<li>\n<p>The\u00a0<strong>message<\/strong>\u00a0itself: any integer that is not larger than order\u00a0<strong>n<\/strong>.\u00a0<strong>Usually<\/strong>, a\u00a0<strong>hash<\/strong>\u00a0of string is used. But for simplicity reasons, we will use pure integers.<\/p>\n<\/li>\n<li>\n<p><strong>K<\/strong>\u00a0\u2014 random integer that is generated when signing a message, exactly for that signature. This is kept secret, and there is no way to find it by a third party.<\/p>\n<\/li>\n<\/ul>\n<p>Here is the complete picture. Green stickers indicate that the variable is shared with the public, and the red ones indicate the variables that are kept secret:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ade\/fb9\/804\/adefb98046458a16dfd9f2fedf46e378.png\" alt=\"\" title=\"\" width=\"1400\" height=\"1865\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ade\/fb9\/804\/adefb98046458a16dfd9f2fedf46e378.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Way too many variables! Here are the algorithms for\u00a0<strong>signing<\/strong>\u00a0and\u00a0<strong>verifying<\/strong>\u00a0a message:<\/p>\n<h3>The algorithm for signing a message:<\/h3>\n<p>We have our\u00a0<strong>PrivateKey<\/strong>\u00a0and a\u00a0<strong>message<\/strong>. To sign a message, we should:<\/p>\n<ol>\n<li>\n<p>Generate a random integer\u00a0<strong>k<\/strong>. It should be a big number. [1,\u00a0<strong>n<\/strong>-1]<\/p>\n<\/li>\n<li>\n<p>Calculate point\u00a0<strong>R = G * k<\/strong><\/p>\n<\/li>\n<li>\n<p>Calculate\u00a0<strong>r<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e89\/627\/c7f\/e89627c7fc67f7d759fcb7fb6ea3ee1f.png\" alt=\"\" title=\"\" width=\"1400\" height=\"270\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e89\/627\/c7f\/e89627c7fc67f7d759fcb7fb6ea3ee1f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>4. Calculate\u00a0<strong>s:<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/347\/19b\/727\/34719b727463ad3a487d2e41740f8468.png\" alt=\"\" title=\"\" width=\"1400\" height=\"276\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/347\/19b\/727\/34719b727463ad3a487d2e41740f8468.png\"\/><figcaption><\/figcaption><\/figure>\n<p>That\u2019s it.\u00a0<strong>The signature is a pair of integers (r, s).<\/strong><\/p>\n<p>Here is the visual representation of the algorithm:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/05a\/17e\/df2\/05a17edf2af512ac7d69a6943bdd37c0.png\" alt=\"\" title=\"\" width=\"1400\" height=\"1085\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/05a\/17e\/df2\/05a17edf2af512ac7d69a6943bdd37c0.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>The algorithm for verifying a signature<\/h3>\n<p>We have the signer\u2019s\u00a0<strong>PublicKey<\/strong>,\u00a0<strong>message<\/strong>, and\u00a0<strong>signature(r, s).<\/strong><\/p>\n<ol>\n<li>\n<p>Calculate\u00a0<strong>U<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1b1\/b82\/306\/1b1b823065b17e56ab1834c8acc12541.png\" alt=\"\" title=\"\" width=\"1400\" height=\"256\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1b1\/b82\/306\/1b1b823065b17e56ab1834c8acc12541.png\"\/><figcaption><\/figcaption><\/figure>\n<p>2. Calculate\u00a0<strong>V<\/strong>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/324\/500\/7d8\/3245007d899818c7d5d7cff5ddfa8c7f.png\" alt=\"\" title=\"\" width=\"1400\" height=\"251\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/324\/500\/7d8\/3245007d899818c7d5d7cff5ddfa8c7f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>3. Calculate point\u00a0<strong>C<\/strong>\u00a0=\u00a0<strong>U<\/strong>\u00a0<em>\u00a0<\/em><strong><em>G<\/em><\/strong><em>\u00a0+\u00a0<\/em><strong><em>V<\/em><\/strong><em>\u00a0<\/em>\u00a0<strong>PublicKey<\/strong><\/p>\n<p>4. If\u00a0<strong>C<\/strong>.x mod\u00a0<strong>n<\/strong>\u00a0=\u00a0<strong>r<\/strong>, then the signature is valid. Invalid otherwise.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/451\/46d\/e74\/45146de74c600076fc4d2191aecc243a.png\" alt=\"\" title=\"\" width=\"1400\" height=\"1167\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/451\/46d\/e74\/45146de74c600076fc4d2191aecc243a.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Not obvious at all!<\/p>\n<p>Actually, this is just a mathematical trick.<\/p>\n<h3>Let\u2019s play with our formulas and prove that it works!<\/h3>\n<p>In step 3 of our\u00a0<strong>verification<\/strong>\u00a0algorithm, we have a point<br \/><strong>C = U * G + V * PublicKey:<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/052\/384\/0ae\/0523840aeeb9751f34c83e6788f5ac42.png\" alt=\"\" title=\"\" width=\"1400\" height=\"271\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/052\/384\/0ae\/0523840aeeb9751f34c83e6788f5ac42.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s substitute the variables\u00a0<strong>U, V, and PublicKey<\/strong>\u00a0with their definitions:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4c9\/851\/c4f\/4c9851c4f9cfc66c16d94a45cdf6a341.png\" alt=\"\" title=\"\" width=\"1400\" height=\"394\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4c9\/851\/c4f\/4c9851c4f9cfc66c16d94a45cdf6a341.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f58\/fb4\/461\/f58fb4461d2edbae05465d150bce3bab.png\" alt=\"\" title=\"\" width=\"1400\" height=\"159\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f58\/fb4\/461\/f58fb4461d2edbae05465d150bce3bab.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Notice that G * s^-1 is duplicated. Let\u2019s simplify the formula:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/349\/5ea\/731\/3495ea73195774eb582abcfa2599ca2e.png\" alt=\"\" title=\"\" width=\"1400\" height=\"186\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/349\/5ea\/731\/3495ea73195774eb582abcfa2599ca2e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s see the definition of\u00a0<strong>s<\/strong>\u00a0in step\u00a0<strong>4<\/strong>\u00a0of the\u00a0<strong>signing<\/strong>\u00a0algorithm:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2a3\/fc0\/589\/2a3fc0589762b042665c0779e4cef53e.png\" alt=\"\" title=\"\" width=\"1400\" height=\"262\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2a3\/fc0\/589\/2a3fc0589762b042665c0779e4cef53e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s substitute s^-1 in our formula:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/62d\/3b4\/8f1\/62d3b48f16e6d68101ea03915851b122.png\" alt=\"\" title=\"\" width=\"1400\" height=\"178\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/62d\/3b4\/8f1\/62d3b48f16e6d68101ea03915851b122.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s simplify this part:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/843\/cc5\/1db\/843cc51db4d2205869ced5e8a87eab96.png\" alt=\"\" title=\"\" width=\"1400\" height=\"113\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/843\/cc5\/1db\/843cc51db4d2205869ced5e8a87eab96.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/09a\/a10\/798\/09aa10798caba01ae6b4be5310ce3802.png\" alt=\"\" title=\"\" width=\"1400\" height=\"209\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/09a\/a10\/798\/09aa10798caba01ae6b4be5310ce3802.png\"\/><figcaption><\/figcaption><\/figure>\n<p>Thus, if the signature is correct, the\u00a0<strong>x<\/strong>\u00a0coordinate of\u00a0<strong>C mod n<\/strong>\u00a0is equal to\u00a0<strong>r<\/strong>\u00a0(which is, by its definition, the same\u00a0<strong>x<\/strong>\u00a0coordinate of\u00a0<strong>G * k<\/strong>).<\/p>\n<h2>Secp256k1 standardized variables:<\/h2>\n<p>For the elliptic curve:<\/p>\n<ul>\n<li>\n<p>a=0<\/p>\n<\/li>\n<li>\n<p>b=7<\/p>\n<\/li>\n<li>\n<p>p=<code>115792089237316195423570985008687907853269984665640564039457584007908834671663<\/code><\/p>\n<\/li>\n<\/ul>\n<p>For point G:<\/p>\n<ul>\n<li>\n<p>x coordinate =\u00a0<code>55066263022277343669578718895168534326250603453777594175500187360389116729240<\/code><\/p>\n<\/li>\n<li>\n<p>y coordinate =\u00a0<code>32670510020758816978083085130507043184471273380659243275938904335757337482424<\/code><\/p>\n<\/li>\n<li>\n<p>Order n =\u00a0<code>115792089237316195423570985008687907852837564279074904382605163141518161494337<\/code><\/p>\n<\/li>\n<\/ul>\n<h3>Done! Now we know absolutely EVERYTHING essential!<\/h3>\n<p>The next part is going to be the easiest part for programmers. For everyone else, it\u2019s not necessary to follow. Just proceed to the Live Demo.<\/p>\n<h2>Part V: The implementation<\/h2>\n<blockquote>\n<p><em>This part is intended for programmers.<\/em><\/p>\n<\/blockquote>\n<p>The bottlenecks:<\/p>\n<ul>\n<li>\n<p>We need to be able to perform basic arithmetical operations on very large numbers. In programming, we can easily operate on large numbers using\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Arbitrary-precision_arithmetic\" rel=\"noopener noreferrer nofollow\"><u>bignum arithmetic<\/u><\/a>. So our programming language must support it, or we should use some external package to work with it. In the examples of this part, I will use\u00a0<strong>Python<\/strong>, which\u00a0<strong>supports bignum arithmetic out of the box<\/strong>. For the Live Demo (next part), I will use JavaScript, and there we will need the\u00a0<a href=\"https:\/\/www.npmjs.com\/package\/bignumber.js\" rel=\"noopener noreferrer nofollow\"><u>BigNumber.js package<\/u><\/a>.<\/p>\n<\/li>\n<li>\n<p>The other bottleneck that we will encounter is\u00a0<strong>finding the multiplicative inverse<\/strong>\u00a0of a huge number. Obviously, brute force is not going to work. The multiplicative inverse can be found by the\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Extended_Euclidean_algorithm\" rel=\"noopener noreferrer nofollow\"><strong><u>Extended Euclidean algorithm<\/u><\/strong><\/a><strong>, which has the complexity of O(log(n))<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<p>Python (3.8+) can find the multiplicative inverse out of the box with its built-in\u00a0<strong>pow<\/strong>\u00a0function:<\/p>\n<pre><code class=\"python\">def find_inverse(number, modulus): return pow(number, -1, modulus)<\/code><\/pre>\n<p><strong>If you need the actual implementation of the extended euclidean algorithm, check the code of my Live Demo!<\/strong><\/p>\n<h3>Let\u2019s start writing our code!<\/h3>\n<p>We need one simple thing related to the elliptic curve:\u00a0<strong>Point<\/strong>. Let\u2019s define a class\u00a0<strong>Point<\/strong>. In its constructor, we should make check whether the point lies on the curve:<\/p>\n<pre><code class=\"python\">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<\/code><\/pre>\n<p>We need to be able to <strong>compare two points<\/strong>, <strong>add them together<\/strong>, and <strong>multiply them by an integer.<\/strong><\/p>\n<p>Let\u2019s add a method to check if two points are equal:<\/p>\n<pre><code class=\"python\">def is_equal_to(self, point):         return self.x == point.x &amp; self.y == point.y <\/code><\/pre>\n<p>Now let\u2019s implement <strong>add<\/strong> method, which returns a new Point as the result of addition:<\/p>\n<pre><code class=\"python\">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)  <\/code><\/pre>\n<p><em>All the formulas are listed in PART III.<\/em><\/p>\n<p>Now let\u2019s implement the <strong>multiply<\/strong> method:<\/p>\n<p>The most straightforward implementation would be this:<\/p>\n<pre><code class=\"python\">def multiply(self, times):     point = self     for i in range(times - 1):         point = point.add(self)     return point <\/code><\/pre>\n<p>But let\u2019s say we need to multiply our point by a big number: 115792089237316195. Even if we had the speed of 1 billion additions per second, this would take <strong>3.6 years to calculate this point<\/strong>!<\/p>\n<p><strong>And this is not even a big number for us!<\/strong> Here is a big number:<\/p>\n<p><em>115792089237316195423570985008687907852837564279074904382605163141518161494337<\/em><\/p>\n<p>Calculating the point in this way would take <strong>billions of billions of billions of billions\u2026 of years<\/strong>!<\/p>\n<p>We can define that the efficiency of this algorithm above is O(n), which is of no use for our purposes. If you remember, there is an easy way to achieve <strong>O(log2(n))<\/strong> complexity by continuously doubling our point:<br \/>2P = P+P<br \/>4P = 2P + 2P<br \/>8P = 4P + 4P<br \/>16P = 8P + 8P<br \/>32P= 16P + 16P<br \/>64P = 32P + 32P<\/p>\n<p>And so <strong>log2(115792089237316195) =<\/strong> <strong>56<\/strong><\/p>\n<p><strong>log2(115792089237316195423570985008687907852837564279074904382605163141518161494337)<\/strong> = <strong>256<\/strong><\/p>\n<p>So we don\u2019t need billions of billions of billions\u2026 of years. <strong>We just need 256 operations to get to this large point<\/strong>!<\/p>\n<p>Just one moment: to efficiently multiply by values that are not a degree of 2, it\u2019s reasonable to store all the previous values, and then combine the results together.<\/p>\n<p>For example, if we need to get 100P, we can no longer double 64P. Neither we can add points one by one: potentially this would take billions of billions of years on larger numbers. What\u2019s reasonable to do instead, is:<\/p>\n<p>96P = 64P + 32P<br \/>100P = 96P + 4P<\/p>\n<p>So for that purpose, we need to store all the previous P\u2019s and afterward efficiently use them.<\/p>\n<p>So here is an efficient implementation:<\/p>\n<pre><code class=\"python\">def multiply(self, times):         current_point = self         current_coefficient = 1     pervious_points = []     while current_coefficient &amp;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 &amp;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 &amp;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  <\/code><\/pre>\n<p>Thus we\u2019ve got a super efficient implementation! And now we can perform all the needed operations on an elliptic curve.<\/p>\n<p>Let\u2019s define secp256k1:<\/p>\n<pre><code class=\"python\">secp256k1_curve_config = {     'a': 0,     'b': 7,     'p': 115792089237316195423570985008687907853269984665640564039457584007908834671663 } x = 55066263022277343669578718895168534326250603453777594175500187360389116729240 y = 32670510020758816978083085130507043184471273380659243275938904335757337482424 n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 g_point = Point(x, y, secp256k1_curve_config) <\/code><\/pre>\n<p>I\u2019m using only decimal numbers in our examples because they\u2019re intuitive for a human.<\/p>\n<h4>So far we\u2019ve implemented everything that we discussed prior to PART IV. Now let\u2019s implement the actual digital signature algorithm, described in PART IV.<\/h4>\n<p>Sign method of ECDSA:<\/p>\n<pre><code class=\"python\">def sign_message(message, private_key):     k = random.randint(1, n)     r_point = g_point.multiply(k)     r = r_point.x % n     if r == 0:         return sign_message(message, private_key)     k_inverse = find_inverse(k, n)     s = k_inverse * (message + r * private_key) % n     return r, s <\/code><\/pre>\n<p>Verify method of ECDSA:<\/p>\n<pre><code class=\"python\">def verify_signature(signature, message, public_key):     (r, s) = signature     s_inverse = find_inverse(s, n)     u = message * s_inverse % n     v = r * s_inverse % n     c_point = g_point.multiply(u).add(public_key.multiply(v))     return c_point.x == r <\/code><\/pre>\n<p>Let\u2019s pick some random number as our private key, for example, <strong>123456789012345<\/strong>.<\/p>\n<p>Let our message be 12345.<\/p>\n<p>Do you remember how to get <strong>PublicKey<\/strong> from <strong>PrivateKey<\/strong>?<\/p>\n<pre><code class=\"python\">private_key = 123456789012345  # any random integer public_key = g_point.multiply(private_key) message = 12345  # any integer <\/code><\/pre>\n<p>Now let\u2019s sign and try to verify:<\/p>\n<pre><code class=\"python\">signature = sign_message(message, private_key) print('Signature: ', signature) print('Is valid: ', verify_signature(signature, message, public_key)) <\/code><\/pre>\n<p>It works! You can try to corrupt the signature or the original message and make sure that our algorithm works properly.<\/p>\n<h4>Here is the complete code:<\/h4>\n<pre><code class=\"python\">import random   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)   def sign_message(message, private_key):     k = random.randint(1, n)     r_point = g_point.multiply(k)     r = r_point.x % n     if r == 0:         return sign_message(message, private_key)     k_inverse = find_inverse(k, n)     s = k_inverse * (message + r * private_key) % n     return r, s   def verify_signature(signature, message, public_key):     (r, s) = signature     s_inverse = find_inverse(s, n)     u = message * s_inverse % n     v = r * s_inverse % n     c_point = g_point.multiply(u).add(public_key.multiply(v))     return c_point.x == r   # test starts here private_key = 123456789012345  # any random integer public_key = g_point.multiply(private_key) message = 12345  # any integer  signature = sign_message(message, private_key) print('Signature: ', signature) print('Is valid: ', verify_signature(signature, message, public_key))<\/code><\/pre>\n<h4>So the implementation of the entire ECDSA algorithm took just 100 lines of code! And it\u2019s perfectly working. This is absolutely the same algorithm as the one used in Bitcoin!<\/h4>\n<h2>PartVI: Live Demo<\/h2>\n<p>As I promised at the beginning of this article, here is the live demo using <strong>only<\/strong> the concepts and formulas described in the article. Just a couple of notes:<\/p>\n<ul>\n<li>\n<p>Initially, we could only sign integer messages. But in the demo, you can <strong>choose<\/strong> to apply a <strong>hash<\/strong> function (<a href=\"https:\/\/en.wikipedia.org\/wiki\/SHA-2\" rel=\"noopener noreferrer nofollow\"><strong>sha256<\/strong><\/a>) to your message. Thanks to it, a message can be a string.<\/p>\n<\/li>\n<li>\n<p>Bitcoin uses slightly different formats of <a href=\"https:\/\/river.com\/learn\/terms\/s\/sec-format\/\" rel=\"noopener noreferrer nofollow\">public keys<\/a> and <a href=\"https:\/\/river.com\/learn\/terms\/d\/der\/\" rel=\"noopener noreferrer nofollow\">signatures<\/a>.<\/p>\n<\/li>\n<li>\n<p><strong>Never<\/strong> use it in a production environment! <strong>It is not safe<\/strong>. For production, you must <strong>only<\/strong> use <a href=\"https:\/\/www.openssl.org\/\" rel=\"noopener noreferrer nofollow\">well-tested solutions<\/a>.<\/p>\n<\/li>\n<\/ul>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/633ee3731f2ba68d76c3e99f\" data-style=\"\" id=\"633ee3731f2ba68d76c3e99f\" width=\"\"><\/div>\n<p>I hope this article was very useful for you. I did my best to make it useful. Feel free to share it with friends or use any piece of it anywhere. Just please leave a link to the original article.<\/p>\n<p>Feel free to contact me and ask questions:<\/p>\n<p><a href=\"mailto:exemak@gmail.com\" rel=\"noopener noreferrer nofollow\">exemak@gmail.com<\/a><\/p>\n<p><a href=\"http:\/\/t.me\/exemak\" rel=\"noopener noreferrer nofollow\">t.me\/exemak<\/a><\/p>\n<p>Mikhail Karavaev<\/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\/692072\/\"> https:\/\/habr.com\/ru\/articles\/692072\/<\/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>Elliptic curves are very simple.\u00a0The Elliptic Curves Digital Signature Algorithm (ECDSA), which works on top of their properties, is used in most blockchains like Bitcoin, Ethereum, etc., and is even simpler. But it\u2019s challenging to find a good explanation on the internet and build all the pieces together. But here it is! In this article, we will.<\/p>\n<p>We will go through all the concepts needed to understand and implement this algorithm \u2014 one by one. By the end of this article, we will have a fully functioning demo\u00a0<strong>from scratch<\/strong>, which can extract the\u00a0<strong>public key<\/strong>\u00a0from the\u00a0<strong>private key<\/strong>,\u00a0<strong>sign<\/strong>\u00a0a message, and\u00a0<strong>verify<\/strong>\u00a0that the signature is correct. This implementation will\u00a0<strong>only<\/strong>\u00a0use the concepts described in this article. Moreover, it will take less than 100 lines of code.<\/p>\n<p>This article is targeted mainly at developers like myself, who want to finally understand ECDSA, but it will also be very useful for everyone else. It requires knowing no more than middle school math.<\/p>\n<p>I highly recommend following it step by step. If you want, you can grab a piece of paper and a pen and repeat all the steps in this article. It would be even better! If you\u2019re not a programmer, you can ignore some pieces of code. If you are, I recommend re-writing the code on your own and practicing!<\/p>\n<p>The article consists of 6 parts; each part uses the concepts of the previous parts (except part 2):<\/p>\n<ul>\n<li>\n<p>I: The essentials of elliptic curves<\/p>\n<\/li>\n<li>\n<p>II: The essentials of finite fields<\/p>\n<\/li>\n<li>\n<p>III: Elliptic curves over finite fields<\/p>\n<\/li>\n<li>\n<p>IV: Practical use of it: ECDSA<\/p>\n<\/li>\n<li>\n<p>V: The implementation<\/p>\n<\/li>\n<li>\n<p>VI: Live Demo<\/p>\n<\/li>\n<\/ul>\n<p>Let\u2019s start here!<\/p>\n<h2>PART I: The Essentials of Elliptic Curves<\/h2>\n<p>We\u2019re all probably familiar with all those graphs on coordinate grids where the\u00a0<strong>y<\/strong>\u00a0variable somehow depends on\u00a0<strong>x<\/strong>. For example,\u00a0<strong>y = x<\/strong>,\u00a0<strong>y = x\u00b2<\/strong>, and so on. Most probably, we all have some experience with it. Let\u2019s look at them:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>The equation for an elliptic curve is not much different!<\/strong>\u00a0It has the form of\u00a0<strong>y\u00b2 = x\u00b3 + ax + b<\/strong>. What are\u00a0<strong>a<\/strong>\u00a0and\u00a0<strong>b<\/strong>? Just some arbitrary constants. Let\u2019s see how it looks with\u00a0<strong>a = 0<\/strong>,\u00a0<strong>b = 7<\/strong>, just like in the Bitcoin curve:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h2>It has the following three super important properties upon which everything works:<\/h2>\n<blockquote>\n<p><em>This is where it may get hard to follow and understand\u00a0<\/em><a href=\"https:\/\/www.youtube.com\/watch?v=6eZQu120A80\" rel=\"noopener noreferrer nofollow\"><em><u>why<\/u><\/em><\/a><em>. You may even think this is something incoherent and irrelevant. But please trust me. These properties will lead us to a very amazing result! But now let\u2019s pretend that we\u2019re just having fun without a purpose.<\/em><\/p>\n<\/blockquote>\n<ol>\n<li>\n<p>The elliptic curve is symmetric along the\u00a0<strong>x-axis<em>. <\/em><\/strong>It means that for any point on the curve A, we can get its mirror point, called -A, by simply mirroring its y coordinate:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<ol start=\"2\">\n<li>\n<p> If we draw a line through\u00a0<strong>any of two points not lying on a vertical line<\/strong>, it will\u00a0<a href=\"https:\/\/www.youtube.com\/watch?v=6eZQu120A80\" rel=\"noopener noreferrer nofollow\"><strong><u>intersect<\/u><\/strong><\/a>\u00a0the\u00a0<strong>curve at exactly one more point<\/strong>! Let\u2019s draw a line through the\u00a0<strong>A<\/strong>\u00a0and\u00a0<strong>B<\/strong>\u00a0points and call the third point\u00a0<strong>\u2014 C<\/strong>. Then, let\u2019s reflect it to get the point\u00a0<strong>C<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><em>Another example:<\/em><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>This C point is called the sum of A and B. So A + B = C.<\/strong><\/p>\n<ol start=\"3\">\n<li>\n<p>If we draw a\u00a0<strong>tangent<\/strong>\u00a0<strong>line<\/strong>\u00a0through any point\u00a0<strong>A<\/strong>\u00a0lying on a curve, it will intersect the curve at\u00a0<strong>exactly one point<\/strong>. We will call this point\u00a0<strong>-2A.<\/strong>\u00a0We already know how to get\u00a0<strong>2A<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>The easiest way to think about a tangent line is to imagine it intersecting\u00a0<strong>A<\/strong>\u00a0point twice. As if it intersects the curve not at two points but three: A, A, -2A.<\/p>\n<h3>That\u2019s it! We defined three mathematical operations on the elliptic curve: multiplying a point by -1, adding two points together, and doubling a point.<\/h3>\n<h4>And here is where the algebra of elliptic curves starts working.<\/h4>\n<p>Now we have the following picture with points\u00a0<strong>A<\/strong>,\u00a0<strong>2A<\/strong>, and\u00a0<strong>-2A<\/strong>:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s draw a line through\u00a0<strong>A<\/strong>\u00a0and\u00a0<strong>2A<\/strong>. The third point that we\u2019ll get is\u00a0<strong>-3A<\/strong>. Then just reflect it to get\u00a0<strong>3A<\/strong>:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>You probably don\u2019t yet understand why we\u2019re doing all of it. Just look at one more step. What if we try drawing a line between\u00a0<strong>3A<\/strong>\u00a0and\u00a0<strong>-2A<\/strong>?<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>Do you see the magic?<\/strong>\u00a0By drawing a line between\u00a0<strong>3A<\/strong>\u00a0and\u00a0<strong>-2A<\/strong>\u00a0we\u2019re getting the\u00a0<strong>-A<\/strong>\u00a0point, which is the reflection of our original\u00a0<strong>A<\/strong>\u00a0point along the x-axis!<\/p>\n<h3>What we just defined in the three clauses above, is the algebra of elliptic curves.<\/h3>\n<p>Just try to understand the power of those three operations: essentially now we can perform operations on the points lying on a curve\u00a0<strong>as if they\u2019re not points, but just numbers<\/strong>!<\/p>\n<p>What we\u00a0<strong>can<\/strong>\u00a0do with points on a curve:<\/p>\n<ul>\n<li>\n<p>Addition of two points\u00a0<strong>(A + B)<\/strong><\/p>\n<\/li>\n<li>\n<p>Subtraction of two points\u00a0<strong>A \u2014 B<\/strong>\u00a0=\u00a0<strong>(A + (-B))<\/strong><\/p>\n<\/li>\n<li>\n<p>Doubling of a point (multiplication by two)\u00a0<strong>2A<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>Multiplying by any integer (by combining the previous operations together, we can get any integer * Point)<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>What we\u00a0<strong>can\u2019t<\/strong>\u00a0do:<\/p>\n<ul>\n<li>\n<p>Multiplication of two points<\/p>\n<\/li>\n<li>\n<p>Division of a point over another point<\/p>\n<\/li>\n<li>\n<p><strong>Division of a point over a scalar value<\/strong><\/p>\n<\/li>\n<\/ul>\n<p>For example, to get\u00a0<strong>10A<\/strong>:<br \/><em>2A = A + A<br \/>4A = 2A + 2A<br \/>8A = 4A + 4A<br \/>10A = 8A + 2A<\/em><\/p>\n<p>It\u2019s also good to notice that the calculation may be performed in a logarithmic amount of operations. So the approximate amount of operations needed for calculating\u00a0<strong>n * Point<\/strong>\u00a0is\u00a0<strong>O(log2(n))<\/strong>!<\/p>\n<h3>Eventually, we can multiply a point by any integer, but there is no way to get the integer back! This is the gist of it! And this is what makes the elliptic curves very good for cryptography. And it works for infinitely large numbers.<\/h3>\n<h3>The only drawback, for now, is the need to draw it. But of course, there are mathematical formulas for reflecting a point, for addition, and for doubling a point:<\/h3>\n<ol>\n<li>\n<p><strong>Multiplying the point by -1<\/strong>. If we have a point <strong>A(x, y),<\/strong> we can easily get <strong>-A<\/strong> by multiplying its <strong>y<\/strong> coordinate by <strong>-1.<\/strong> -A(x, -y). <strong>Example: <br \/>-1 * A(2, 2) \u2192 -A(2, -2) <br \/>-1 * A(1, -1) \u2192 -A(1, 1) <br \/>-1 * A(5, 8) \u2192 -A(5, -8) <br \/>-1 * A(5, -8) \u2192 -A(5, 8)<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>Adding two points together.<\/strong> We can add two points together, but with one condition: they should not lie on a vertical line (their x coordinates should not be equal). This is the formula for adding <strong>A<\/strong> and <strong>B (A + B = C)<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<ol start=\"3\">\n<li>\n<p><strong>Adding a point to itself<\/strong>\u00a0(multiplying a point by 2). This is a very similar operation to the addition of two points but slightly different:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>That\u2019s it! Time to practice!<\/h3>\n<p>Let\u2019s try adding A and B here (let\u2019s use approximation to 3 points after a comma):<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>According to the formula defined above for adding two points,<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Now let\u2019s find our point\u00a0<strong>C<\/strong>\u00a0graphically:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>It works!<\/strong>\u00a0Yes, with a minor proximity issue, because of rounding. But it works! For better understanding, I recommend you try to perform all those operations on your own.<\/p>\n<h3>This was all we needed to know about elliptic curves and the operations on them that we need to be able to perform!<\/h3>\n<p>Everything is fine, but we need a couple more properties for building a cryptography system.<\/p>\n<h2>Part II: Finite fields<\/h2>\n<p>We don\u2019t need to study everything about\u00a0<a href=\"http:\/\/web.stanford.edu\/~marykw\/classes\/CS250_W19\/readings\/Forney_Introduction_to_Finite_Fields.pdf\" rel=\"noopener noreferrer nofollow\"><u>finite fields<\/u><\/a>. All we need here is to understand a couple of essential properties to move on and be able to operate on a certain \u201calgebra\u201d of finite fields.<\/p>\n<p>Have you heard of the\u00a0<strong>modulus<\/strong>\u00a0operation? If you\u2019re a programmer, you probably did. This is just a\u00a0<strong>reminder of division<\/strong>, and in programming languages, it\u2019s usually expressed as a\u00a0<strong>%<\/strong>\u00a0(or\u00a0<strong>mod<\/strong>) operator. For example:<\/p>\n<p><strong>2 mod 11 = 2<br \/>10 mod 11 = 10<br \/>11 mod 11 = 0<br \/>13 mod 11 = 2<br \/>14 mod 11 = 3<\/strong><\/p>\n<p>If we try numbers from\u00a0<strong>0<\/strong>\u00a0to\u00a0<strong>33 mod 11<\/strong>, we will get these numbers:<strong>0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0<\/strong><\/p>\n<p><em>It works\u00a0<\/em><strong><em>like a clock<\/em><\/strong><em>.\u00a0<\/em><code>We can call it a finite field of order 11<\/code>.<\/p>\n<h3>We need to know just four properties:<\/h3>\n<ol>\n<li>\n<p><strong>The order of multiplication doesn\u2019t matter. <br \/>a * b * c<\/strong>\u00a0mod n\u00a0<strong>is the same as<\/strong>\u00a0(<strong>a<\/strong>\u00a0mod n) * (<strong>b<\/strong>\u00a0mod n) * (<strong>c<\/strong>\u00a0mod n) mod n,\u00a0<strong>which is the same as<\/strong>\u00a0(<strong>a * b<\/strong>\u00a0mod n) * <strong>c<\/strong>\u00a0mod n.<br \/>Example:<br \/><strong>6 * 7 * 8<\/strong>\u00a0mod 11 =\u00a0<strong>336<\/strong>\u00a0mod 11 =\u00a0<strong>6, same as:<\/strong>\u00a0<br \/>(<strong>6 * 7<\/strong>\u00a0mod 11) \u00a0<strong>8<\/strong>\u00a0mod 11 = (<strong>42<\/strong>\u00a0mod 11) \u00a0<strong>9<\/strong>\u00a0mod 11 =\u00a0<strong>9 * 8<\/strong>\u00a0mod 11 =\u00a0<strong>72<\/strong>\u00a0mod 11 =\u00a0<strong>6<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>Negative number<\/strong>\u00a0<strong>mod n is the<\/strong>\u00a0<strong>same as n-(|negative number| mod n<\/strong>). <br \/>Examples:<br \/>1)\u00a0<strong>-4 mod 11<\/strong>\u00a0= 11-(4 mod 11) =\u00a0<strong>11\u20134 = 7<br \/><\/strong>2)<strong> -7 mod 11<\/strong>\u00a0= 11 \u2014 (7 mod 11) =\u00a0<strong>11\u20137 = 4<br \/><\/strong>3)<strong>\u00a0-9 mod 11<\/strong>\u00a0= 11 \u2014 (9 mod 11) =\u00a0<strong>11\u20139 = 2<br \/><\/strong>4)\u00a0<strong>-2 mod 11<\/strong>\u00a0= 11 \u2014 (2 mod 11) =\u00a0<strong>11\u20132 = 9<br \/><\/strong>5)<strong>\u00a0-13 mod 11<\/strong>\u00a0= 11 \u2014 (13 mod 11) =\u00a0<strong>11\u20132 = 9<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u201c<\/strong><a href=\"https:\/\/en.wikipedia.org\/wiki\/Multiplicative_inverse\" rel=\"noopener noreferrer nofollow\"><strong><u>Multiplicative inverse<\/u><\/strong><\/a><strong>\u201d: for any a, there is a number b, such as ab mod n = 1.<br \/>If a * b mod 11 = 1,<\/strong>\u00a0<strong>a<\/strong>\u00a0is called the\u00a0<strong>multiplicative inverse of b<\/strong>\u00a0<strong>modulo<\/strong>\u00a0<strong>n<\/strong>, and\u00a0<strong>vice versa<\/strong>:\u00a0<strong>b<\/strong>\u00a0is called the multiplicative inverse of\u00a0<strong>a<\/strong>\u00a0modulo n.<br \/>Examples:<br \/>1)\u00a0<strong>5 * x mod 11<\/strong>\u00a0= 1. Let\u2019s try values for x one by one, and we will find out\u00a0<strong>x = 9,\u00a0<\/strong>because 5 * 9 = 45, 45 mod 11 = 1. So\u00a0<strong>9\u00a0<\/strong>is the<strong>\u00a0multiplicative inverse of 5 modulo 11<\/strong>.<br \/>2)\u00a0<strong>7 * x mod 11 = 1<\/strong>. Let\u2019s try our brute force again, and we will find out\u00a0<strong>x = 8<\/strong>. 8 is the multiplicative inverse of 7 modulo 11.<br \/>3)\u00a0<strong>10 * x mod 11 = 1. x = 10.<\/strong>\u00a0So 10 is the multiplicative inverse of 10 modulo 11.<\/p>\n<p>Usually, the multiplicative inverse is found by the\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Extended_Euclidean_algorithm\" rel=\"noopener noreferrer nofollow\"><u>extended Euclidean algorithm<\/u><\/a>, but it\u2019s a matter of a separate article. So, for now, let\u2019s just use brute force. Also,\u00a0<strong>n<\/strong>\u00a0must be a prime number!<\/p>\n<\/li>\n<li>\n<p><strong>The division is the same operation as multiplication by the multiplicative inverse!<\/strong>\u00a0The last and most important property:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>So, when we need to deal with division mod n, we can easily calculate it. Let\u2019s see an example:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong>That\u2019s it! Now we know how to operate on finite fields \u201calgebra\u201d.<\/strong><\/p>\n<h2>Part III: Elliptic curves over finite fields<\/h2>\n<p>Here\u2019s where it becomes less obvious and a little harder to understand.\u00a0<strong>But this is exactly how elliptic curves are used in cryptography<\/strong>. What we need to do is exactly what is said in the title: put our elliptic curve over a finite field.<\/p>\n<p>So, here is how our formula changes:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Everything is the same as in the original formula but now both parts of the equation are now under the\u00a0<strong>modulo p<\/strong>.<\/p>\n<p>Let\u2019s use the elliptic curve with the following configuration for our examples:<\/p>\n<ul>\n<li>\n<p><em>a = 0<\/em><\/p>\n<\/li>\n<li>\n<p><em>b = 7<\/em><\/p>\n<\/li>\n<li>\n<p><em>p = 11<\/em><\/p>\n<\/li>\n<\/ul>\n<p>Let\u2019s find all the points on this curve running this code:<\/p>\n<pre><code class=\"javascript\">const a = 0; const b = 7; const p = 11;   for (let x = 0; x &lt;= p; x ++) {   for (let y = 0; y &lt;= p; y ++) {     if (y**2 % p === (x**3 + a * x + b) % p) {       console.log(`(${x}, ${y})`);     }   } }<\/code><\/pre>\n<p>It\u2019s\u00a0<strong>javascript<\/strong>, so you can run it even in the browser.<\/p>\n<p>Here is the result: <strong>(2, 2), (2, 9), (3, 1), (3, 10), (4, 4), (4, 7), (5, 0), (5,11), (6, 5), (6, 6), (7, 3), (7, 8)<\/strong><\/p>\n<p>Let\u2019s see what it looks like on a coordinate grid:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>Let\u2019s try a=0, b=7, p=23:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><strong><em>Doesn\u2019t look like anything, right? No distinguishable shape.<\/em><\/strong><\/p>\n<h3>But! What turns out is that it preserves all the properties and formulas of the \u201coriginal\u201d elliptic curve!<\/h3>\n<p>S<\/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-397172","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/397172","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=397172"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/397172\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=397172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=397172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=397172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}