Commit a9031b9c authored by Amirali Sanatinia's avatar Amirali Sanatinia
Browse files

Initial commit

parent e8cddef1
Loading
Loading
Loading
Loading
+16 −9
Changes for Dockerfile: 16 added lines, 9 removed lines.
Original line number Diff line number Diff line
FROM jupyter/<notebook>:<version hash>
FROM jupyter/minimal-notebook

# launchbot-specific labels
LABEL name.launchbot.io="Applied Cryptography with Python"
LABEL workdir.launchbot.io="/home/jovyan"
LABEL description.launchbot.io="Applied Cryptography with Python"
LABEL 8888.port.launchbot.io="Start Tutorial"

#Set the working directory
WORKDIR /home/jovyan/

# Modules
COPY requirements.txt /home/jovyan/requirements.txt
RUN pip install -r /home/jovyan/requirements.txt

# Add files
COPY notebooks /home/jovyan/notebooks
COPY data /home/jovyan/data
COPY solutions /home/jovyan/solutions
COPY include /home/jovyan/notebooks/include
COPY *.ipynb /home/jovyan/notebooks/
COPY private_key.der /home/jovyan/notebooks/
COPY private_key.pem /home/jovyan/notebooks/
COPY public_key.der /home/jovyan/notebooks/

# Modules
RUN pip install cryptography

# Allow user to write to directory
USER root
@@ -22,4 +29,4 @@ USER $NB_USER
EXPOSE 8888

# Start the notebook server
CMD jupyter notebook --no-browser --port 8888 --ip=0.0.0.0 --NotebookApp.token='' --NotebookApp.disable_check_xsrf=True --NotebookApp.iopub_data_rate_limit=1.0e10
CMD jupyter notebook --no-browser --port 8888 --ip='0.0.0.0' --NotebookApp.token='' --NotebookApp.disable_check_xsrf=True --NotebookApp.iopub_data_rate_limit=1.0e10
+3 −3
Changes for README.md: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
# ${COURSE TITLE GOES HERE}
# ${Applied Cryptography with Python}

