My goal with this series is to provide an in-depth introduction to cryptocurrencies. Before analyzing cryptocurrencies, we need to understand 2 cryptographic primitives:

Public private key cryptography: This is the focus of this chapter. We will analyze how cryptography is used for generating public/private key pairs and how this is used to derive a "wallet address"

Cryptographic hash functions: This will be the focus of next chapter

We will use these concepts repeatedly in the rest of this series.

**A short history of encryption**

**A short history of encryption**

Encryption has been used for centuries. Humans have always wanted to communicate with each other and sometimes this communication requires secrecy. Information is power. In wars, keeping information like battle strategy, troops quantity etc can be critical to victory. Many centuries ago, information was confined to physical media (paper, scrolls etc). Information was secured by protecting the media on which it was written. Therefore, there was less need for encryption as the physical protection of the information/media made sure that only the intended recipient could read the message.

However, it was not always possible to protect the physical media that contained the information. Therefore, ciphers were invented. A cipher is used to encrypt the message into “cipher-text”. Only a person with the cipher or the key can decrypt the cipher-text (or at least that is the intent). One of the first ciphers to be introduced was the Caesar cipher. It is believed to be used by Julius Caesar and, hence, the name. It is a very simple cipher technology and encrypts a message by substituting each letter in the original message with another letter that is a fixed number of positions down the alphabet. The following diagram shows the result of a Caesar cipher with a right shift of 3 characters. Therefore, the letter ‘a’ gets encoded to ‘d’ in the cipher-text, ‘b’ gets encoded to ‘e’ and so on.

Source: https://brilliant.org/wiki/enigma-machine/#encryption

The Caesar cipher is a weak encryption technique and can be easily compromised. For e.g. the character ‘e’ is the most common letter in the English language. Therefore, the encrypted text can be analyzed to identify the most frequently occurring letter in the cipher-text. The enemy can then assume that this letter can be replaced by the letter ‘e’ and this will reveal the “shift” that has been used for encrypting the message using the Caesar cipher. Furthermore, Caesar cipher can be also compromised by using a brute force technique in which the enemy can try all possible “shift” combinations to see which one can reveal the original message.

In parallel, there was an effort to increase the speed of information transmission. At first, horses were used for transmitting information. They were replaced by locomotives and then with telegraph wires. Ultimately, they were replaced by radio waves in the 20th century. Radio waves are a type of electromagnetic waves, which travel at the speed of light. However, these new faster modes of information transmission also made it easy to intercept the message. The information was no longer attached to a physical media that could be protected/secured but was relayed over telegraph wires or radio waves and these media could be more easily “tapped” into. Therefore, the need for encryption became more important.

Advancement in cryptographic technology also meant that simple encryption techniques (like Caesar cipher) would no longer be effective. This led to more sophisticated encryption techniques in the 19th and 20th centuries. One of the most famous was the encryption provided by the Enigma machines, which was used by the Germans in World War 2.

The Enigma machine leveraged a substitution cipher (similar to the approach underlying Caesar cipher). However, the “key” or the shift for each letter was different. This made it difficult to decrypt messages that were encrypted by Enigma. German troops received an Enigma book every month that contained the settings for the machines for each day of that month so that they could decode the message.

This kind of encryption is known as symmetric encryption. In this form of encryption, the key that is used for encryption and decryption is the same. However, this leads to another challenge - how do you share the key with the intended recipient without sharing it with others? The sender would need to meet the recipient in person or arrange another way to share the key so that the future messages can be encrypted/decrypted only between the sender and recipient. During World War 2, the German government was able to coordinate distribution of the enigma key setting books and their secure distribution. However, such a distribution is not practical for individuals/corporations. This led to the development of asymmetric encryption.

