
Bitcoin in a nutshell - Cryptography
One of the reasons why Bitcoin continues to attract so much attention is its exceptional “math”. Satoshi Nakamoto managed to create a system that is able to function in the complete absence of trust between its participants. All interactions are based on rigorous mathematics, no human factor - that was the idea of revolution, and not in a peer-to-peer network, as many people think. Therefore, I decided to devote the first chapter to the mathematical foundations of Bitcoin.
Below I will try to explain to you the most basic things - elliptic curves, ECC, private / public keys and so on. If possible, I will illustrate my words with code examples, mainly in Python 2.7, if something is not clear - ask in the comments.

As I said above, cryptography is a fundamental part of Bitcoin. Without it, nothing would have worked at all, so you need to start from here.
Bitcoin uses the so-called cryptography on elliptic curves ( Elliptic curve cryptography, ECC ). It is based on some special function - an elliptic curve (not to be confused with an ellipse). What this function is and why it is so remarkable I will tell further.
Если на пальцах, то эллиптическая кривая — это внешне довольно простая функция, как правило, записываемая в виде так называемой формы Вейерштрасса:
В зависимости от значений параметров
и
, график данной функции может выглядеть по разному:

Скрипт для отрисовки графика на Python:
If you believe the wiki, then for the first time this function was lit up in the writings of Diophantus, and later, in the 17th century, Newton himself became interested in it. His research led in many respects to the formulas for adding points on an elliptic curve, which we will now meet. Hereinafter, we will consider some elliptic curve
.
Let there be two points
. Their sum is called the point
, which in the simplest case is defined as follows: we draw a line through
and
- it intersects the curve
at a single point, we call it
. Changing the
coordinate of the point
to the opposite sign, we get a point
, which we will call the sum
and
, that is
.

I consider it necessary to note that we are just introducing such an addition operation - if you add up the points in the usual sense, that is, add up the corresponding coordinates, you will get a completely different point
, which most likely has nothing to do with
or
and does not lie on the curve at all
.
The most quick-witted ones have already asked themselves - what will happen if, for example, a straight line is drawn through two points having the coordinates of the view
and
that is, a straight line passing through them is parallel to the ordinate axis (third frame in the picture below).

It is easy to see that in this case there is no third intersection with the curve
that we called
. To avoid this mishap, we introduce the so-called point at infinity (point of infinity), usually denoted by
or just
like the picture. And we will say that in the absence of intersection
.
Of particular interest to us is the case when we want to add a point to itself (2 frames, a point
). In this case, we simply draw a tangent to the point
and reflect the resulting intersection point with respect to
.
Now, with a flick of the wrist, you can enter the operation of multiplying a point by some
number. As a result, we get a new point
, that is,
time. Everything should become clear with the picture:

The ECC is used in exactly the same curve, only considered over a finite field
- prime. I.e
%0A)
All of these properties (addition, multiplication, point at infinity) for such a function remain valid, although if you try to draw this function, it will only resemble a familiar elliptic curve remotely (at best). And the concept of “tangent to a function at a point” generally loses all meaning, but that's okay. Here is an example of a function
for
:

But for
, there is generally an almost chaotic set of points. The only thing that still reminds of the origin of this graph is the symmetry about the axis
.

PS If you are interested, as in the case of a curve above a finite field, calculate the coordinates of a point
, knowing the coordinates
and
- you can scroll through“An Introduction to Bitcoin, Elliptic Curves and the Mathematics of ECDSA” by N. Mistry , everything is detailed there, it’s enough to know math at the 8th grade level.
PPS In case my examples did not satisfy your inquiring mind, here is a site for drawing curves of all sorts, experiment.
Returning to Bitcoin, it uses the SECP256k1 curve . It has the form
and is considered above the field
, where
is a very large prime number, namely
.
The so-called base point is also defined for SECP256k1 , it is also the generator point - it is just a point, usually indicated
, lying on this curve. It is needed to create a public key, which will be described below.
A simple example: using Python, check if the point of the
curve belongs to SECP256k1
The general idea is this: Alice wants to transfer 1 BTC to Bob. To do this, she creates a message like:
Then Alice takes her private key (for now, you can assume that this is a number known only to Alice), a message hash, and a view function
. At the output, she receives the signature of her message - in the case of ECDSA it will be a pair of integers, for other algorithms the signature may look different. After that, she sends all network participants an initial message, signature and her public key.
As a result, each Vasya will be able to take this trinity, a view function,
and check whether the owner of the private key actually signed this message or not. And if everyone inside the network knows what
belongs to Alice, then you can understand whether she sent the money or if someone is trying to do it on her behalf.