![Powered by Jupyter Logo](https://cdn.oreillystatic.com/images/icons/powered_by_jupyter.png)

This project contains the Jupyter Notebooks and the associated Dockerfile for ${INSTRUCTOR} _${TITLE}_. It contains both the exercises (/notebooks) and the solutions (/solutions), as well as any data or files needed (/data).
This project contains the Jupyter Notebooks and the associated Dockerfile for ${Amirali Sanatinia} _${Applied Cryptography with Python}_. It contains both the exercises (/notebooks) and the solutions (/solutions), as well as any data or files needed (/data).

This is a public repository so there is no need to create an account to download its contents. To download the source code from this page, click the 'Cloud' icon on the top right hand, above where the latest commit is detailed.

To download via git from your preferred terminal application, type: 

```git clone https://resources.oreilly.com/live-training/${COMPLETE URL}```
```git clone https://resources.oreilly.com/live-training/applied-cryptography-with-python```

## Running Jupyter Locally via Docker

+65 −0
Changes for notebooks/0. Math Background.ipynb: 65 added lines, 0 removed lines.
Original line number Diff line number Diff line
%% Cell type:markdown id: tags:

# Math Background

%% Cell type:markdown id: tags:

Here we shortly review some math background. Namely, exponentiation, logarithm, xor, and modulo.

%% Cell type:markdown id: tags:

## XOR

%% Cell type:markdown id: tags:

XOR or exclusive or, is one of the widely used logic operators, specially in cryptography. It is usually shown with ⊕. XOR is a binary operator and the value of operation is 1, when only one of the operands is 1.

   - $ 1 \oplus 1 = 0 $
   - $ 0 \oplus 0 = 0 $
   - $ 1 \oplus 0 = 1 $
   - $ 0 \oplus 1 = 1 $



%% Cell type:markdown id: tags:

## Modulo

%% Cell type:markdown id: tags:

Module operation gives us the remainder of division. We use *mod* or *%* as notation.

    a = b * n + c
    a % b = c
    a % n = c

  - $(a * b) \mod n = (a \mod n * b \mod n) \mod n$
  - $(a + b) \mod n = (a \mod n + b \mod n) \mod n$

A few numerical examples:

  - $3 \mod 5 = 3$
  - $7 \mod 5 = 2$
  - $42 \mod 5 = (6 \mod 5 * 7 \mod 5 ) = (1 * 2 \mod 5) = 2$

%% Cell type:markdown id: tags:

## Exponentiation

%% Cell type:markdown id: tags:

Exponentiation is a mathematical operation involving two numbers, represented as $b^n$. Where b is the base, and n is power or exponent. It simply translates into multiplying $b$, $n$ times by it self.

$2 ^ 3$ = 2 \* 2 \* 2

%% Cell type:markdown id: tags:

## Logarithm

%% Cell type:markdown id: tags:

Logarithm is the inverse operation of exponentiation. If $a = b^n$, then $ \log_b a$, is to find how many times the base ($b$), needs to be mulitplied by itself to produce $a$.

If $a = 16 = 2^4$, then:

$log_2 16 = 4$
+43 −0
Changes for notebooks/1. Introduction.ipynb: 43 added lines, 0 removed lines.
Original line number Diff line number Diff line
%% Cell type:markdown id: tags:

# Applied cryptography with Python

%% Cell type:markdown id: tags:

 - Cryptography is ubiquitous today
 - From mobile phones to wireless communication
 - Supported in almost every programming language
 - It is even embedded in the CPUs
 - It is not hard to do crypto right but...

 <img src="include/crypto_failures.png" width="750">

%% Cell type:markdown id: tags:

We will look at the basic blocks of modern crypto using Python. There are a number of crypto libraries in Python:

 - **pycrypto** (oldest and most widely used)
 - **m2crypto** (SWIG binding)
 - **cryptography** (PY2, PY3, PyPy, OpenSSL CFFI binding)


We will use the cryptography library. You can download the library from [here](https://cryptography.io/) and follow the instructions. You should be able to install the library using the following command. You need to have pip installed.

```bash
pip install cryptography
```

To install pip, follow the instructions [here](https://pip.pypa.io/)

%% Cell type:markdown id: tags:

## Cyrptography.io
Cryptography components are divided into different submodules. Following is a list of these submodules (not exhaustive)

* Primitive Crypto Blocks (*cryptography.hazmat*)
 * Message Digest and Hashing algorithms (*cryptography.hazmat.primitives.hashes*)
 * Symmetric encryption algorithms (*cryptography.hazmat.primitives.ciphers*)
 * Asymmetric encryption algorithms (*cryptography.hazmat.primitives.asymmetric*)
 * Key derivation functions (*cryptography.hazmat.primitives.kdf*)
* X.509 Ecosystem (*cryptography.x509*)
* Full high level crypto recipe (*cryptography.fernet*)
+303 −0
Changes for notebooks/2. Hashing Algorithms.ipynb: 303 added lines, 0 removed lines.
Original line number Diff line number Diff line
%% Cell type:markdown id: tags:

# Hashing Algorithms

%% Cell type:markdown id: tags:

The goal is to have a long message as input and produce an output which is much shorter, called the hash or message digest. Furthermore, we want it to have certain properties.

- **Input**: long message
- **Output**: short fixed size block (called hash or message digest)

*We want the same input always produces the same output (deterministic)*

%% Cell type:markdown id: tags:

## *<font color=" #6495ED">Exercise</font>*

 - A *non* security related example of hash functions?
 - A security related example of hash functions?

%% Cell type:markdown id: tags:

*** There is a difference between hash functions and cryptographic hash functions ***

%% Cell type:markdown id: tags:

### Desired properties
  - Pre-image: Given a hash $h$ it is computationally infeasible to find a message $m$ that produces $h$
  - Second preimage: Given message m, it is computationally infeasible to find a message $m’$, ($m ≠ m’$) such that, $h(m) = h(m’)$
  - Collisions: It is computationally difficult to find any two messages $m, m’$ $(m ≠ m’)$ such that, $h(m) = h(m’)$


**Examples**:
 - Recommended Hash Algorithm (SHA-2, SHA-3) by NIST
 - <strike>SHA-1</strike>: output 160 bits being phased out (shattered.io)
 - <strike>MD2, MD4, and MD5</strike> by Ron Rivest [RFC1319, 1320, 1321]

<br>
source: shattered.io
<br>
<img src="include/shattered.png" width="400">
<img src="include/shattered_diagram.png" width="400">

%% Cell type:markdown id: tags:

<br>

%% Cell type:markdown id: tags:

### SHA Family

Secure Hash Algorithm (SHA) family, is a series of hashing algorithms. Ranging from SHA-0 to SHA-3. SHA-0 should never be used, it's advised to move from SHA-1 to SHA-2. SHA-3 is the most recent version, standardized by NIST.

 * SHA-1: Digest size (160), Block size (512)
 * SHA-2: Digest size (224, 256, 384, or 512), Block size (512, 1024)
 * SHA-3: Digest size (224, 256, 384, 512), Block size (1600)

%% Cell type:code id: tags:

``` python
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
import base64 # to produce human readable encoding of the bytes

digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"O'Reilly")
digest.update(b"Crypto")
msg_digest = digest.finalize()
# Notice the output size of the digest
print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))

print()

digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(b"O'ReillyCrypto")
msg_digest = digest.finalize()
# Notice the output size of the digest
print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))

print()
```

%% Cell type:markdown id: tags:

## <font color=" #6495ED">Exercise</font>

 - Let's explore what other hashing algorithms are available and use a different one.
 - Change "O'ReillyCrypto", to "O'Reilly Crypto" and see check the result

%% Cell type:markdown id: tags:

### Python Builtin Support

%% Cell type:markdown id: tags:

*"Additional algorithms may also be available depending upon the OpenSSL library that Python uses on your platform. On most platforms the sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256() are also available."*

source: https://docs.python.org/3/library/hashlib.html

%% Cell type:markdown id: tags:

## *<font color=" #b74138">Solution</font>*

%% Cell type:code id: tags:

``` python
import hashlib
print(hashlib.algorithms_available)
```

%% Cell type:code id: tags:

``` python
sha256 = hashlib.sha256()
sha256.update(b"O'Reilly Crypto")

msg_digest = sha256.digest()
# Notice the output size of the digest
print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))
```

%% Cell type:markdown id: tags:

## <font color=" #6495ED">Exercise</font>
 - Use a different hashing algorithm and compare the digest size and speed

%% Cell type:markdown id: tags:

## *<font color=" #b74138">Solution</font>*

%% Cell type:code id: tags:

``` python
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes

digest = hashes.Hash(hashes.SHA3_512(), backend=default_backend())
digest.update(b"O'ReillyCrypto")
msg_digest = digest.finalize()

print ("msg_digest:", len(msg_digest), len(msg_digest) * 8)
print ("base64 encoding:", base64.b64encode(msg_digest))
```

%% Cell type:code id: tags:

``` python
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
import time
import os

msg = os.urandom(1024 * 1024)
loops = 500

s = time.time()

for i in range(loops):
    digest = hashes.Hash(hashes.SHA3_256(), backend=default_backend())
    digest.update(msg)
    msg_digest = digest.finalize()

e = time.time()

print ("{} loops of SHA3_256 took: {} seconds".format(loops, e - s))

s = time.time()

for i in range(loops):
    digest = hashes.Hash(hashes.MD5(), backend=default_backend())
    digest.update(msg)
    msg_digest = digest.finalize()

e = time.time()

print ("{} loops of MD5 took: {} seconds".format(loops, e - s))
```

%% Cell type:markdown id: tags:

## <font color=" #6495ED">Exercise</font>

 - Let's explore the impact of the size of the message on the speed of our hashing

%% Cell type:markdown id: tags:

## *<font color=" #b74138">Solution</font>*

%% Cell type:code id: tags:

``` python
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
import time
import os

loops = 50

for msg_size in range(1, 10):
    s = time.time()

    msg = os.urandom(1024 * 1024 * msg_size)

    for i in range(loops):
        digest = hashes.Hash(hashes.SHA3_256(), backend=default_backend())
        digest.update(msg)
        msg_digest = digest.finalize()

    e = time.time()

    print ("{} loops of SHA3_256 over {} bytes took: {} seconds".format(loops, len(msg), e - s))
```

%% Cell type:markdown id: tags:

### Hash-based message authentication code (HMAC)

HMACs are used for message authentications combined with a secret key. This provide integrity check and authentication. An attacker can not forge the digest without knowing the secret key. Same message produces different digests for different keys.

<img src="include/SHAhmac.png" width="600">

image source: wikipedia

%% Cell type:markdown id: tags:

$ HMAC(K,m) = H((K\oplus opad) || H((K \oplus ipad) || m))$

%% Cell type:markdown id: tags:

### HMAC Calculation

%% Cell type:code id: tags:

``` python
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hmac, hashes
import os
import base64

hmc_key = k = os.urandom(16)
hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())
hmc.update(b"O'ReillyCrypto")
hmc_sig = hmc.finalize()
print (base64.b64encode(hmc_sig))
```

%% Cell type:markdown id: tags:

### HMAC Verification

%% Cell type:code id: tags:

``` python
# Verification Successufl
hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())
hmc.update(b"O'ReillyCrypto")
hmc.verify(hmc_sig)
```

%% Cell type:markdown id: tags:

## <font color=" #6495ED">Exercise</font>

 - Let's change the calculated HMAC and see what happens when the two HMACs don't match

%% Cell type:markdown id: tags:

## *<font color=" #b74138">Solution</font>*

%% Cell type:code id: tags:

``` python
# Verification Fails (Wrong HMAC)
hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())
hmc.update(b"O'ReillyCrypto")
hmc.verify(hmc_sig+b"1")
```

%% Cell type:code id: tags:

``` python
# Verification Fails (Wrong Message)
hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())
hmc.update(b"O'ReillyCrypto1")
hmc.verify(hmc_sig)
```

%% Cell type:code id: tags:

``` python
# Verification Fails (Wrong Key)
hmc = hmac.HMAC(os.urandom(16), hashes.SHA1(), default_backend())
hmc.update(b"O'ReillyCrypto")
hmc.verify(hmc_sig)
```

%% Cell type:code id: tags:

``` python
```
Loading