In asymmetric encryption, the key that is used for encryption is different from the key that is used for decryption. Imagine that Alice wants to send a message to Bob. Bob will share his public key with Alice. This public key can be accessed by anyone including a “man in the middle”, who wants to gain access to the message. Alice can use Bob’s public key to encrypt the message that she wants to send to Bob. Alice can also sign the message using her own private key. Since only Alice has access to her private key, this signature will prove to Bob (and others) that the message came from Alice (otherwise the man in the middle can impersonate Alice and send a fake message to Bob by encrypting it using Bob’s public key as Bob’s public key is available to everyone). Bob receives Alice’s encrypted message and is able to decrypt it using his private key (which is only available to Bob). He is also able to verify the signature in the message that proves that the person who sent the message had access to Alice’s private key (and, therefore, Alice must have sent the message).

In the rest of this chapter, we will discuss 2 popular examples of asymmetric cryptography:

**RSA**: Named using the initials of researchers that proposed it - Ron Rivest, Adi Shamir and Leonard Adleman**ECDSA**: Elliptic Curve Digital Signature Algorithm; This is the algorithm that is used in many popular crypto projects like Bitcoin and Ethereum

**RSA: Using prime numbers for cryptography**

**RSA: Using prime numbers for cryptography**

Asymmetric cryptographic techniques leverage a “trapdoor” function. A trapdoor function is something that is easy to perform in one direction but is very difficult to reverse or perform in the opposite direction.

In RSA, 2 large prime numbers - we will denote them by p and q - are taken and multiplied together to give another number (known as modulus, n). It is easy to create a number like ‘n’. But given a number ‘n’ it is very difficult to find the prime factors, p and q. This property of prime numbers is used as the trapdoor function to achieve cryptographic security.

The steps that are used for generating the key pair and encrypting/decrypting messages are shown below. In this example, I am using small prime numbers. In real world applications, much larger prime numbers are used.

__Step 1: __

Choose 2 large prime numbers - p and q. We will choose the following:

```
p = 29
q = 41
```

__Step 2: __

Calculate the modulus of p and q

`Modulus = n = p x q = 29 x 41 = 1189`

__Step 3: __

Calculate the totient of n. We will represent this as totient(n)

`totient(n) = (p-1) x (q-1) = (29-1) x (41-1) = 28 x 40 = 1120`

__Step 4: __

In this step, we will calculate the public key. The public key is represented as (e, n). ‘n’ is already public as we calculated it in step 2. We now need to identify the exponent, e, that satisfies the following conditions

Should be a prime number

Should be >=3

Should be < totient(n)

Should not be a factor of totient(n)

Totient(n) can be prime factorized as follows:

`totient(n) = 1120 = (2^5) x 5 x 7`

Therefore, e cannot be 2, 5 or 7 but it can be any other prime number that satisfies the first 3 conditions. Therefore, potential values of e can be 11, 13, 17, 19, 23….etc. We will select e to be 11. However, note that other prime numbers from this list can also be used. In real world applications, e is typically taken to be 65537.

Therefore, the public key = (e, n) = (11, 1189) in our example.

__Step 5: __

We will now calculate the private key. The private key is represented as (d, n). The value of d can be found using the following equation:

`(e x d) mod (totient(n)) = 1`

“Mod” is a mathematical operator that means the “remainder of”. Therefore, x mod y will be equal to the remainder when x is divided by y. For e.g. 10 mod 3 = 1 as when 10 is divided by 3, it leaves a remainder of 1.

Therefore, in the above equation, we have to search for a ‘d’ that will leave a remainder for 1 when the (e x d) is divided by totient(n). We can use an __online calculator__ to calculate this. We find this to be 611.

We can confirm that 611 satisfies the equation as follows:

```
e x d = 11 x 611 = 6721
totient(n) = 1120
6721 = (1120 x 6) + 1. Therefore, it leaves a remainder of 1 as expected
```

Therefore, the private key is represented as (d, n) i.e. (611, 1189)

__Step 6: __

Encrypt message

Let’s assume that the message that we want to encrypt is the number 5. Note that any message can be converted into numbers. For e.g. if we want to encrypt the word “Hello” then it can be converted into binary. For e.g. this __calculator__ can be used for finding the binary representation of the text “Hello” which is:

`01001000 01100101 01101100 01101100 01101111 `

