*Authors: João Paulo Barraca, Vitor Cunha, Paulo C. Bartolomeu, Alfredo Matos, Catarina Silva*

# Slides

Download here

# Introduction

In this guide we will develop programs that use cryptographic methods,
relying in the **Python3 Cryptography** module.
The module can be installed using the typical package management methods
(e.g, `apt install python3-cryptography`

), or using the `pip3`

tool
(e.g. `pip3 install cryptography`

). The `apt`

method is preferred to `pip3`

.

# RSA

## RSA key pair generation

Create a small program to generate an `RSA`

key pair, with a key length specified by the user (1024, 2048, 3072 or 4096). The program must save the key pair in two files, one for the private key and the other one for the public key, whose names should also be specified by the user. The keys can be saved as binary blobs but, probably, the `PEM`

format will be more appropriate.

Run the program, several times, varying the key length and register the elapsed time using the `time`

program in the shell (use `man time`

for more information), for example:

```
time python keygen.py ./pub.txt ./priv.txt 4096
```

**Questions:**

- What do you think of using 4096 bit keys by default in relation to speed?
- How the actual key size varies with the number of bits?

`RSA`

Encryption

Create a small program to encrypt a file using the `RSA`

algorithm.

The user must indicate the following data:

- Name of the original file to encrypt
- Name of the file with the public key
- Name for the encrypted file.

For the encryption select the `PKCS #1`

padding scheme. Note that this scheme is not recommended for new applications. Also, *pay attention to the size of the original file*, i.e., the file to encrypt. Using the `PKCS #1`

default configuration, the block size is equal to the key size minus eleven bytes (eleven bytes for padding). So, for example using a 1024 bits `RSA`

key (128 bytes), the block size is 117 bytes (128 - 11).

`RSA`

Decryption

Create a small program to decrypt the contents of a file, whose name is
provided by the user, using the `RSA`

algorithm. The user must also indicate:

- Name of the encrypted file;
- Name of the file to save the decrypted content;
- Name of the file containing the private key to use.

## Large file encryption

As should be known by now, `RSA`

encryption is not efficient and is not
recommended to encrypt data bigger than its block size. Let’s conduct a benchmark.

### Symmetric vs. Asymmetric cryptography benchmark

Generate two files with 100 kB and 10 MB of size. Using these files and the `time`

application, register the time it takes to encrypt and decrypt these files with `RSA`

(key = 1024 bits) and `AES128`

. Employ the applications developed in this guide and in the previous one.

The following bash command can be used to generate a 100 kB file:

```
dd if=/dev/zero of=file.txt bs=1024 count=100
```

### Symmetric and Asymmetric cryptography combination

Consider a large file (500 MB, for example) that you want to
send to some person, with the guarantee that only that person can
decrypt the file. More, you have the public key of that person, and you
are not able to contact the person before sending the file. So, you have
a big file to transmit to a person, from which you know the public key,
but the process will be very slow if you encrypt the file using `RSA`

.
However, you can use any other encryption algorithm to encrypt the file, but remember you want that only the receiver must be able to decrypt the file.

**Questions:**
What combination of encryption technologies allow to efficiently send the file to the recipient, with the guarantee that only that person can decrypt the file?

A typical solution is called *Hybrid Encryption*, which combines two
ciphers, a symmetric to encrypt the file with a random key, and a
asymmetric to encrypt the key used in the previous step.

Implement a program that is able to encrypt/decrypt a large file using the `AES128`

algorithm, employing a randomly generated secret. The secret should be supplied to the intended receiver ciphered with `RSA`

using its own public key. The receiver should be able to reverse the process and obtain the original version of the large file. The program should accept the following arguments:

- Operation to perform (encrypt/decrypt);
- Name of the (large) file to encrypt/decrypt;
- Name of the file with the key to be used (public/private).

**Questions:**

- With this method, what is sent to the destination?
- Should we always send the pubic key?

# Elliptic curves

Elliptic Curve Cryptography (`ECC`

) is a lot different from `RSA`

.

First, whilst in `RSA`

one chooses the length of the `RSA`

modulus (in
bits), in `ECC`

one chooses a curve, and the curve defines the key length.

Second, the private and public keys that belong to the same key pair
are of a different nature: the *private key is an integer* (a
scalar), whilst the *public key is a two-coordinate point*. The
public component is a point given by the multiplication of the
private key with a so-called curve generator (`G`

), which is a point
of the curve. Since the sum of two points defines a new point
(elliptic curves have a special algebra…), and the multiplication
of `G`

by the private key (a scalar) is nothing more than a sum of `G`

values, it is simple to conclude that the public key is a point.

Third, there is no such thing as an encryption with a public key and a posterior decryption with the corresponding private key. This is not used at all. Instead, a method similar to a Diffie-Hellman key agreement is used. For encrypting a message to a receiver B, the sender A uses B’s public and a new private key to compute a point in the curve, and from that point derives a secret, symmetric key. The message is then encrypted with that symmetric key and sent to B, together with the public component of the random private key created by A. The receiver B multiplies the received public key with its own private key and reaches the same point in the curve, which it can use to derive the exact same secret, symmetric key and use it to decipher the message.

There are many elliptic curves, both proposed in standards and
other publications. NIST proposed 15 curves, known as `P`

, `B`

and `K`

curve (5 of each). The name stems from the mathematical elements
used in the curves – `P`

from prime, `B`

from binary, `K`

from Koblitz, a
variant a `B`

curves. Other curves are recommended by *de facto*
standards, such as `RFC 7748`

, which describes `Curve25519`

and
`Curve448`

). The SafeCurves
publication provides some guidelines for selecting a god curve.

## ECC key pair generation

`ECC`

key pair generation is fairly simple. First, one chooses a
curve; we will use `P-521`

.

Then, we generate a random private key for that curve. This is a 521-bit random integer. Then, from that private key, we generate the public key.

Create a program the generates a key pair and saves it in a file.
The private component should be protected by a password, provided as
a program parameter. You can use the `PEM`

format for encapsulating
each of the keys. We will assume this program will be called `p256_gen`

.

```
p256_gen one_password > KPair
```

*Note*: you can generate two `PEM`

contents, one for the private
component, another for the public component, and store them in the
same `PEM`

file. We will consider this approach below.

## Secure messaging with public encryption and private decryption

Create a program `ECC_encrypt`

that encrypts the contents received
from the standard input to the standard output. The program should
have a parameter a file containing the public of the receiver.

The contents produced must contain both the encrypted input and the
originator’s public key. You can use any message format for that,
for instance, `JSON`

(do not forget to use `Base64`

for encoding binary
contents into strings for `JSON`

). For symmetric encryption, you can
use `AES`

in `CTR`

mode and an `IV`

derived from the secret key (e.g., by
hashing it).

```
ECC_encrypt KPair < plaintext > ciphertext
```

Create a program `ECC_decrypt`

that decrypts the contents received
from the standard input to the standard output. The program should
have as parameters a file containing the private key of the receiver
and a password for having access to that private key. The format of
the input is the one produced by `ECC_encrypt`

.

```
ECC_decrypt KPair one_password < ciphertext > recovered_plaintex
```

After these two command, the contents of `plaintext`

should be equal
to the contents of `recovered_plaintext`

.