Skip to content

Commit 85a0bfb

Browse files
Svetlin Nakovgitbook-bot
authored andcommitted
GITBOOK-4: change request with no subject merged in GitBook
1 parent a05a517 commit 85a0bfb

File tree

76 files changed

+1108
-1178
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1108
-1178
lines changed

asymmetric-key-ciphers/README.md

Lines changed: 28 additions & 29 deletions
Large diffs are not rendered by default.

asymmetric-key-ciphers/ecc-encryption-decryption.md

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
11
# ECC Encryption / Decryption
22

3-
In this section we shall explain how to implement **elliptic-curve based public-key encryption / decryption** \(asymmetric encryption scheme based on ECC\). This is **non-trivial** and usually involves a design of hybrid encryption scheme, involving ECC cryptography, ECDH key exchange and symmetric encryption algorithm.
3+
In this section we shall explain how to implement **elliptic-curve based public-key encryption / decryption** (asymmetric encryption scheme based on ECC). This is **non-trivial** and usually involves a design of hybrid encryption scheme, involving ECC cryptography, ECDH key exchange and symmetric encryption algorithm.
44

5-
Assume we have a ECC **private-public key pair**. We want to encrypt and decrypt data using these keys. By definition, **asymmetric encryption** works as follows: if we **encrypt data by a private key**, we will be able to **decrypt** the ciphertext later by the corresponding **public key**:
5+
Assume we have a ECC **private-public key pair**. We want to encrypt and decrypt data using these keys. By definition, **asymmetric encryption** works as follows: if we **encrypt data by a public key**, we will be able to **decrypt** the ciphertext later by the corresponding **private key**:
66

77
![](../.gitbook/assets/asymmetric-encryption-diagram.png)
88

9-
The above process can be directly applied for the **RSA** cryptosystem, but not for the **ECC**. The elliptic curve cryptography \(ECC\) **does not directly provide encryption** method. Instead, we can design a **hybrid encryption scheme** by using the **ECDH** \(Elliptic Curve Diffie–Hellman\) key exchange scheme to derive a **shared secret key** for symmetric data encryption and decryption.
9+
The above process can be directly applied for the **RSA** cryptosystem, but not for the **ECC**. The elliptic curve cryptography (ECC) **does not directly provide encryption** method. Instead, we can design a **hybrid encryption scheme** by using the **ECDH** (Elliptic Curve Diffie–Hellman) key exchange scheme to derive a **shared secret key** for symmetric data encryption and decryption.
1010

11-
This is how most **hybrid encryption schemes** works \(the encryption process\):
11+
This is how most **hybrid encryption schemes** works (the encryption process):
1212

1313
![](../.gitbook/assets/hybrid-encryption.png)
1414

15-
This is how most **hybrid encryption schemes** works \(the decryption process\):
15+
This is how most **hybrid encryption schemes** works (the decryption process):
1616

17-
![](../.gitbook/assets/hybrid-decryption%20%281%29.png)
17+
![](<../.gitbook/assets/hybrid-decryption (1).png>)
1818

1919
Let's get into details how to design and implement an **ECC-based hybrid encryption scheme**.
2020

21-
## ECC-Based Secret Key Derivation \(using ECDH\)
21+
## ECC-Based Secret Key Derivation (using ECDH)
2222

23-
Assume we have a **cryptographic elliptic curve** over finite field, along with its generator point **G**. We can use the following two functions to calculate a **shared a secret key** for **encryption** and **decryption** \(derived from the ECDH scheme\):
23+
Assume we have a **cryptographic elliptic curve** over finite field, along with its generator point **G**. We can use the following two functions to calculate a **shared a secret key** for **encryption** and **decryption** (derived from the ECDH scheme):
2424

25-
* **calculateEncryptionKey**\(pubKey\) --&gt; \(sharedECCKey, ciphertextPubKey\)
25+
* **calculateEncryptionKey**(pubKey) --> (sharedECCKey, ciphertextPubKey)
2626
1. Generate **ciphertextPrivKey** = _new **random** private key_.
2727
2. Calculate **ciphertextPubKey** = ciphertextPrivKey \* G.
2828
3. Calculate the ECDH shared secret: **sharedECCKey** = pubKey \* ciphertextPrivKey.
2929
4. Return both the **sharedECCKey** + **ciphertextPubKey**. Use the **sharedECCKey** for symmetric encryption. Use the randomly generated **ciphertextPubKey** to calculate the decryption key later.
30-
* **calculateDecryptionKey**\(privKey, ciphertextPubKey\) --&gt; sharedECCKey
30+
* **calculateDecryptionKey**(privKey, ciphertextPubKey) --> sharedECCKey
3131
1. Calculate the the ECDH shared secret: **sharedECCKey** = ciphertextPubKey \* privKey.
3232
2. Return the **sharedECCKey** and use it for the decryption.
3333