Therefore, any message can be converted into a number and the encryption formula can be applied on it as shown below:

`encrypted_message = (original_message ^ e) mod n`

As identified above, e = 11, n = 1189 and original_message = 5

We can use an online mathematical calculator like wolfram alpha to do the above calculation and we identify it to be:

`encrypted_message = 651`

__Step 7: __

Decrypt message

`decrypted_message = (encrypted_message ^ d) mod n`

If everything goes as expected then the decrypted_message should be equal to the original_message

As identified above, d = 611, n = 1189 and encrypted_message = 651

We can calculate the above using wolfram alpha. The decrypted_message is calculated to be 5, which is the same as the original message (as expected).

In RSA, the public key is shared with the world but the private key is kept secret. However, in step 5, we calculated the private key from the public key. Is it possible for our adversary to do this calculation i.e. can our adversary derive the private key from the public key?

The answer is no. In Step 5, we needed ‘e’ and the totient(n) to calculate ‘d’, which is the missing part of the private key. The adversary will know the public key = (e, n) i.e. the adversary will know the values of e and n individually. However, to derive ‘d’ (i.e. derive the private key), the adversary will also need to know the totient(n). However, totient(n) = (p-1) x (q-1). Therefore, the adversary will need to know the prime factors of n i.e. p and q to be able to calculate the totient(n). However, as discussed, it is a very difficult problem to calculate the prime factors for a large number like n. This is the trapdoor property used in RSA and ensures that the private key cannot be derived from the public key.

One key challenge with RSA is that the key size for achieving a high level of security can be quite high. While prime factorization is a difficult problem, the recent increase in computing resources has made it possible to prime factorize large numbers. T__his page__ tracks some of the large prime numbers that have been factored. For e.g. in 2020, a number - RSA-250 - that has 250 decimal digits (or 829 bits) was factored. The factorization took 2700 CPU core years using a 2.1GHz Intel Xeon Gold 6130 CPU as a reference. On cloud computing platforms like AWS, it is possible to rent out instances that can deliver 10+ cores. An adversary can run 1000s of these instances and can potentially break the encryption in a reasonable amount of time. Therefore, for added security, RSA recommend key lengths that are very long (e.g. 2048 bits long). This can represent a computational challenge for some applications as the public key has to be communicated (i.e. consumes networking capacity) and can also consume more compute/storage capacity. This is one of the reasons that ECDSA was developed.

**ECDSA: Using elliptic curves for cryptography**

**ECDSA: Using elliptic curves for cryptography**

RSA leverages a property of prime numbers (i.e. it is very difficult to factorize large numbers into its prime factors) as its trapdoor function. Similarly ECDSA leverages a property of elliptical curves as its trapdoor function.

First, we need to understand what elliptical curves are. In mathematics, the relationship between 2 variables can be represented graphically on a 2 dimensional chart. For e.g. a circle can be represented using the following equation:

`x^2 + y^2 = r^2`

In this equation, x and y are the variables while ‘r’ is a constant that is kept fixed. Geometrically, r is the radius of this circle. When this equation is plotted in 2 dimensions, it generates the familiar “circle” curve.

Elliptical curves is another type of mathematical curve that can be represented by the following equation

`y^2 = x^3 + ax + b`

In the above equation, x and y are variables while ‘a’ and ‘b’ are constants. When plotted, elliptical curves looks like the following:

Cryptocurrencies like Bitcoin and Ethereum use a special kind of elliptic curve known as secp256k1 in which a = 0 and b = 7. Some additional manipulation is done to the curve so that the equation of the curve is as follows

`y^2 mod p = (x^3 + 7) mod p`

p is a constant in the above equation and is defined as follows

`p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 -1`

Numbers can be represented in different notations. Typically, we use the decimal notation i.e. base 10 notation as there are 10 digits/characters that can be used for representing a number. However, it is very easy to convert a number into another notation. 2 other notations that we will frequently use in this series are:

Binary notation; base 2

Hexadecimal notation; base 16

There are numerous online calculators that can convert a number from one notation to the other. I will use __this calculator__ for any such conversions.