Moreover, suppose that there was a person standing between Alice and the rest of the network. Let him intercept Alice's message and change something in it, literally 1 bit out of a billion. But even in this case, checking the signature for validity
will show that the message has been changed.
This is a very important feature for Bitcoin, because the network is distributed . We cannot know in advance who our transaction will get with the demand to transfer 1000 BTC. But he will not be able to change it (for example, indicate his address as the recipient), because the transaction is signed by your private key, and the rest of the network participants will immediately understand that something is wrong here.
AHTUNG!In fact, the process is quite different from the above. Here I just showed on my fingers what an electronic digital signature is and why it is needed. The real algorithm is described in the chapter “Bitcoin in a nutshell - Transactions” .
A private key is a fairly general term and various types of private keys can be used in various electronic signature algorithms.
As you may have noticed, Bitcoin uses the ECDSA algorithm - in its case, the private key is some kind of 256-bit integer, that is, the most common integer from
to
. Technically, even the number 123456 will be a valid private key, but very soon you will find out that your coins “belong” to you right up to the moment the attacker has your private key, and values like 123456 are very easy to find.
It is important to note that today it is impossible to sort through all the keys due to the fact that
this is a fantastically large number.
We will try to imagine it: according to this article , there are a little fewer
grains of sand on the whole Earth . We will use that
, that is,
grains of sand. And all the addresses we have
, approximately
.
So, we can take all the sand on Earth, turn every grain of sand into a new Earth, in the resulting pile of planets, turn every grain of sand on every planet into a new Earth, and the total number of grains of sand will still be orders of magnitude less than the number of possible private keys.
For the same reason, when creating a private key, most Bitcoin clients simply take 256 random bits - the probability of collision is extremely small.
Let
- our private key,
- base point, then the public key
. That is, in fact, the public key is a certain point lying on the curve SECP256k1.
Two important nuances. First, it is easy to see that the operation of obtaining a public key is uniquely determined, that is, a single private key always corresponds to a single public key. Secondly, the reverse operation is computationally difficult and, in the general case, obtaining a private key from a public one is possible only by exhaustive search of the first.
Below you will find out that exactly the same connection exists between the public key and the address, but the whole point is that the hash functions are irreversible.

To compile and run, we use (pre-installing libbitcoin):
You can see that the formats of the public keys in the first and second examples are different (at least in length), I will discuss this in more detail below.
This encoding will be met by us constantly throughout the book, so you should understand how it works and why it is needed at all.
Its essence is to write down the sequence of bytes in the most readable format as briefly as possible and at the same time make the probability of possible typos even less. I think you yourself understand that in the case of Bitcoin, security is never superfluous. One wrong character and money will go to the address, keys to which most likely no one will ever find. Here is a comment on this encoding from in base58.h :
The brevity of recording is easiest to implement using the fairly common Base64 encoding , that is, using the base 64 number system, where numbers
The first difference with Base58Check is that characters are removed
The second difference is the same check . At the end of the line, checksum is added again - the first 4 bytes

The most obvious way to store a private key is to write 256 bits as a bunch of zeros and ones. But, probably, any technically competent person understands that it will be much easier to present the same sequence in the form of 32 bytes, where each byte corresponds to two characters in a hexadecimal notation. Let me remind you that in this case, numbers
Another more advanced format is WIF ( Wallet Import Format ). It is built quite simply:
Just in case, let me remind you that the public key is just a point on the line SECP256k1. The first and most common variant of its recording is an uncompressed format, 32 bytes each for X and Y coordinates. To avoid confusion, the prefix of
However, as the name suggests, this is not the best way to store a public key.
You will be surprised, but the second format is called compressed . Its essence is as follows: a public key is a point on a curve, that is, a pair of numbers satisfying the equation
. So it is possible to write down only the X coordinate, and if we need the Y coordinate, we simply solve the equation. Thus, we reduce the size of the public key by almost 50%!
The only caveat is that if the point lies on the curve, then obviously there are two solutions to this equation for its X coordinate (look at the graphs above if in doubt). Usually we would just save the sign for the Y coordinate, but when it comes to functions over a finite field, we need to use the following property:if there are solutions to the equation for the X coordinate, then one of the points will have an even Y coordinate, and the second will have an odd one (again, you can see for yourself).
In the first case, the prefix is used