34-
The above calculations use the same math, like the **ECDH** algorithm \(see the [previous section](ecdh-key-exchange.md)\). Recall that EC points have the following property:
34+
The above calculations use the same math, like the **ECDH** algorithm (see the [previous section](ecdh-key-exchange.md)). Recall that EC points have the following property:
3535

36-
* \(_**a**_ \* **G**\) \* _**b**_ = \(_**b**_ \* **G**\) \* _**a**_
36+
* (_**a**_ \* **G**) \* _**b**_ = (_**b**_ \* **G**) \* _**a**_
3737

3838
Now, assume that _**a**_ = privKey, _**a**_ \* **G** = pubKey, _**b**_ = ciphertextPrivKey, _**b**_ \* **G** = ciphertextPubKey.
3939

@@ -45,7 +45,7 @@ This is what exactly the above two functions calculate, directly following the *
4545

4646
## ECC-Based Secret Key Derivation - Example in Python
4747

48-
The below Python code uses the `tinyec` library to generate a **ECC private-public key pair** for the message recipient \(based on the `brainpoolP256r1` curve\) and then derive a **secret shared key** \(for encryption\) and ephemeral **ciphertext public key** \(for ECDH\) from the recipient's **public key** and later derive the same **secret shared key** \(for decryption\) from the recipient's **private key** and the generated earlier ephemeral **ciphertext public key**:
48+
The below Python code uses the `tinyec` library to generate a **ECC private-public key pair** for the message recipient (based on the `brainpoolP256r1` curve) and then derive a **secret shared key** (for encryption) and ephemeral **ciphertext public key** (for ECDH) from the recipient's **public key** and later derive the same **secret shared key** (for decryption) from the recipient's **private key** and the generated earlier ephemeral **ciphertext public key**:
4949

5050
```python
5151
from tinyec import registry
@@ -83,25 +83,25 @@ Run the above code example: [https://repl.it/@nakov/ECC-based-secret-key-derivat
8383

8484
The code is pretty simple and demonstrates that we can generate a pair { **secret key** + **ciphertext public key** } from given EC **public key** and later we can recover the same **secret key** from the pair { **ciphertext public key** + **private key** }. The above code produces output like this:
8585

86-
```text
86+
```
8787
private key: 0x2e2921b4cde59cdf01e7a014a322abd530b3015085c31cb6e59502da761d29e9
8888
public key: 0x850d3873cf4ac50ddb54ddbd27f8225fc43bd3f4c2cc0a4f9d1f9ce15fc4eb711
8989
ciphertext pubKey: 0x71586f9999d3ee050005054bc681c1d96c5eb054ca15b080ba245e495627003b0
9090
encryption key: 0x9d13d3f8f9747669432f575731926b5ed99a6883f00146cbd3203ffa7ff8b1ae1
9191
decryption key: 0x9d13d3f8f9747669432f575731926b5ed99a6883f00146cbd3203ffa7ff8b1ae1
9292
```
9393