Now p is a very large prime number. We can represent it in different notation as follows:

```
P (in decimal): 115792089237316195423570985008687907853269984665640564039457584007908834671663
P (in binary): 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111011111111111111111111110000101111
P (in HEX): FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
```

If you count the number of 0/1s used for representing P in binary then you will find that the total number of characters used is 256. Similarly, the total number of characters used for representing P in HEX is 64. Therefore, these numbers are referred to as 256 bit numbers (as 256 bits/binary digits are needed to represent the number). A 256 bit number can be represented using 64 characters in HEX.

Note that p is not the largest 256 bit number that can be constructed. The theoretical maximum 256 bit number will consist of all 1s in the above representation and will be equal to the following (in decimal):

115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,665,640,564,039,457,584,007,913,129,639,935

This theoretical maximum is slightly larger than p. However, since p is very close to the theoretical maximum, we can almost assume that p is equal to 2^256. Furthermore, we can assume that this special elliptic curve is defined for integer values only. This property is introduced due to the “modulus” operator that is introduced in the equation.

Elliptical curves have another special property, which is the basis for the ECDSA’s trapdoor functionality. Let's take a point on the curve, G. For the special curve, secp256k1, G is defined as the following point:

*x* = 55066263022277343669578718895168534326250603453777594175500187360389116729240
*y* = 32670510020758816978083085130507043184471273380659243275938904335757337482424

If we want to add G to itself i.e. calculate G+G = 2G then we can do this using the following steps (note this approach holds true for elliptical curves because of their mathematical properties):

Draw a tangent to the curve at the point G

Identify the point at which this tangent intersects the elliptic curve. Note that the mathematics of elliptic curve ensures that the tangent will intersect the curve at one and only one point

Take the reflection of this point in the x axis i.e. change the sign of the y-coordinate. This point is defined as G+G = 2G

Similarly, we can calculate 3G (=G + 2G) in the following way:

Draw a line joining G and 2G

Identify the point at which this line intersects the elliptic curve. It is guaranteed that this line will intersect the curve at one and only one point

Take the reflection of this point in the x-axis. The resultant point is 3G

Therefore, 2G, 3G etc are also points on the elliptic curve. If we follow the above steps then we can find kG for any value of k. For a large value of k, it is easy to calculate kG (which is just a point on the elliptic curve). However, if kG is known then it is not possible to back calculate the value of k that led to kG. This is the desired property for a trapdoor function. Therefore, kG can be treated as the public key while k can be treated as a private key.

Let’s summarize the entire approach with a real example:

__Step 1:__

Start with picking your private key, k. This number can be any 256 bit number that is less than p (=115792089237316195423570985008687907853269984665640564039457584007908834671663). As discussed earlier, p is almost equal to 2^32 (in decimal) or p can be considered almost equal to the largest 256 bit number (in binary). Therefore, almost any 256 bit number can be chosen. Note that it is important to make sure that our chosen private key is random so that it is not easy to guess. We will use the following private key for our discussion

```
Private key in DEC: 92708965803452882195017470517437847623936144041812006235926846203727924302528
Private key in BIN: 11001100 11110111 01101010 01000101 11010010 00000011 11101110 00111011 10011110 00101001 01101111 00010000 01110101 01001001 10011001 10001101 00100010 01111100 01111001 00100001 01100011 10100100 01000001 01101110 10100010 11110111 00100011 00101111 01100001 00100010 00010010 11000000
Private key in HEX: ccf76a45d203ee3b9e296f107549998d227c792163a4416ea2f7232f612212c0
```

__Step 2:__

Calculate public key using k (which is the private key) and G. As discussed earlier, G is a fixed point for secp256k1. You can use an __online calculator__ to calculate the value of the public key, kG. For the chosen private key, the public key is calculated to be the following:

```
x = 62612040937758171590997371752890249086110878804501011805800919440880618122678
y = 110557282650229166677803199770394945229462525760635132164239138162679181498501
```