As already mentioned, the address is obtained from the public key in a unique way. Moreover, it is impossible to carry out the reverse operation, since cryptographically strong hash functions are used - RIPEMD160 and SHA256 . Here is the algorithm for translating the public key to the address:
I don’t think you need to know the technical details of exactly how ECDSA signs and checks messages, anyway you will use ready-made libraries everywhere. The main thing is that you have a common understanding of why this is necessary, but if you are still interested, look through the Layman's Guide to Elliptic Curve Digital Signatures , there is a beautiful visualization of the whole process below, you can try it yourself.
That's it for me, the next chapter: Bitcoin in a nutshell - Transaction .
Below I will try to explain to you the most basic things - elliptic curves, ECC, private / public keys and so on. If possible, I will illustrate my words with code examples, mainly in Python 2.7, if something is not clear - ask in the comments.

Book
- Bitcoin in a nutshell - Cryptography
- Bitcoin in a nutshell - Transaction
- Bitcoin in a nutshell - Protocol
- Bitcoin in a nutshell - Blockchain
- Bitcoin in a nutshell - mining
Table of content
- Introduction
- Elliptic curve
- Digital signature
- Private key
- Public key
- Formats & address
- Sign
- Verify
- Formats
- Links
Introduction
As I said above, cryptography is a fundamental part of Bitcoin. Without it, nothing would have worked at all, so you need to start from here.
Bitcoin uses the so-called cryptography on elliptic curves ( Elliptic curve cryptography, ECC ). It is based on some special function - an elliptic curve (not to be confused with an ellipse). What this function is and why it is so remarkable I will tell further.
Elliptic curve
Эллипти́ческая крива́я над полем— неособая кубическая кривая на проективной плоскости над
(алгебраическим замыканием поля
), задаваемая уравнением 3-й степени с коэффициентами из поля
и «точкой на бесконечности» — Wikipedia
Если на пальцах, то эллиптическая кривая — это внешне довольно простая функция, как правило, записываемая в виде так называемой формы Вейерштрасса:
В зависимости от значений параметров

Скрипт для отрисовки графика на Python:
import numpy as np
import matplotlib.pyplot as plt
def main():
a = -1
b = 1
y, x = np.ogrid[-5:5:100j, -5:5:100j]
plt.contour(x.ravel(), y.ravel(), pow(y, 2) - pow(x, 3) - x * a - b, [0])
plt.grid()
plt.show()
if __name__ == '__main__':
main()
If you believe the wiki, then for the first time this function was lit up in the writings of Diophantus, and later, in the 17th century, Newton himself became interested in it. His research led in many respects to the formulas for adding points on an elliptic curve, which we will now meet. Hereinafter, we will consider some elliptic curve
Let there be two points

I consider it necessary to note that we are just introducing such an addition operation - if you add up the points in the usual sense, that is, add up the corresponding coordinates, you will get a completely different point
The most quick-witted ones have already asked themselves - what will happen if, for example, a straight line is drawn through two points having the coordinates of the view