94-
It is clear from the above output that the **encryption key** \(derived from the public key\) and the **decryption key** \(derived from the corresponding private key\) **are the same**. This is due to the above discussed property of the ECC: `pubKey * ciphertextPrivKey = ciphertextPubKey * privKey`. These keys will be used for data encryption and decryption in an integrated encryption scheme. The above output will be different if you run the code \(due to the randomness used to generate `ciphertextPrivKey`, but the encryption and decryption keys will always be the same \(the ECDH shared secret\).
94+
It is clear from the above output that the **encryption key** (derived from the public key) and the **decryption key** (derived from the corresponding private key) **are the same**. This is due to the above discussed property of the ECC: `pubKey * ciphertextPrivKey = ciphertextPubKey * privKey`. These keys will be used for data encryption and decryption in an integrated encryption scheme. The above output will be different if you run the code (due to the randomness used to generate `ciphertextPrivKey`, but the encryption and decryption keys will always be the same (the ECDH shared secret).
9595

96-
The above demonstrated mechanism for generating a shared ephemeral secret key, based on a ECC key pair, is an example of **KEM** \(key encapsulation mechanism\), based on the ECC and ECDH.
96+
The above demonstrated mechanism for generating a shared ephemeral secret key, based on a ECC key pair, is an example of **KEM** (key encapsulation mechanism), based on the ECC and ECDH.
9797

9898
## ECC-Based Hybrid Encryption / Decryption - Example in Python
9999

100100
Once we have the **secret key**, we can use it for **symmetric data encryption**, using a symmetric encryption scheme like AES-GCM or ChaCha20-Poly1305. Let's implement a fully-functional **asymmetric ECC encryption and decryption** hybrid scheme. It will be based on the `brainpoolP256r1` curve and the **AES-256-GCM** authenticated symmetric cipher.
101101

102102
We shall use the `tinyec` and `pycryptodome` Python libraries respectively for ECC calculations and for the AES cipher:
103103

104-
```text
104+
```
105105
pip install tinyec
106106
pip install pycryptodome
107107
```
@@ -166,23 +166,22 @@ print("decrypted msg:", decryptedMsg)
166166

167167
Run the above code example: [https://repl.it/@nakov/ECC-based-hybrid-encryption-decryption-in-Python](https://repl.it/@nakov/ECC-based-hybrid-encryption-decryption-in-Python).
168168

169-
The above example starts from generating an ECC public + private **key pair** for the message recipient: `pubKey` + `privKey`, using the `tinyec` library. These keys will be used to **encrypt** the message `msg` through the hybrid encryption scheme \(asymmetric ECC + symmetric AES\) and to **decrypt** is later back to its original form.
169+
The above example starts from generating an ECC public + private **key pair** for the message recipient: `pubKey` + `privKey`, using the `tinyec` library. These keys will be used to **encrypt** the message `msg` through the hybrid encryption scheme (asymmetric ECC + symmetric AES) and to **decrypt** is later back to its original form.
170170

171-
Next, we **encrypt** `msg` by using the `pubKey` and we obtain as a result the following set of output: { `ciphertext`, `nonce`, `authTag`, `ciphertextPubKey` }. The `ciphertext` is obtained by the symmetric AES-GCM encryption, along with the `nonce` \(random AES initialization vector\) and `authTag` \(the MAC code of the encrypted text, obtained by the GCM block mode\). Additionally, we obtain a randomly generated ephemeral public key `ciphertextPubKey`, which will be encapsulated in the encrypted message and will be used to recover the AES symmetric key during the decryption \(using the ECDH key agreement scheme, as it was show before\).
171+
Next, we **encrypt** `msg` by using the `pubKey` and we obtain as a result the following set of output: { `ciphertext`, `nonce`, `authTag`, `ciphertextPubKey` }. The `ciphertext` is obtained by the symmetric AES-GCM encryption, along with the `nonce` (random AES initialization vector) and `authTag` (the MAC code of the encrypted text, obtained by the GCM block mode). Additionally, we obtain a randomly generated ephemeral public key `ciphertextPubKey`, which will be encapsulated in the encrypted message and will be used to recover the AES symmetric key during the decryption (using the ECDH key agreement scheme, as it was show before).
172172

173-
To **decrypt** the encrypted message, we use the data produced during the encryption { `ciphertext`, `nonce`, `authTag`, `ciphertextPubKey` }, along with the decryption `privateKey`. The result is the decrypted plaintext message. We use authenticated encryption \(GCM block mode\), so if the decryption key or some other parameter is incorrect, the decryption will fail with an **exception**.
173+
To **decrypt** the encrypted message, we use the data produced during the encryption { `ciphertext`, `nonce`, `authTag`, `ciphertextPubKey` }, along with the decryption `privateKey`. The result is the decrypted plaintext message. We use authenticated encryption (GCM block mode), so if the decryption key or some other parameter is incorrect, the decryption will fail with an **exception**.
174174

175-
Internally, the `encrypt_ECC(msg, pubKey)` function first generates an ephemeral **ECC key-pair** for the ciphertext and calculates the symmetric encryption shared ECC key `sharedECCKey = ciphertextPrivKey * pubKey`. This key is an EC point, so it is then transformed to **256-bit AES secret key** \(integer\) though hashing the point's `x` and `y` coordinates. Finally, the **AES-256-GCM** cipher \(from `pycryptodome`\) **encrypts** the message by the 256-bit shared secret key `secretKey` and produces as **output** `ciphertext` + `nonce` + `authTag`.
175+
Internally, the `encrypt_ECC(msg, pubKey)` function first generates an ephemeral **ECC key-pair** for the ciphertext and calculates the symmetric encryption shared ECC key `sharedECCKey = ciphertextPrivKey * pubKey`. This key is an EC point, so it is then transformed to **256-bit AES secret key** (integer) though hashing the point's `x` and `y` coordinates. Finally, the **AES-256-GCM** cipher (from `pycryptodome`) **encrypts** the message by the 256-bit shared secret key `secretKey` and produces as **output** `ciphertext` + `nonce` + `authTag`.
176176

177-
The `decrypt_ECC(encryptedMsg{ciphertext, nonce, authTag, ciphertextPubKey}, privKey)` function internally first calculates the symmetric encryption shared ECC key `sharedECCKey = privKey * ciphertextPubKey`. It is an EC point, so it should be first transformed to **256-bit AES secret key** though hashing the point's `x` and `y` coordinates. Then the **AES-256-GCM cipher** is used to **decrypt** the `ciphertext` + `nonce` + `authTag` by the 256-bit shared secret key `secretKey`. The produced output is the original plaintext message \(or an exception in case of incorrect decryption key or unmatching `authTag`\).
177+
The `decrypt_ECC(encryptedMsg{ciphertext, nonce, authTag, ciphertextPubKey}, privKey)` function internally first calculates the symmetric encryption shared ECC key `sharedECCKey = privKey * ciphertextPubKey`. It is an EC point, so it should be first transformed to **256-bit AES secret key** though hashing the point's `x` and `y` coordinates. Then the **AES-256-GCM cipher** is used to **decrypt** the `ciphertext` + `nonce` + `authTag` by the 256-bit shared secret key `secretKey`. The produced output is the original plaintext message (or an exception in case of incorrect decryption key or unmatching `authTag`).
178178

179179
The output from the above code looks like this:
180180

181-
```text
181+
```
182182
original msg: b'Text to be encrypted by ECC public key and decrypted by its corresponding ECC private key'
183183
encrypted msg: {'ciphertext': b'b5953b3082fcefdbde91dd3c03cf83dde0822c19be6ae906a634db65115295e7cbcd7a1a492d69ba5be91990c70d8df9dc84360cf554f155ef81ce1f0ad44bd9fdabbc5f960517089262b3390e61b37610012bee4e6bcae335', 'nonce': b'9d55f4b5c87fff773d0457f3b23a953e', 'authTag': b'5c9d339778925aa4e44f43252a28681d', 'ciphertextPubKey': '0x21dbc985b625f2a42d0f86fc234b49b55477928bae73dfac73bafd9bed50abe70'}
184184
decrypted msg: b'Text to be encrypted by ECC public key and decrypted by its corresponding ECC private key'
185185
```
186186

187187
Enjoy the above example, **play with it**, try to understand how exactly it works, try to change the underlying ECC curve, try to change the symmetric encryption algorithm, try to decrypt the ciphertext with wrong private key.
188-

asymmetric-key-ciphers/ecdh-key-exchange-examples.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ECDH Key Exchange - Examples
22

3-
Now let's implement the **ECDH** algorithm \(Elliptic Curve Diffie–Hellman Key Exchange\) in Python.
3+
Now let's implement the **ECDH** algorithm (Elliptic Curve Diffie–Hellman Key Exchange) in Python.
44

55
We shall use the `tinyec` library for ECC in Python:
66

@@ -40,11 +40,11 @@ print("Equal shared keys:", aliceSharedKey == bobSharedKey)
4040

4141
Run the above code example: [https://repl.it/@nakov/ECDH-Key-Exchange-in-Python](https://repl.it/@nakov/ECDH-Key-Exchange-in-Python).
4242

43-
The **elliptic curve** used for the ECDH calculations is **256-bit** named curve `brainpoolP256r1`. The **private keys** are **256-bit** \(64 hex digits\) and are generated randomly. The **public keys** will be **257 bits** \(65 hex digits\), due to **key compression**.
43+
The **elliptic curve** used for the ECDH calculations is **256-bit** named curve `brainpoolP256r1`. The **private keys** are **256-bit** (64 hex digits) and are generated randomly. The **public keys** will be **257 bits** (65 hex digits), due to **key compression**.
4444

4545
The **output** of the above code looks like this:
4646

47-
```text
47+
```
4848
Alice public key: 0x66c808e6b5be6d6620934bc6ffa2b8b47f9786c002bfb06d53a0c27535641a5d1
4949
Bob public key: 0x7d15195432d1ac7f38aeb054d07d9b2e1faa913b78ad04d5efdd4a1ee8d9a3191
5050
Now exchange the public keys (e.g. through Internet)
@@ -53,5 +53,4 @@ Bob shared key: 0x90f5a1cf2ed1dbb0322178df6bb0dd72c541884618b2989a3e5e663198667a
5353
Equal shared keys: True
5454
```
5555

56-
Due to randomization, if you run the above code, the **keys will be different**, but the calculated **shared secret** for Alice and Bob at the end will always be **the same**. The generated **shared secret** is a **257-bit** integer \(compressed EC point for 256-bit curve, encoded as 65 hex digits\).
57-
56+
Due to randomization, if you run the above code, the **keys will be different**, but the calculated **shared secret** for Alice and Bob at the end will always be **the same**. The generated **shared secret** is a **257-bit** integer (compressed EC point for 256-bit curve, encoded as 65 hex digits).

0 commit comments

Comments
 (0)