As mentioned above, the public key is a point (i.e. it is defined by an x and y coordinate) on the elliptic curve. The above point is shown in decimal notation. We can also display them in HEX notation. The HEX values of the public key is shown below:

```
x = 8A6D28C988C4C2C6BD6D18614933F5CB78F9020D5E056D1DFABC848121D72DB6
y = F46D3458185D8FE3FB94E4A9AEDD7CAEA2E57DFF685ADA01B8B8D69FE6B05885
```

Therefore, we can use ECDSA to generate a private/public key pair using the above approach. We will now look at the applications of ECDSA in cryptocurrencies.

**Applications of ECDSA in cryptocurrency:**

**Applications of ECDSA in cryptocurrency:**

ECDSA plays 2 critical functions in cryptocurrencies:

Function #1: Used for generation of the “wallet” address so that the user can receive bitcoins from another user

Function #2: Sign a bitcoin transaction so that the user can authenticate that the transaction has been authorized by the user

We will focus on the first function in this chapter. We will discuss the 2nd function in a later chapter.

Consider Bitcoin. Alice can send bitcoins to Bob. Alice does so by specifying the “wallet address” of Bob. This wallet address is derived from Bob’s public key. Let's derive this using the public key that we calculated in the previous section. The steps to do this are as follows:

__Step 1:__

Write the public key in the right format.

In the last section, we calculated the public key to be a point on the elliptic curve defined by the following coordinates (we show the coordinates in HEX notation) :

```
x = 8A6D28C988C4C2C6BD6D18614933F5CB78F9020D5E056D1DFABC848121D72DB6
y = F46D3458185D8FE3FB94E4A9AEDD7CAEA2E57DFF685ADA01B8B8D69FE6B05885
```

We will represent this in the following format:

`concatenate(x-coordinate, y-coordinate)`

Note that a “04” prefix is added sometimes to show that the key is uncompressed. This means that we have taken both x and y coordinates in the public key representation and no information has been “lost”. To save space, we can also take only the x coordinate value in which case we will either use a "02" or "03" prefix. When we take only the x coordinate then the key is labelled compressed. We will continue to use the uncompressed key in the rest of this chapter.

After doing the above formatting changes, we are left with the following:

`public key = 8A6D28C988C4C2C6BD6D18614933F5CB78F9020D5E056D1DFABC848121D72DB6F46D3458185D8FE3FB94E4A9AEDD7CAEA2E57DFF685ADA01B8B8D69FE6B05885`

__Step 2: __

We will calculate the SHA256 hash of the above. We will go into more details of hash functions in the next chapter. For now, we can assume that a hash function can uniquely transform some data into another data. We can calculate the SHA256 hash using an __online calculator__.

Therefore,

```
SHA256(8A6D28C988C4C2C6BD6D18614933F5CB78F9020D5E056D1DFABC848121D72DB6F46D3458185D8FE3FB94E4A9AEDD7CAEA2E57DFF685ADA01B8B8D69FE6B05885) =
a40d78dc9a298c8f388aa49b8f09e48d9531f1846bf9b419ff0f2af273dd11cf
```

__Step 3:__

Do another hash - RIPEMD-160 - on the output from step 2. We can use the online calculator to do this.

```
RIPEMD160(a40d78dc9a298c8f388aa49b8f09e48d9531f1846bf9b419ff0f2af273dd11cf) =
f14b5fcd11cd66debec4f597a417dc3c2526432e
```

__Step 4:__

Add “version” as a prefix to the above hash value.

We will add the prefix - 0x00 - to the above hash value. This prefix is a convention that is used to indicate that a particular value that is being calculated is a bitcoin wallet address. Therefore, we obtain:

`0x00f14b5fcd11cd66debec4f597a417dc3c2526432e`

__Step 5:__

Calculate double SHA256 hash of the value obtained in step 4. Double hash means that we have to take SHA256 of the SHA256 value of 0x00f14b5fcd11cd66debec4f597a417dc3c2526432e.

This is represented as SHA256(SHA256(0x00f14b5fcd11cd66debec4f597a417dc3c2526432e)). Again we can use the online calculator for generating this.

