├── .gitignore ├── 0. Math Background.ipynb ├── 1. Introduction.ipynb ├── 2. Hashing Algorithms.ipynb ├── 3. Symmetric Encryption.ipynb ├── 4. Asymmetric Encryption.ipynb ├── 5. Key Derivation Functions (KDF).ipynb ├── 6. Pretty Good Privacy (PGP).ipynb ├── Dockerfile ├── LICENSE ├── README.md └── include ├── CBC1.png ├── CBC_dec.png ├── CBC_enc.png ├── CTR_dec.png ├── CTR_enc.png ├── ECB1.png ├── ECB2.png ├── ECB_dec.png ├── ECB_enc.png ├── PGP_diagram.png ├── RSA_OAEP.png ├── SHAhmac.png ├── crypto_failures.png ├── shattered.png ├── shattered_diagram.png ├── sym_vs_asym.png └── tux.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /0. Math Background.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Math Background" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Here we shortly review some math background. Namely, exponentiation, logarithm, xor, and modulo." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## XOR" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "XOR or exclusive or, is one of the widely used logic operators, especially 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.\n", 29 | "\n", 30 | " - $ 1 \\oplus 1 = 0 $ \n", 31 | " - $ 0 \\oplus 0 = 0 $\n", 32 | " - $ 1 \\oplus 0 = 1 $\n", 33 | " - $ 0 \\oplus 1 = 1 $\n", 34 | "\n", 35 | "\n" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "## Modulo" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "Module operation gives us the remainder of division. We use *mod* or *%* as notation.\n", 50 | "\n", 51 | " a = b * n + c\n", 52 | " a % b = c\n", 53 | " a % n = c\n", 54 | " \n", 55 | " - $(a * b) \\mod n = (a \\mod n * b \\mod n) \\mod n$\n", 56 | " - $(a + b) \\mod n = (a \\mod n + b \\mod n) \\mod n$\n", 57 | " \n", 58 | "A few numerical examples:\n", 59 | "\n", 60 | " - $3 \\mod 5 = 3$\n", 61 | " - $7 \\mod 5 = 2$\n", 62 | " - $42 \\mod 5 = (6 \\mod 5 * 7 \\mod 5 ) = (1 * 2 \\mod 5) = 2$" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "## Exponentiation" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "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.\n", 77 | "\n", 78 | "$2 ^ 3$ = 2 \\* 2 \\* 2" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "## Logarithm" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": { 91 | "collapsed": true 92 | }, 93 | "source": [ 94 | "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$.\n", 95 | "\n", 96 | "If $a = 16 = 2^4$, then:\n", 97 | "\n", 98 | "$log_2 16 = 4$ " 99 | ] 100 | } 101 | ], 102 | "metadata": { 103 | "kernelspec": { 104 | "display_name": "Python 3", 105 | "language": "python", 106 | "name": "python3" 107 | }, 108 | "language_info": { 109 | "codemirror_mode": { 110 | "name": "ipython", 111 | "version": 3 112 | }, 113 | "file_extension": ".py", 114 | "mimetype": "text/x-python", 115 | "name": "python", 116 | "nbconvert_exporter": "python", 117 | "pygments_lexer": "ipython3", 118 | "version": "3.6.1" 119 | } 120 | }, 121 | "nbformat": 4, 122 | "nbformat_minor": 2 123 | } 124 | -------------------------------------------------------------------------------- /1. Introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Applied Modern Cryptography in Python (PyCon 2017)" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | " - Cryptography is ubiquitous today\n", 15 | " - From mobile phones to wireless communication\n", 16 | " - Supported in almost every programming language \n", 17 | " - It is even embedded in the CPUs\n", 18 | " - It is not hard to do crypto right but...\n", 19 | " \n", 20 | " " 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "We will look at the basic blocks of modern crypto using Python. There are a number of crypto libraries in Python:\n", 28 | "\n", 29 | " - **pycrypto** (oldest and most widely used)\n", 30 | " - **m2crypto** (SWIG binding)\n", 31 | " - **cryptography** (PY2, PY3, PyPy, OpenSSL CFFI binding)\n", 32 | "\n", 33 | "\n", 34 | "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. \n", 35 | "\n", 36 | "```bash\n", 37 | "pip install cryptography\n", 38 | "```\n", 39 | "\n", 40 | "To install pip, follow the instructions [here](https://pip.pypa.io/)" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "## Cyrptography.io\n", 48 | "Cryptography components are divided into different submodules. Following is a list of these submodules (not exhaustive)\n", 49 | "\n", 50 | "* Primitive Crypto Blocks (*cryptography.hazmat*)\n", 51 | " * Message Digest and Hashing algorithms (*cryptography.hazmat.primitives.hashes*)\n", 52 | " * Symmetric encryption algorithms (*cryptography.hazmat.primitives.ciphers*)\n", 53 | " * Asymmetric encryption algorithms (*cryptography.hazmat.primitives.asymmetric*)\n", 54 | " * Key derivation functions (*cryptography.hazmat.primitives.kdf*)\n", 55 | "* X.509 Ecosystem (*cryptography.x509*)\n", 56 | "* Full high level crypto recipe (*cryptography.fernet*)" 57 | ] 58 | } 59 | ], 60 | "metadata": { 61 | "kernelspec": { 62 | "display_name": "Python 3", 63 | "language": "python", 64 | "name": "python3" 65 | }, 66 | "language_info": { 67 | "codemirror_mode": { 68 | "name": "ipython", 69 | "version": 3 70 | }, 71 | "file_extension": ".py", 72 | "mimetype": "text/x-python", 73 | "name": "python", 74 | "nbconvert_exporter": "python", 75 | "pygments_lexer": "ipython3", 76 | "version": "3.6.1" 77 | } 78 | }, 79 | "nbformat": 4, 80 | "nbformat_minor": 2 81 | } 82 | -------------------------------------------------------------------------------- /2. Hashing Algorithms.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hashing Algorithms" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "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.\n", 15 | "\n", 16 | "- **Input**: long message\n", 17 | "- **Output**: short fixed size block (called hash or message digest)\n", 18 | " \n", 19 | "*We want the same input always produces the same output (deterministic)*" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "## *Exercise*\n", 27 | "\n", 28 | " - A *non* security related example of hash functions?\n", 29 | " - A security related example of hash functions?" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "*** There is a difference between hash function and cryptographic hash functions ***" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "### Desired properties\n", 44 | " - Pre-image: Given a hash *h* it is computationally infeasible to find a message *m* that produces *h*\n", 45 | " - Second preimage: Given message m, it is computationally infeasible to find a message m’, (m ≠ m’) such that, h(m) = h(m’)\n", 46 | " - Collisions: It is computationally difficult to find any two messages m, m’ (m ≠ m’) such that, h(m) = h(m’)\n", 47 | " \n", 48 | "\n", 49 | "**Examples**:\n", 50 | " - Recommended Hash Algorithm (SHA-2, SHA-3) by NIST\n", 51 | " - SHA-1: output 160 bits being phased out (shattered.io)\n", 52 | " - MD2, MD4, and MD5 by Ron Rivest [RFC1319, 1320, 1321]\n", 53 | " \n", 54 | "
\n", 55 | "source: shattered.io\n", 56 | "
\n", 57 | "\n", 58 | "" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "
" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "### SHA Family\n", 73 | "\n", 74 | "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, published in 2015.\n", 75 | "\n", 76 | " * SHA-1: Digest size (160), Block size (512)\n", 77 | " * SHA-2: Digest size (224, 256, 384, or 512), Block size (512, 1024)\n", 78 | " * SHA-3: Digest size (224, 256, 384, 512), Block size (1600)" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "from cryptography.hazmat.backends import default_backend\n", 88 | "from cryptography.hazmat.primitives import hashes\n", 89 | "import base64 # to produce human readable encoding of the bytes\n", 90 | "\n", 91 | "digest = hashes.Hash(hashes.SHA256(), backend=default_backend())\n", 92 | "digest.update(b\"PyCon\")\n", 93 | "digest.update(b\"2017\")\n", 94 | "msg_digest = digest.finalize()\n", 95 | "# Notice the output size of the digest\n", 96 | "print (\"msg_digest:\", len(msg_digest), len(msg_digest) * 8)\n", 97 | "print (\"base64 encoding:\", base64.b64encode(msg_digest))\n", 98 | "\n", 99 | "print()\n", 100 | "\n", 101 | "digest = hashes.Hash(hashes.SHA256(), backend=default_backend())\n", 102 | "digest.update(b\"PyCon2017\")\n", 103 | "msg_digest = digest.finalize()\n", 104 | "# Notice the output size of the digest\n", 105 | "print (\"msg_digest:\", len(msg_digest), len(msg_digest) * 8)\n", 106 | "print (\"base64 encoding:\", base64.b64encode(msg_digest))\n", 107 | "\n", 108 | "print()\n", 109 | "\n", 110 | "digest = hashes.Hash(hashes.SHA256(), backend=default_backend())\n", 111 | "digest.update(b\"PyCon 2017\")\n", 112 | "msg_digest = digest.finalize()\n", 113 | "# Notice the output size of the digest\n", 114 | "print (\"msg_digest:\", len(msg_digest), len(msg_digest) * 8)\n", 115 | "print (\"base64 encoding:\", base64.b64encode(msg_digest))" 116 | ] 117 | }, 118 | { 119 | "cell_type": "markdown", 120 | "metadata": {}, 121 | "source": [ 122 | "## *Exercise *\n", 123 | "\n", 124 | " - Let's explore what other hashing algorithms are available and use a different one.\n", 125 | " - Change \"PyCon2017\", to PyCon 2017\" and see check the result" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "### Python Builtin Support" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "*\"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.\"*\n", 140 | "\n", 141 | "source: https://docs.python.org/3/library/hashlib.html" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "import hashlib\n", 151 | "sha256 = hashlib.sha256()\n", 152 | "sha256.update(b\"PyCon2017\")\n", 153 | "\n", 154 | "msg_digest = sha256.digest()\n", 155 | "# Notice the output size of the digest\n", 156 | "print (\"msg_digest:\", len(msg_digest), len(msg_digest) * 8)\n", 157 | "print (\"base64 encoding:\", base64.b64encode(msg_digest))" 158 | ] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": {}, 163 | "source": [ 164 | "## *Exercise *\n", 165 | "\n", 166 | " - Let's see what other hashing algorithms our python supports." 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "### Hash-based message authentication code (HMAC)\n", 174 | "\n", 175 | "HMACs are used for message authentications combined with a secret key. This provide integrity checking and authentication. An attacker can not forge the digest without knowing the secret key.\n", 176 | "\n", 177 | "\n", 178 | "\n", 179 | "image source: wikipedia" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "$ HMAC(K,m) = H((K\\oplus opad) || H((K \\oplus ipad) || m))$" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "### HMAC Calculation" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": null, 199 | "metadata": {}, 200 | "outputs": [], 201 | "source": [ 202 | "from cryptography.hazmat.backends import default_backend\n", 203 | "from cryptography.hazmat.primitives import hmac, hashes\n", 204 | "import os\n", 205 | "import base64\n", 206 | "\n", 207 | "hmc_key = k = os.urandom(16)\n", 208 | "hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())\n", 209 | "hmc.update(b\"PyCon2017\")\n", 210 | "hmc_sig = hmc.finalize()\n", 211 | "print (base64.b64encode(hmc_sig))" 212 | ] 213 | }, 214 | { 215 | "cell_type": "markdown", 216 | "metadata": {}, 217 | "source": [ 218 | "### HMAC Verification" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": null, 224 | "metadata": { 225 | "collapsed": true 226 | }, 227 | "outputs": [], 228 | "source": [ 229 | "# Verification Successufl\n", 230 | "hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())\n", 231 | "hmc.update(b\"PyCon2017\")\n", 232 | "hmc.verify(hmc_sig)" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": {}, 239 | "outputs": [], 240 | "source": [ 241 | "# Verification Fails\n", 242 | "hmc = hmac.HMAC(hmc_key, hashes.SHA1(), default_backend())\n", 243 | "hmc.update(b\"PyCon2017\")\n", 244 | "hmc.verify(hmc_sig+b\"1\")" 245 | ] 246 | } 247 | ], 248 | "metadata": { 249 | "kernelspec": { 250 | "display_name": "Python 3", 251 | "language": "python", 252 | "name": "python3" 253 | }, 254 | "language_info": { 255 | "codemirror_mode": { 256 | "name": "ipython", 257 | "version": 3 258 | }, 259 | "file_extension": ".py", 260 | "mimetype": "text/x-python", 261 | "name": "python", 262 | "nbconvert_exporter": "python", 263 | "pygments_lexer": "ipython3", 264 | "version": "3.6.1" 265 | } 266 | }, 267 | "nbformat": 4, 268 | "nbformat_minor": 2 269 | } 270 | -------------------------------------------------------------------------------- /3. Symmetric Encryption.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Modern Cryptography\n", 8 | "\n", 9 | "Generally speaking there are two *kinds* of encryption: symmetric and asymmetric.\n", 10 | "\n", 11 | "In symmetric encryption, the parties involved share the ***same*** key.\n", 12 | "\n", 13 | "In asymmetric encryption, the parties use ***different*** keys, that are mathematically ***related*** to each other.\n", 14 | "\n", 15 | "" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "## Symmetric Encryption\n", 23 | "\n", 24 | "In the following, we look at symmetric encryption algorithms. In symmetric crypto, we use the same key for encryption and decryption. **Therefore, the two parties need to establish a secret key between them.** Symmetric encryption can be up to 1000 times faster than asymmetric encryption. Given the support of some crypto algorithm in the CPU and at hardware level, even faster." 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "## *Exercise*\n", 32 | "\n", 33 | " - How should we share this secret key? securely, of course!" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "### Advanced Encryption Algorithm (AES)\n", 41 | "\n", 42 | "AES is based on Rijndael encryption algorithm, designed by Joan Daemen and Vincent Rijmen. It was one of the algorithms submitted to U.S. National Institute of Standards and Technology (NIST) to replace DES and 3DES. It was published in 1998 and accepted and standardized in 2001.\n", 43 | "\n", 44 | " * AES supports key sizes of 128/192/256 bits\n", 45 | " * Block size: 128 bit\n", 46 | " * It's iterative rather than Feistel cipher\n", 47 | " * Treats data in 4 groups of 4 bytes\n", 48 | " * Operates on an entire block in every round\n", 49 | " * Resistant against known attacks\n", 50 | " * Speed and code compactness on many CPUs\n", 51 | " * Rijndael block and key size vary between 128, 192, 256\n", 52 | " * However, in AES block size in 128\n", 53 | " * Number of rounds a function of key size\n", 54 | " * 128 bits 10 rounds\n", 55 | " * 192 bits 12 rounds\n", 56 | " * 256 bits 14 rounds\n", 57 | "\n", 58 | " * Today most implementations use the CPU support (Intel AES-NI)" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "### Block cipher mode of operation\n", 66 | "\n", 67 | "To encrypt messages of arbitrary size with block ciphers, we use the following algorithms, called the modes of operation. They define how to encrypt each block of the plaintext to produce the corresponding cipher text block. Some of these are completely insecure (ECB) and should not be used.\n", 68 | "\n", 69 | " * Electronic Codebook (ECB)\n", 70 | " * Cipher Block Chaining (CBC)\n", 71 | " * Counter (CTR)\n", 72 | " \n", 73 | " \n", 74 | "### Electronic Codebook (ECB)\n", 75 | "\n", 76 | "\n", 77 | "\n", 78 | "\n", 79 | "\n", 80 | "\n", 81 | "### Cipher Block Chaining (CBC)\n", 82 | "\n", 83 | "\n", 84 | "\n", 85 | "\n", 86 | "\n", 87 | "\n", 88 | "### Counter (CTR)\n", 89 | "\n", 90 | "\n", 91 | "" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "collapsed": true 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "import os\n", 103 | "from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n", 104 | "from cryptography.hazmat.backends import default_backend\n", 105 | "key = os.urandom(16) # in bytes, 128 bits\n", 106 | "iv = os.urandom(16)" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": { 113 | "collapsed": true 114 | }, 115 | "outputs": [], 116 | "source": [ 117 | "# ECB Mode, we only need a key\n", 118 | "### *** DO NOT USE ECB. IT IS INSECURE *** ###\n", 119 | "\n", 120 | "cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend())\n", 121 | "encryptor = cipher.encryptor()\n", 122 | "# note that we don't need padding here, since len(\"PyCon 2017 Cypto\") = 16\n", 123 | "cipher_text = encryptor.update(b\"PyCon 2017 Cypto\") + encryptor.finalize()" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "cipher_text" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "print (len(cipher_text))" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "decryptor = cipher.decryptor()\n", 151 | "decryptor.update(cipher_text) + decryptor.finalize()" 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "metadata": { 158 | "collapsed": true 159 | }, 160 | "outputs": [], 161 | "source": [ 162 | "# CBC Mode, we also need an IV\n", 163 | "cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())\n", 164 | "encryptor = cipher.encryptor()\n", 165 | "# note that we don't need padding here, since len(\"PyCon 2017 Cypto\") = 16\n", 166 | "cipher_text = encryptor.update(b\"PyCon 2017 Cypto\") + encryptor.finalize()" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": {}, 173 | "outputs": [], 174 | "source": [ 175 | "cipher_text" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "decryptor = cipher.decryptor()\n", 185 | "decryptor.update(cipher_text) + decryptor.finalize()" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "metadata": { 192 | "collapsed": true 193 | }, 194 | "outputs": [], 195 | "source": [ 196 | "# CTR Mode, we don't need padding in CTR mode. In transforms a block cipher into a stream cipher\n", 197 | "# we only need to introduce the nonce\n", 198 | "cipher = Cipher(algorithms.AES(key), modes.CTR(os.urandom(16)), backend=default_backend())\n", 199 | "encryptor = cipher.encryptor()\n", 200 | "# len(b\"PyCon 2017 Cypto!!\") = 18, however no padding is needed.\n", 201 | "cipher_text = encryptor.update(b\"PyCon 2017 Cypto!!\") + encryptor.finalize()" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "## *Exercise*\n", 209 | "\n", 210 | " - Encrypt the file following text using the ECB, and CBC or CTR mode and compare the results." 211 | ] 212 | }, 213 | { 214 | "cell_type": "code", 215 | "execution_count": null, 216 | "metadata": { 217 | "collapsed": true 218 | }, 219 | "outputs": [], 220 | "source": [ 221 | "plain_text = b\"PyCon is great!!\" * 128" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": { 228 | "collapsed": true 229 | }, 230 | "outputs": [], 231 | "source": [ 232 | "def print_text(text, b64=False):\n", 233 | " for i in range(0, 128, 16):\n", 234 | " if b64:\n", 235 | " pt = base64.b64encode(text[i:i+16])\n", 236 | " else:\n", 237 | " pt = text[i:i+16]\n", 238 | " print (pt)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": { 245 | "collapsed": true 246 | }, 247 | "outputs": [], 248 | "source": [ 249 | "## IMPLEMENTATION" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": null, 255 | "metadata": { 256 | "collapsed": true 257 | }, 258 | "outputs": [], 259 | "source": [ 260 | "print_text(ecb_ct)" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": null, 266 | "metadata": { 267 | "collapsed": true 268 | }, 269 | "outputs": [], 270 | "source": [ 271 | "print_text(cbc_ct)" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": null, 277 | "metadata": { 278 | "collapsed": true 279 | }, 280 | "outputs": [], 281 | "source": [ 282 | "print_text(ctr_ct)" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "## *Extra Activity*\n", 290 | "\n", 291 | "Encrypt the file \"include/tux.png\" using the ECB, and CBC or CTR mode and compare the results.\n", 292 | " - **You need to install the [pillow](https://python-pillow.org/) library**\n", 293 | " - read the image file and get all the pixel values\n", 294 | " - encrypt the pixel values\n", 295 | " - create a new image with new (encrypted) pixel values\n", 296 | " - write your newly crafted image to disk" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": {}, 302 | "source": [ 303 | "To install Pillow, simply use pip or conda:\n", 304 | "\n", 305 | "```bash\n", 306 | " pip install Pillow\n", 307 | " conda install pillow\n", 308 | "```" 309 | ] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": { 314 | "collapsed": true 315 | }, 316 | "source": [ 317 | "The origianl image from Wikipedia. " 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "metadata": {}, 323 | "source": [ 324 | "
\n", 325 | "ECB Encryption of the image with two different keys. The results (colors) are different, because we are using two different keys. However, the patterns inside the data (image) is not hidden.\n", 326 | "
\n", 327 | "
\n", 328 | "\n", 329 | " " 330 | ] 331 | }, 332 | { 333 | "cell_type": "markdown", 334 | "metadata": {}, 335 | "source": [ 336 | "
\n", 337 | "As compared to when we are using the CBC (or CTR) mode. Because we introduce the randomness at the beginning (IV), and we carry this randomness (noise) throughout the encryption the patterns are diminished.\n", 338 | "
\n", 339 | "
\n", 340 | "\n", 341 | "" 342 | ] 343 | }, 344 | { 345 | "cell_type": "markdown", 346 | "metadata": {}, 347 | "source": [ 348 | "## Encryption alone is not good enough\n", 349 | "\n", 350 | "Encrypting your data alone will not protect you from data tampering, meaning an adversary can change the results of your decryption without having access to the key -- all without you noticing. That's where HMACs discussed previously become handy." 351 | ] 352 | }, 353 | { 354 | "cell_type": "markdown", 355 | "metadata": {}, 356 | "source": [ 357 | "### Bit flipping attack" 358 | ] 359 | }, 360 | { 361 | "cell_type": "markdown", 362 | "metadata": {}, 363 | "source": [ 364 | "Since the IV is sent in clear we can change the IV value and change the corresponding plaintext, when using CBC mode.\n", 365 | "\n", 366 | "***Encryption***\n", 367 | "\n", 368 | " - $C_{i}=E_{K}(P_{i}\\oplus C_{i-1})$\n", 369 | " - $ C_{0}=IV$\n", 370 | "\n", 371 | "***Decryption***\n", 372 | " - $P_{i}=D_{K}(C_{i})\\oplus C_{i-1}$\n", 373 | " - $C_{0}=IV$\n", 374 | " \n", 375 | " \n", 376 | "Therefore to change the plaintext value we just need to xor the old plaintext(p), and the new value (t), with the IV:\n", 377 | "\n", 378 | "$IV = IV \\oplus p \\oplus t$\n", 379 | "\n", 380 | "Meaning if the first 4 bytes of the plaint text are: \"1234\" and we want to change it to \"6789\" all we have to do is\n", 381 | "\n", 382 | "$IV[0:4] = IV[0:4] \\oplus 1234 \\oplus 6789$" 383 | ] 384 | }, 385 | { 386 | "cell_type": "markdown", 387 | "metadata": {}, 388 | "source": [ 389 | "## *Exercise*\n", 390 | "\n", 391 | " - Imagine the message is only 16 bytes, \"PyCon2017 Crypto\". Change the year from 2017 to 1991." 392 | ] 393 | }, 394 | { 395 | "cell_type": "code", 396 | "execution_count": null, 397 | "metadata": { 398 | "collapsed": true 399 | }, 400 | "outputs": [], 401 | "source": [ 402 | "def xor(s1, s2):\n", 403 | " return bytes([a ^ b for a,b in zip(s1,s2)])" 404 | ] 405 | }, 406 | { 407 | "cell_type": "code", 408 | "execution_count": null, 409 | "metadata": { 410 | "collapsed": true 411 | }, 412 | "outputs": [], 413 | "source": [ 414 | "iv = os.urandom(16)\n", 415 | "cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())\n", 416 | "encryptor = cipher.encryptor()\n", 417 | "cipher_text = encryptor.update(b\"PyCon2017 Crypto\") + encryptor.finalize()" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": null, 423 | "metadata": {}, 424 | "outputs": [], 425 | "source": [ 426 | "cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())\n", 427 | "decryptor = cipher.decryptor()\n", 428 | "decryptor.update(cipher_text) + decryptor.finalize()" 429 | ] 430 | }, 431 | { 432 | "cell_type": "code", 433 | "execution_count": null, 434 | "metadata": { 435 | "collapsed": true 436 | }, 437 | "outputs": [], 438 | "source": [ 439 | "## IMPLEMENTATION" 440 | ] 441 | }, 442 | { 443 | "cell_type": "markdown", 444 | "metadata": {}, 445 | "source": [ 446 | "
" 447 | ] 448 | }, 449 | { 450 | "cell_type": "markdown", 451 | "metadata": { 452 | "collapsed": true 453 | }, 454 | "source": [ 455 | "## Authenticated Encryption with Associated Data (AEAD)\n", 456 | "\n", 457 | "AEAD provides confidentiality, integrity, and authenticity at once. Such schemes help to mitigate against the bit flipping attacks that we just did. The Galois/Counter Mode (GCM) mode of operation is the recommended schemes to be used. Fortunately, the *cryptography* library already has it implemented." 458 | ] 459 | }, 460 | { 461 | "cell_type": "code", 462 | "execution_count": null, 463 | "metadata": { 464 | "collapsed": true 465 | }, 466 | "outputs": [], 467 | "source": [ 468 | "# GCM Mode, we also need an IV\n", 469 | "cipher = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend())\n", 470 | "encryptor = cipher.encryptor()\n", 471 | "# note that we don't need padding here, since len(\"PyCon2017 Crypto\") = 16\n", 472 | "encryptor.authenticate_additional_data(b\"SOME ADDITIONAL DATA\")\n", 473 | "cipher_text = encryptor.update(b\"PyCon2017 Crypto\") + encryptor.finalize()\n", 474 | "tag = encryptor.tag" 475 | ] 476 | }, 477 | { 478 | "cell_type": "code", 479 | "execution_count": null, 480 | "metadata": {}, 481 | "outputs": [], 482 | "source": [ 483 | "decryptor = Cipher(algorithms.AES(key), modes.GCM(iv,tag), backend=default_backend()).decryptor()\n", 484 | "decryptor.authenticate_additional_data(b\"SOME ADDITIONAL DATA\")\n", 485 | "decryptor.update(cipher_text) + decryptor.finalize()" 486 | ] 487 | }, 488 | { 489 | "cell_type": "markdown", 490 | "metadata": { 491 | "collapsed": true 492 | }, 493 | "source": [ 494 | "## Padding\n", 495 | "\n", 496 | "With some block cipher mode of operations (e.g., CBC) we need to pad the data to the block size. Otherwise, if would throw an exception." 497 | ] 498 | }, 499 | { 500 | "cell_type": "code", 501 | "execution_count": null, 502 | "metadata": { 503 | "collapsed": true 504 | }, 505 | "outputs": [], 506 | "source": [ 507 | "import os\n", 508 | "from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n", 509 | "from cryptography.hazmat.backends import default_backend\n", 510 | "key = os.urandom(16) # in bytes, 128 bits\n", 511 | "\n", 512 | "#CTR\n", 513 | "cipher = Cipher(algorithms.AES(key), modes.CTR(os.urandom(16)), backend=default_backend())\n", 514 | "encryptor = cipher.encryptor()\n", 515 | "# len(\"PyCon 2017 Cryptography\") = 23, but we don't need padding in CTR\n", 516 | "ctr_ct = encryptor.update(b\"PyCon 2017 Cryptography\") + encryptor.finalize()" 517 | ] 518 | }, 519 | { 520 | "cell_type": "code", 521 | "execution_count": null, 522 | "metadata": {}, 523 | "outputs": [], 524 | "source": [ 525 | "#CBC\n", 526 | "cipher = Cipher(algorithms.AES(key), modes.CBC(os.urandom(16)), backend=default_backend())\n", 527 | "encryptor = cipher.encryptor()\n", 528 | "# len(\"PyCon 2017 Cryptography\") = 23, throws an exception\n", 529 | "cbc_ct = encryptor.update(b\"PyCon 2017 Cryptography\") + encryptor.finalize()" 530 | ] 531 | }, 532 | { 533 | "cell_type": "markdown", 534 | "metadata": {}, 535 | "source": [ 536 | "### Public-Key Cryptography Standards (PKCS)\n", 537 | "\n", 538 | "PKCS7 padding is described in RFC 5652. The number of missing bytes (n) to the whole block size is repeated n times.\n", 539 | "\n", 540 | " - For example if the block size is 16,\n", 541 | " - The data is of size 13, the data is padding with 3, 3 times. 03 03 03.\n", 542 | " - The data is of size 14, the data is padded with 2, 2 times. 02 02\n" 543 | ] 544 | }, 545 | { 546 | "cell_type": "markdown", 547 | "metadata": {}, 548 | "source": [ 549 | "## *Exercise*\n", 550 | "\n", 551 | " - Implement PKCS7 padding" 552 | ] 553 | }, 554 | { 555 | "cell_type": "code", 556 | "execution_count": null, 557 | "metadata": { 558 | "collapsed": true 559 | }, 560 | "outputs": [], 561 | "source": [ 562 | "## IMPLEMENTATION\n", 563 | "def pkcs7_pad(text):\n", 564 | " pass" 565 | ] 566 | }, 567 | { 568 | "cell_type": "code", 569 | "execution_count": null, 570 | "metadata": { 571 | "collapsed": true 572 | }, 573 | "outputs": [], 574 | "source": [ 575 | "# Test our implementation of PKCS7 padding\n", 576 | "\n", 577 | "from cryptography.hazmat.primitives import padding\n", 578 | "\n", 579 | "for i in range(16):\n", 580 | " msg = b'A'*i\n", 581 | " padder = padding.PKCS7(128).padder()\n", 582 | " padded_data = padder.update(msg)\n", 583 | " padded_data += padder.finalize()\n", 584 | " assert padded_data == pkcs7_pad(msg)" 585 | ] 586 | } 587 | ], 588 | "metadata": { 589 | "kernelspec": { 590 | "display_name": "Python 3", 591 | "language": "python", 592 | "name": "python3" 593 | }, 594 | "language_info": { 595 | "codemirror_mode": { 596 | "name": "ipython", 597 | "version": 3 598 | }, 599 | "file_extension": ".py", 600 | "mimetype": "text/x-python", 601 | "name": "python", 602 | "nbconvert_exporter": "python", 603 | "pygments_lexer": "ipython3", 604 | "version": "3.6.1" 605 | } 606 | }, 607 | "nbformat": 4, 608 | "nbformat_minor": 2 609 | } 610 | -------------------------------------------------------------------------------- /4. Asymmetric Encryption.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "collapsed": true 7 | }, 8 | "source": [ 9 | "# Asymmetric Encryption\n", 10 | "\n", 11 | "Reminder: In asymmetric encryption schemes, the parties use ***different*** keys, that are mathematically ***related*** to each other." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## *Exercise*\n", 19 | "\n", 20 | " - Why asymmetric encryption is useful?\n", 21 | " - Give a few examples where it can be used?" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": { 27 | "collapsed": true 28 | }, 29 | "source": [ 30 | "### RSA\n", 31 | "\n", 32 | "RSA is an asymmetric encryption algorithm by Ron Rivest, Adi Shamir, and Leonard Adleman. It was published in 1977. Its security is based on the hardness of factorization problem. However, now it has its own problem, called the RSA problem. RSA is slow, and is not used for encrypting large data, but it's mostly used to encrypt the symmetric key that is used for encryption.\n", 33 | "\n", 34 | "\n", 35 | " * p, q, two big prime numbers (private, chosen)\n", 36 | " * n = pq, φ(n) = (p-1)(q-1) (public, calculated)\n", 37 | " * e, with gcd(φ(n), e) = 1, 1 < e < φ(n)\t(public, chosen)\n", 38 | " * d = e - 1 mod φ(n)\t(private, calculated)\n", 39 | " * $E(M) = M^e \\mod n$\n", 40 | " * $D(M) = M^d \\mod n$\n", 41 | " * $D(E(M)) = M^{ed} \\mod n = M$" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "## *Exercise*\n", 49 | "\n", 50 | " - How to test if a number is prime?" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "## RSA EXAMPLE\n", 58 | "\n", 59 | " - p = 5; q = 11 => n = 55\n", 60 | " - φ(n) = 40\n", 61 | " - e = 3 => d = 27\n", 62 | " - Because ed = 1 mod φ(n)\n", 63 | " - Public key: (e, n)\n", 64 | " - Private key: (d, n)\n", 65 | " - Encryption\n", 66 | " - M = 2\n", 67 | " - Encryption(M) = $ M^e\\mod n$ = $2^3\\mod n$ = 8\n", 68 | " - Decryption(8) = $ M^d\\mod n$ = $8^{27} \\mod n$ = 2" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": { 75 | "collapsed": true 76 | }, 77 | "outputs": [], 78 | "source": [ 79 | "2 ** 3 % 55" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": { 86 | "collapsed": true 87 | }, 88 | "outputs": [], 89 | "source": [ 90 | "8 ** 27 " 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": null, 96 | "metadata": { 97 | "collapsed": true 98 | }, 99 | "outputs": [], 100 | "source": [ 101 | "8 ** 27 % 55" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "## *Exercise*\n", 109 | "\n", 110 | " - Why can't we just use asymmetric encryption?" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "### OpenSSL\n", 118 | "\n", 119 | "To generate keys, use the following instructions:\n", 120 | "\n", 121 | "```bash\n", 122 | " openssl genrsa -out private_key.pem 2048\n", 123 | " openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt\n", 124 | " openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der\n", 125 | " ```" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": { 132 | "collapsed": true 133 | }, 134 | "outputs": [], 135 | "source": [ 136 | "%%bash\n", 137 | "openssl genrsa -out private_key.pem 2048\n", 138 | "openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt\n", 139 | "openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": { 146 | "collapsed": true 147 | }, 148 | "outputs": [], 149 | "source": [ 150 | "# import key from a file. E.g., previously generated by OpenSSL\n", 151 | "from cryptography.hazmat.backends import default_backend\n", 152 | "from cryptography.hazmat.primitives import serialization\n", 153 | "\n", 154 | "with open(\"private_key.pem\", \"rb\") as key_file:\n", 155 | " private_key = serialization.load_pem_private_key(\n", 156 | " key_file.read(),\n", 157 | " password=None,\n", 158 | " backend=default_backend())\n", 159 | "public_key = private_key.public_key()" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": { 166 | "collapsed": true 167 | }, 168 | "outputs": [], 169 | "source": [ 170 | "# Generate a 2048 bit private key\n", 171 | "from cryptography.hazmat.backends import default_backend\n", 172 | "from cryptography.hazmat.primitives.asymmetric import rsa\n", 173 | "\n", 174 | "private_key = rsa.generate_private_key(\n", 175 | " public_exponent=65537,\n", 176 | " key_size=2048,\n", 177 | " backend=default_backend())\n", 178 | "# to get the public key\n", 179 | "public_key = private_key.public_key()" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": { 186 | "collapsed": true 187 | }, 188 | "outputs": [], 189 | "source": [ 190 | "2 ** 16 +1 " 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "metadata": { 197 | "collapsed": true 198 | }, 199 | "outputs": [], 200 | "source": [ 201 | "print(bin(2**16 + 1))\n", 202 | "print(bin(2**1 + 1))" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": {}, 208 | "source": [ 209 | "## *Exercise*\n", 210 | "\n", 211 | " - What's wrong with textbook RSA?" 212 | ] 213 | }, 214 | { 215 | "cell_type": "markdown", 216 | "metadata": {}, 217 | "source": [ 218 | "## It's all about padding\n", 219 | "\n", 220 | "Textbook RSA is not IND-CPA secure, therefore we use Optimal Asymmetric Encryption Padding (OAEP). There are also other attacks against RSA with improper padding\n", 221 | "\n", 222 | "\n", 223 | "\n", 224 | "image souce: wikipedia" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": { 231 | "collapsed": true 232 | }, 233 | "outputs": [], 234 | "source": [ 235 | "from cryptography.hazmat.backends import default_backend\n", 236 | "from cryptography.hazmat.primitives import hashes\n", 237 | "from cryptography.hazmat.primitives.asymmetric import padding\n", 238 | "\n", 239 | "message = b\"The SECRET KEY\"\n", 240 | "ciphertext = public_key.encrypt(\n", 241 | " message,\n", 242 | " padding.OAEP(\n", 243 | " mgf=padding.MGF1(algorithm=hashes.SHA1()),\n", 244 | " algorithm=hashes.SHA1(),\n", 245 | " label=None))" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": {}, 252 | "outputs": [], 253 | "source": [ 254 | "print(ciphertext)" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": { 261 | "collapsed": true 262 | }, 263 | "outputs": [], 264 | "source": [ 265 | "from cryptography.hazmat.backends import default_backend\n", 266 | "from cryptography.hazmat.primitives import hashes\n", 267 | "from cryptography.hazmat.primitives.asymmetric import padding\n", 268 | "\n", 269 | "plaintext = private_key.decrypt(\n", 270 | " ciphertext,\n", 271 | " padding.OAEP(\n", 272 | " mgf=padding.MGF1(algorithm=hashes.SHA1()),\n", 273 | " algorithm=hashes.SHA1(),\n", 274 | " label=None))" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": null, 280 | "metadata": {}, 281 | "outputs": [], 282 | "source": [ 283 | "print(plaintext)" 284 | ] 285 | } 286 | ], 287 | "metadata": { 288 | "kernelspec": { 289 | "display_name": "Python 3", 290 | "language": "python", 291 | "name": "python3" 292 | }, 293 | "language_info": { 294 | "codemirror_mode": { 295 | "name": "ipython", 296 | "version": 3 297 | }, 298 | "file_extension": ".py", 299 | "mimetype": "text/x-python", 300 | "name": "python", 301 | "nbconvert_exporter": "python", 302 | "pygments_lexer": "ipython3", 303 | "version": "3.6.1" 304 | } 305 | }, 306 | "nbformat": 4, 307 | "nbformat_minor": 2 308 | } 309 | -------------------------------------------------------------------------------- /5. Key Derivation Functions (KDF).ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Key Derivation Functions (KDF)" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Key derivation is the process of producing one or more keys from a master key, also known as key stretching. The master key can be a password, passphrase, or a Diffie-Hellman negotiated shared key." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "Let's propose our simple KDF as:\n", 22 | "\n", 23 | "$DK = HASH(password)$" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## *Exercise*\n", 31 | "\n", 32 | " - Why this KDF is not good?" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "- There is no noise. Same password, produces same key. (add some randomness)\n", 40 | "- It's too fast to calculate, therefore easy to brute-force. (add iterations, use more expensive functions)" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "$DK = KDF(password, salt, iterations)$" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "## PBKDF2 (Password-Based Key Derivation Function 2)\n", 55 | "\n", 56 | "PBKDF2 is part of PKCS, and replaces the earlier PBKDF1. We need to pass a hashing function that will be used as the HMAC, number of iterations to mitigate brute-force attack, and a salt for rainbow tables." 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "$DK = PBKDF2(PRP, password, salt, iterations, keylen)$\n", 64 | "\n", 65 | "For example in your wireless communication a key is derived as the following:\n", 66 | "\n", 67 | "$Key = PBKDF2(HMAC−SHA1, passphrase, ssid, 4096, 256)$" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": { 74 | "collapsed": true 75 | }, 76 | "outputs": [], 77 | "source": [ 78 | "import os\n", 79 | "from cryptography.hazmat.primitives import hashes\n", 80 | "from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC\n", 81 | "from cryptography.hazmat.backends import default_backend\n", 82 | "salt = os.urandom(16)\n", 83 | "\n", 84 | "# key derivation\n", 85 | "kdf = PBKDF2HMAC(\n", 86 | " algorithm=hashes.SHA256(),\n", 87 | " length=32,\n", 88 | " salt=salt,\n", 89 | " iterations=100000,\n", 90 | " backend=default_backend())\n", 91 | "\n", 92 | "key = kdf.derive(b\"THE_SECRET_PASSWORD\")" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "import base64\n", 102 | "\n", 103 | "print(key, len(key))\n", 104 | "print(base64.b64encode(key))" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": { 111 | "collapsed": true 112 | }, 113 | "outputs": [], 114 | "source": [ 115 | "# Key verification\n", 116 | "kdf = PBKDF2HMAC(\n", 117 | " algorithm=hashes.SHA256(),\n", 118 | " length=32,\n", 119 | " salt=salt,\n", 120 | " iterations=100000,\n", 121 | " backend=default_backend())\n", 122 | "\n", 123 | "kdf.verify(b\"THE_SECRET_PASSWORD\", key)" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "### Password Storage\n", 131 | "\n", 132 | "We can use *PBKDF2* for password storage as well. However, it is recommended to use [scrypt](http://www.tarsnap.com/scrypt.html) that requires large amount of memory instead of just high computation demand." 133 | ] 134 | } 135 | ], 136 | "metadata": { 137 | "kernelspec": { 138 | "display_name": "Python 3", 139 | "language": "python", 140 | "name": "python3" 141 | }, 142 | "language_info": { 143 | "codemirror_mode": { 144 | "name": "ipython", 145 | "version": 3 146 | }, 147 | "file_extension": ".py", 148 | "mimetype": "text/x-python", 149 | "name": "python", 150 | "nbconvert_exporter": "python", 151 | "pygments_lexer": "ipython3", 152 | "version": "3.6.1" 153 | } 154 | }, 155 | "nbformat": 4, 156 | "nbformat_minor": 2 157 | } 158 | -------------------------------------------------------------------------------- /6. Pretty Good Privacy (PGP).ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Pretty Good Privacy (PGP)\n", 8 | "\n", 9 | " - A data encryption/decryption tool\n", 10 | " - Can be used to encrypt and authenticate email, files, etc.\n", 11 | " - Created by Phil Zimmermann in 1991\n", 12 | " - A practical hybrid system that uses symmetric and asymmetric crypto\n", 13 | "\n", 14 | "\n", 15 | "\n", 16 | "image source: wikipedia" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "collapsed": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "#Use GCM\n", 28 | "def enc_key(public_key, message):\n", 29 | " pass\n", 30 | "\n", 31 | "def dec_key(private_key, ciphertext):\n", 32 | " pass\n", 33 | "\n", 34 | "def enc_msg(key, iv, msg):\n", 35 | " pass\n", 36 | "\n", 37 | "def dec_msg(key, iv, ciphertext):\n", 38 | " pass" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": { 45 | "collapsed": true 46 | }, 47 | "outputs": [], 48 | "source": [ 49 | "k1 = os.urandom(16)\n", 50 | "iv = os.urandom(16)\n", 51 | "msg = b\"PyCon 2017 Crypto!!\"\n", 52 | "\n", 53 | "cipher = enc_msg(k1, iv, msg)\n", 54 | "encrypted_key = enc_key(public_key, k1)\n", 55 | "\n", 56 | "decrypted_key = dec_key(private_key, encrypted_key)\n", 57 | "plaintext = dec_msg(decrypted_key, iv, cipher)" 58 | ] 59 | } 60 | ], 61 | "metadata": { 62 | "kernelspec": { 63 | "display_name": "Python 3", 64 | "language": "python", 65 | "name": "python3" 66 | }, 67 | "language_info": { 68 | "codemirror_mode": { 69 | "name": "ipython", 70 | "version": 3 71 | }, 72 | "file_extension": ".py", 73 | "mimetype": "text/x-python", 74 | "name": "python", 75 | "nbconvert_exporter": "python", 76 | "pygments_lexer": "ipython3", 77 | "version": "3.6.1" 78 | } 79 | }, 80 | "nbformat": 4, 81 | "nbformat_minor": 2 82 | } 83 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jupyter/minimal-notebook 2 | 3 | # launchbot-specific labels 4 | LABEL name.launchbot.io="Applied Cryptography with Python" 5 | LABEL workdir.launchbot.io="/home/jovyan" 6 | LABEL description.launchbot.io="Applied Cryptography with Python" 7 | LABEL 8888.port.launchbot.io="Start Tutorial" 8 | 9 | #Set the working directory 10 | WORKDIR /home/jovyan/ 11 | 12 | # Add files 13 | COPY include /home/jovyan/include 14 | COPY *.ipynb /home/jovyan/ 15 | RUN rmdir /home/jovyan/work 16 | 17 | # Modules 18 | RUN pip install cryptography 19 | 20 | # Allow user to write to directory 21 | USER root 22 | RUN chown -R $NB_USER /home/jovyan \ 23 | && chmod -R 774 /home/jovyan 24 | USER $NB_USER 25 | 26 | # Expose the notebook port 27 | EXPOSE 8888 28 | 29 | # Start the notebook server 30 | 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 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Amirali Sanatinia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Applied Modern Cryptography in Python (PyCon 2017) 2 | 3 | [Amirali Sanatinia](http://www.ccs.neu.edu/home/amirali) 4 | 5 | Today we use cryptography in almost everywhere. From surfing the web over https, to working remotely over ssh. Although most developers don't need to implement cryptography primitives, the knowledge and understanding of these building block allows them to better deploy them in their application. In modern crypto we have all the building block to develop secure application. However, we see instances of insecure code everywhere. Most of these vulnerabilities are not because of theoretic shortcomings, but due to bad implementation or a flawed protocol design. Cryptography is a delicate art where nuances matter, and failure to comprehend the subtleties of these building blocks leads to critical vulnerabilities. To add insult to injury most of the resources available are either outdated or wrong, and inarguably, using bad crypto more dangerous than not using it. 6 | 7 | 8 | ## Requirements 9 | 10 | * Python 3 11 | * [Jupyter Notebook](http://jupyter.org/) 12 | * [cryptography](http://cryptography.io/) 13 | 14 | 15 | ## Setup Instructions 16 | You need to have [pip](https://packaging.python.org/) installed. Optinally you can use [virtualenv](https://packaging.python.org/installing/#creating-virtual-environments) for an isolated installation of libraries instead of globally. 17 | 18 | ```bash 19 | $ pip3 install jupyter 20 | $ pip3 install cryptography 21 | ``` 22 | 23 | Alternatively, if you have the conda package manager, you can run: 24 | 25 | ```bash 26 | $ conda create -n crypto python=3.6 jupyter cryptography 27 | $ source activate crypto 28 | $ jupyter notebook 29 | ``` 30 | ## Docker Image 31 | You can also use the following commands to run a dockerized version of this tutorial. 32 | 33 | ```bash 34 | $ docker build -t NAME . 35 | $ docker run -p 8888:8888 NAME 36 | ``` 37 | 38 | Replace NAME with a name for this docker image (e.g., crypto) 39 | -------------------------------------------------------------------------------- /include/CBC1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/CBC1.png -------------------------------------------------------------------------------- /include/CBC_dec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/CBC_dec.png -------------------------------------------------------------------------------- /include/CBC_enc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/CBC_enc.png -------------------------------------------------------------------------------- /include/CTR_dec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/CTR_dec.png -------------------------------------------------------------------------------- /include/CTR_enc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/CTR_enc.png -------------------------------------------------------------------------------- /include/ECB1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/ECB1.png -------------------------------------------------------------------------------- /include/ECB2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/ECB2.png -------------------------------------------------------------------------------- /include/ECB_dec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/ECB_dec.png -------------------------------------------------------------------------------- /include/ECB_enc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/ECB_enc.png -------------------------------------------------------------------------------- /include/PGP_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/PGP_diagram.png -------------------------------------------------------------------------------- /include/RSA_OAEP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/RSA_OAEP.png -------------------------------------------------------------------------------- /include/SHAhmac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/SHAhmac.png -------------------------------------------------------------------------------- /include/crypto_failures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/crypto_failures.png -------------------------------------------------------------------------------- /include/shattered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/shattered.png -------------------------------------------------------------------------------- /include/shattered_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/shattered_diagram.png -------------------------------------------------------------------------------- /include/sym_vs_asym.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/sym_vs_asym.png -------------------------------------------------------------------------------- /include/tux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amiralis/pycon2017_crypto_tutorial/af770374d43df592c1ec6b523060d43122caa2a3/include/tux.png --------------------------------------------------------------------------------