It is easy to see that in this case there is no third intersection with the curve
Of particular interest to us is the case when we want to add a point to itself (2 frames, a point
Now, with a flick of the wrist, you can enter the operation of multiplying a point by some

Elliptic curve over a finite field
The ECC is used in exactly the same curve, only considered over a finite field
All of these properties (addition, multiplication, point at infinity) for such a function remain valid, although if you try to draw this function, it will only resemble a familiar elliptic curve remotely (at best). And the concept of “tangent to a function at a point” generally loses all meaning, but that's okay. Here is an example of a function

But for

PS If you are interested, as in the case of a curve above a finite field, calculate the coordinates of a point
PPS In case my examples did not satisfy your inquiring mind, here is a site for drawing curves of all sorts, experiment.
SECP256k1
Returning to Bitcoin, it uses the SECP256k1 curve . It has the form
The so-called base point is also defined for SECP256k1 , it is also the generator point - it is just a point, usually indicated
A simple example: using Python, check if the point of the
>>> p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
>>> x = 55066263022277343669578718895168534326250603453777594175500187360389116729240
>>> y = 32670510020758816978083085130507043184471273380659243275938904335757337482424
>>> (x ** 3 + 7) % p == y**2 % p
True
Digital signature
Electronic signature (EDS), Electronic digital signature (EDS) - the details of an electronic document obtained as a result of cryptographic conversion of information using a private signature key and allowing to verify the absence of information distortion in an electronic document from the moment the signature was generated (integrity), the signature belongs to the owner of the key certificate signatures (authorship), and in case of successful verification confirm the fact of signing an electronic document (non-repudiation) - Wikipedia
The general idea is this: Alice wants to transfer 1 BTC to Bob. To do this, she creates a message like:
{
"from" : 1FXySbm7jpJfHEJRjSNPPUqnpRTcSuS8aN, // Alice's address
"to" : 1Eqm3z1yu6D4Y1c1LXKqReqo1gvZNrmfvN, // Bob's address
"amount" : 1 // Send 1 BTC
}
Then Alice takes her private key (for now, you can assume that this is a number known only to Alice), a message hash, and a view function
As a result, each Vasya will be able to take this trinity, a view function,

Moreover, suppose that there was a person standing between Alice and the rest of the network. Let him intercept Alice's message and change something in it, literally 1 bit out of a billion. But even in this case, checking the signature for validity
This is a very important feature for Bitcoin, because the network is distributed . We cannot know in advance who our transaction will get with the demand to transfer 1000 BTC. But he will not be able to change it (for example, indicate his address as the recipient), because the transaction is signed by your private key, and the rest of the network participants will immediately understand that something is wrong here.
AHTUNG!In fact, the process is quite different from the above. Here I just showed on my fingers what an electronic digital signature is and why it is needed. The real algorithm is described in the chapter “Bitcoin in a nutshell - Transactions” .
Private key
A private key is a fairly general term and various types of private keys can be used in various electronic signature algorithms.
As you may have noticed, Bitcoin uses the ECDSA algorithm - in its case, the private key is some kind of 256-bit integer, that is, the most common integer from
It is important to note that today it is impossible to sort through all the keys due to the fact that
We will try to imagine it: according to this article , there are a little fewer
So, we can take all the sand on Earth, turn every grain of sand into a new Earth, in the resulting pile of planets, turn every grain of sand on every planet into a new Earth, and the total number of grains of sand will still be orders of magnitude less than the number of possible private keys.
For the same reason, when creating a private key, most Bitcoin clients simply take 256 random bits - the probability of collision is extremely small.
Python
>>> import random
>>> private_key = ''.join(['%x' % random.randrange(16) for x in range(0, 64)])
>>> private_key
'9ceb87fc34ec40408fd8ab3fa81a93f7b4ebd40bba7811ebef7cbc80252a9815'
>>> # or
>>> import os
>>> private_key = os.urandom(32).encode('hex')
>>> private_key
'0a56184c7a383d8bcce0c78e6e7a4b4b161b2f80a126caa48bde823a4625521f'
Python, ECDSA
>>> import binascii
>>> import ecdsa # sudo pip install ecdsa
>>> private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
>>> binascii.hexlify(private_key.to_string()).decode('ascii').upper()
u'CE47C04A097522D33B4B003B25DD7E8D7945EA52FA8931FD9AA55B315A39DC62'
Bitcoin-cli
$ bitcoin-cli getnewaddress
14RVpC4su4PzSafjCKVWP2YBHv3f6zNf6U
$ bitcoin-cli dumpprivkey 14RVpC4su4PzSafjCKVWP2YBHv3f6zNf6U
L3SPdkFWMnFyDGyV3vkCjroGi4zfD59Wsc5CHdB1LirjN6s2vii9
Public key
Let
Two important nuances. First, it is easy to see that the operation of obtaining a public key is uniquely determined, that is, a single private key always corresponds to a single public key. Secondly, the reverse operation is computationally difficult and, in the general case, obtaining a private key from a public one is possible only by exhaustive search of the first.
Below you will find out that exactly the same connection exists between the public key and the address, but the whole point is that the hash functions are irreversible.

Python, ECDSA
>>> import binascii
>>> import ecdsa
>>> private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
>>> public_key = private_key.get_verifying_key()
>>> binascii.hexlify(public_key.to_string()).decode('ascii').upper()
u'D5C08F1BFC9C26A5D18FE9254E7923DEBBD34AFB92AC23ABFC6388D2659446C1F04CCDEBB677EAABFED9294663EE79D71B57CA6A6B76BC47E6F8670FE759D746'
C ++, libbitcoin
#include
#include
int main() {
// Private key
bc::ec_secret secret = bc::decode_hash(
"038109007313a5807b2eccc082c8c3fbb988a973cacf1a7df9ce725c31b14776");
// Get public key
bc::ec_point public_key = bc::secret_to_public_key(secret);
std::cout << "Public key: " << bc::encode_hex(public_key) << std::endl;
}
To compile and run, we use (pre-installing libbitcoin):
$ g++ -o public_key $$(pkg-config --cflags --libs libbitcoin)
$ ./public_key
Public key: 0202a406624211f2abbdc68da3df929f938c3399dd79fac1b51b0e4ad1d26a47aa
You can see that the formats of the public keys in the first and second examples are different (at least in length), I will discuss this in more detail below.
Formats & address
Base58Check encoding
This encoding will be met by us constantly throughout the book, so you should understand how it works and why it is needed at all.
Its essence is to write down the sequence of bytes in the most readable format as briefly as possible and at the same time make the probability of possible typos even less. I think you yourself understand that in the case of Bitcoin, security is never superfluous. One wrong character and money will go to the address, keys to which most likely no one will ever find. Here is a comment on this encoding from in base58.h :
// Why base-58 instead of standard base-64 encoding? // - Don't want 0OIl characters that look the same in some fonts and // could be used to create visually identical looking account numbers. // - A string with non-alphanumeric characters is not as easily accepted as an account number. // - E-mail usually won't line-break if there's no punctuation to break at. // - Doubleclicking selects the whole number as one word if it's all alphanumeric.
The brevity of recording is easiest to implement using the fairly common Base64 encoding , that is, using the base 64 number system, where numbers
0,1,...,9
, letters a-z
and A-Z
are used for writing - this gives 62 characters, the remaining two can be anything, depending on the implementation. The first difference with Base58Check is that characters are removed
0,O,l,I
in case someone decides to mix them up. It turns out 58 characters, you can checkb58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
def base58encode(n):
result = ''
while n > 0:
result = b58[n%58] + result
n /= 58
return result
# print "Base58 encode for '123123':", base58encode(123123)
# # Base58 encode for '123123': dbp
The second difference is the same check . At the end of the line, checksum is added again - the first 4 bytes
SHA256(SHA256(str))
. Well, you also need to add as many units to the beginning as there were leading zeros before the encoding in base58, this is already a technical matter.import hashlib
def base58encode(n):
b58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
result = ''
while n > 0:
result = b58[n % 58] + result
n /= 58
return result
# Will be used to decode raw bytes and then encode them to the base58
def base256decode(s):
result = 0
for c in s:
result = result * 256 + ord(c)
return result
def countLeadingZeroes(s):
count = 0
for c in s:
if c == '\0':
count += 1
else:
break
return count
def base58CheckEncode(prefix, payload):
s = chr(prefix) + payload
checksum = hashlib.sha256(hashlib.sha256(s).digest()).digest()[0:4]
result = s + checksum
return '1' * countLeadingZeroes(result) + base58encode(base256decode(result))

Private key formats
The most obvious way to store a private key is to write 256 bits as a bunch of zeros and ones. But, probably, any technically competent person understands that it will be much easier to present the same sequence in the form of 32 bytes, where each byte corresponds to two characters in a hexadecimal notation. Let me remind you that in this case, numbers
0,1,...,9
and letters are used A,B,C,D,E,F
. I used this format in the examples above, for beauty it is sometimes sometimes separated by spaces.E9 87 3D 79 C6 D8 7D C0 FB 6A 57 78 63 33 89 F4 45 32 13 30 3D A6 1F 20 BD 67 FC 23 3A A3 32 62
Another more advanced format is WIF ( Wallet Import Format ). It is built quite simply:
- Take a private key, for example
0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D
- We write it to Base58Check with a prefix
0x80
. All.
private_key = '0a56184c7a383d8bcce0c78e6e7a4b4b161b2f80a126caa48bde823a4625521f'
def privateKeyToWif(key_hex):
return base58CheckEncode(0x80, key_hex.decode('hex'))
# print "Private key in WIF format:", privateKeyToWif(private_key)
# # Private key in WIF format: 5HtqcFguVHA22E3bcjJR2p4HHMEGnEXxVL5hnxmPQvRedSQSuT4
Public key formats
Just in case, let me remind you that the public key is just a point on the line SECP256k1. The first and most common variant of its recording is an uncompressed format, 32 bytes each for X and Y coordinates. To avoid confusion, the prefix of
0x04
that 65 bytes is also used.import ecdsa
private_key = '0a56184c7a383d8bcce0c78e6e7a4b4b161b2f80a126caa48bde823a4625521f'
def privateKeyToPublicKey(s):
sk = ecdsa.SigningKey.from_string(s.decode('hex'), curve=ecdsa.SECP256k1)
vk = sk.verifying_key
return ('\04' + sk.verifying_key.to_string()).encode('hex')
uncompressed_public_key = privateKeyToPublicKey(private_key)
# print "Uncompressed public key: {}, size: {}".format(uncompressed_public_key, len(uncompressed_public_key) / 2)
# # Uncompressed public key: 045fbbe96332b2fc2bcc1b6a267678785401ee3b75674e061ca3616bbb66777b4f946bdd2a6a8ce419eacc5d05718bd718dc8d90c497cee74f5994681af0a1f842, size: 65
However, as the name suggests, this is not the best way to store a public key.
You will be surprised, but the second format is called compressed . Its essence is as follows: a public key is a point on a curve, that is, a pair of numbers satisfying the equation
The only caveat is that if the point lies on the curve, then obviously there are two solutions to this equation for its X coordinate (look at the graphs above if in doubt). Usually we would just save the sign for the Y coordinate, but when it comes to functions over a finite field, we need to use the following property:if there are solutions to the equation for the X coordinate, then one of the points will have an even Y coordinate, and the second will have an odd one (again, you can see for yourself).
In the first case, the prefix is used
0x02
, in the second - 0x03
. Here is an illustration of the process:
Address
As already mentioned, the address is obtained from the public key in a unique way. Moreover, it is impossible to carry out the reverse operation, since cryptographically strong hash functions are used - RIPEMD160 and SHA256 . Here is the algorithm for translating the public key to the address:
- Take a private key, for example
45b0c38fa54766354cf3409d38b873255dfa9ed3407a542ba48eb9cab9dfca67
- We will get the public key from it in uncompressed format, in this case
04162ebcd38c90b56fbdb4b0390695afb471c944a6003cb334bbf030a89c42b584f089012beb4842483692bdff9fcab8676fed42c47bffb081001209079bbcb8db
. - We believe
RIPEMD160(SHA256(public_key))
that it turns out5879DB1D96FC29B2A6BDC593E67EDD2C5876F64C
- We translate the result into Base58Check with the prefix
0x00
-17JdJpDyu3tB5GD3jwZP784W5KbRdfb84X
. This is the address.
def pubKeyToAddr(s):
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(hashlib.sha256(s.decode('hex')).digest())
return base58CheckEncode(0, ripemd160.digest())
def keyToAddr(s):
return pubKeyToAddr(privateKeyToPublicKey(s))
# print keyToAddr("45b0c38fa54766354cf3409d38b873255dfa9ed3407a542ba48eb9cab9dfca67")
# # '17JdJpDyu3tB5GD3jwZP784W5KbRdfb84X'
Sign & verify
I don’t think you need to know the technical details of exactly how ECDSA signs and checks messages, anyway you will use ready-made libraries everywhere. The main thing is that you have a common understanding of why this is necessary, but if you are still interested, look through the Layman's Guide to Elliptic Curve Digital Signatures , there is a beautiful visualization of the whole process below, you can try it yourself.
That's it for me, the next chapter: Bitcoin in a nutshell - Transaction .