First hash:

`SHA256(0x00f14b5fcd11cd66debec4f597a417dc3c2526432e) = 7200a696ae61e7114ea83cf347b0b40f8fd184ec7131b3759f70b3207bc11c1b`

Second hash:

```
SHA256(7200a696ae61e7114ea83cf347b0b40f8fd184ec7131b3759f70b3207bc11c1b) =
efd8a507c28f73bbcbd678002652d34cf0b4dd4b5dbf5cbb0a1b0b7bb46cc543
```

__Step 6:__

Append the first 4 bytes of the value obtained in step 5 to the value obtained in step 4

In step 5, we obtained:

efd8a507c28f73bbcbd678002652d34cf0b4dd4b5dbf5cbb0a1b0b7bb46cc543

Note that 4 bytes = 4 x 8 = 32 bits. 1 HEX character can represent 4 bits. This is because HEX uses base 16 and binary uses base 2. 2^4 is equal to 16. Therefore, a x bit binary number can be represented by x/4 HEX characters.

Therefore, taking the first 4 bytes of this value means that we need to take first (32/4)=8 characters from the HEX notation. Therefore, we will need to append the following at the end of the value obtained in step 4:

efd8a507

Appending the above gives us the following:

0x00f14b5fcd11cd66debec4f597a417dc3c2526432eefd8a507

Why did we append 8 (and only 8 HEX characters at the end of the value obtained in step 4)? This is because “efd8a507” is used as a checksum. What is a checksum? Checksum is a technique that is used to reduce the possibility of entering a wrong wallet address. We will revisit this after step 7.

__Step 7:__

We will now encode the value obtained at the end of step 7 using base-58 encoding. We can use an __online converter__ to do this. What is base-58 encoding and why do we need to do this? Base-58 is a notation to represent data/numbers. Decimal is a base-10 system while HEX is a base-16 system. Hex uses 16 characters: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F to represent numbers/data. Similarly base-58 uses 58 characters. This consist of

= all uppercase alphabets (except ‘O’ and ‘I’) + lower case alphabets (except ‘l’) + numbers (except ‘0’). The characters - O, I, l and 0 - have been excluded as it is easy to mistakenly type one of these characters. After this exclusion, we are left with 58 characters. Base-58 encoding is used for wallet address to reduce typos.

```
Base-58 encoding of 0x00f14b5fcd11cd66debec4f597a417dc3c2526432eefd8a507 = 1Nzr9Knm9nwZb8Au1xbPRnSdx9dZNC5YYv
```

This final value - 1Nzr9Knm9nwZb8Au1xbPRnSdx9dZNC5YYv - is the Bitcoin wallet address of the user. Bob can send bitcoins to Alice by sending bitcoins to this address.

Now let’s discuss the importance of checksum. Imagine that a user types a wrong wallet address. For e.g. instead the K at the 6 location, the user types a D. Therefore, the wallet address that they have typed is:

1Nzr9**D**nm9nwZb8Au1xbPRnSdx9dZNC5YYv

Now this is a mistake and transactions on blockchain are immutable. The wallet software that the user is using will be able to detect this mistake by using checksum. To see how this works…lets repeat some of the steps backwards.

Let's first decode the wrong base-58 address back to the HEX data. We can use an __online decoder__ to do this. We get the following:

0x00f14b5f6b7ec35f17aac9d22e7eafe8c4ff8129ec8fd8a507

According to the wallet the last 8 characters are the checksum. Therefore:

`Assumed_checksum = 8fd8a507`

This checksum should be the first 8 characters of the double hash of the rest of the data i.e. for everything to be correct:

`First 4 bytes (i.e. 8 characters in HEX) of SHA256(SHA256(0x00f14b5fcd11cd66debec4f597a417dc3c2526432e)) should be = checksum = 8fd8a507`

We can again use an online hash calculator to calculate the double hash value as shown below

```
First 4 bytes (i.e. 8 character in HEX) of [798190315d3365343dd2f03622654bb4f7d534d2da64ad5ab3fcddd696a7b3dc] should be = checksum = 8fd8a507
i.e. 79819031 should be = checksum = 8fd8a507
```

This is not correct. Therefore, the checkum included in the address does not match the address. This implies that there was a mistake in entering the address and the wallet software will let the user know this.

__Deriving Ethereum addresses: __

Before ending this chapter, let's also derive Ethereum wallet address. Ethereum leverages ECDSA for generating public/private key pair as well. Therefore, we can start off with same public key that we had identified before. As a reminder, public keys (as part of ECDSA) are just points on special elliptic curve, secp256k1, can have an x and y coordinate. The public key that we had identified was:

```
x = 8A6D28C988C4C2C6BD6D18614933F5CB78F9020D5E056D1DFABC848121D72DB6
y = F46D3458185D8FE3FB94E4A9AEDD7CAEA2E57DFF685ADA01B8B8D69FE6B05885
```

We now follow these steps:

__Step 1:__

Concatenate x and y coordinate of the public key:

8A6D28C988C4C2C6BD6D18614933F5CB78F9020D5E056D1DFABC848121D72DB6F46D3458185D8FE3FB94E4A9AEDD7CAEA2E57DFF685ADA01B8B8D69FE6B05885

__Step 2:__

Calculate the keccak256 hash of the above. keccak256() is another kind of hash function. We will study them in detail in the next chapter. We can use an online calculator to determine the hash value as shown below:

`keccak256(8A6D28C988C4C2C6BD6D18614933F5CB78F9020D5E056D1DFABC848121D72DB6F46D3458185D8FE3FB94E4A9AEDD7CAEA2E57DFF685ADA01B8B8D69FE6B05885) = 6dd5ccf3dba6f4a63840be07bd5e4d8fcbae9198f6b2373a7cfc770dbc3f0dd3`

__Step 3:__

Keep the last 20 bytes of the above. 20 bytes = 20 x 8 bits = 160 bits. One HEX character can represent 4 bits of data. Therefore, this means that we need to keep the last 160/4 = 40 characters in the value obtained in step 2. This is as follows:

bd5e4d8fcbae9198f6b2373a7cfc770dbc3f0dd3

__Step 4:__

A convention is to append “0x” at the beginning of above to show that the value is shown in HEX notation. This gives us the following:

0xbd5e4d8fcbae9198f6b2373a7cfc770dbc3f0dd3

That’s it! This is our Ethereum wallet address.

Lets summarize our journey:

As part of ECDSA, we first select a random number as our private key. This can be any random 256 bit number or a number less than 2^32 (in decimal)

We then calculate our public key (= private_key x G; G is a fixed generator point). The public key is a point on the elliptic curve

We can decide to use the uncompressed key (i.e. both x and y coordinates of the public key) or a compressed key (i.e. only the x coordinate of the public key). We use an appropriate prefix to denote if we are using uncompressed/compressed key

We then calculate a hash of this public key. In Bitcoin, we calculate the SHA256() followed by RIPEMD-160() hash. In Ethereum, we calculate the keccak256()

We make some formatting modifications to the generated hash. For e.g. in Bitcoin, we add a prefix, checksum etc. In Ethereum, we keep only the last 40 HEX characters, add a prefix etc.

We obtain our wallet address

Therefore, the ECDSA nuances that we covered is central to how bitcoin operates as the public key is a key way for users to receive bitcoins and the private key is a key way that users determine if they want to send/spend or access their bitcoins.

We now have got good handle on the first primitive to understand cryptocurrencies. Note that private/public keys, encryption etc will continue to be important topics as we discuss cryptos. We now move to the 2nd primitive - cryptographic hash functions. We already used hash functions in this chapter

We took a SHA256() and RIPEMD-160() hash of the public key as part of calculating the Bitcoin address. We also did a double SHA256() hash to identify the checkum

We took a keccak256() of the public key to identify the Ethereum address

This application itself makes hash function a central part of the crypto story. But in the next chapter, we will see how hash functions are liberally used across the crypto ecosystem.