├── E0-Security-Theory ├── Overview.pdf ├── Types of attacks.pdf ├── Chosen plaintext attack.pdf ├── Definitions and concepts.pdf └── README.md ├── S2-Block-ciphers ├── Block ciphers.pdf ├── README.md └── DES.ipynb ├── .gitignore ├── P1-Public-key ├── 1. Public key Encryption.pdf ├── 2. Problems in public key.pdf ├── Diffie-Hellman │ └── Vulnerabilities │ │ ├── README.md │ │ ├── Bad_Groups.ipynb │ │ └── Man_in_the_middle.ipynb ├── RSA │ └── Vulnerabilities │ │ ├── README.md │ │ ├── Jochemsz_May_methods.ipynb │ │ ├── Hastad_broadcast_part2.ipynb │ │ ├── Hastad_Broadcast_Attack.ipynb │ │ ├── Franklin-Reiter_related_message.ipynb │ │ └── Known_e_d_pair.ipynb └── Elgamal │ └── Elgamal_intro.ipynb ├── S3-Message-Integrity ├── Hashes (keyless).pdf ├── Message Authentication Code.pdf ├── README.md └── Key_derivation_functions.ipynb ├── E1-Mathematics ├── Abstract-Algebra │ ├── 3. Rings.pdf │ ├── 2. Groups.pdf │ ├── 4. Fields.pdf │ └── 5. Polynomials.pdf ├── README.md ├── Primes-and-Primality-tests │ ├── README.md │ ├── 2. Solovay_Strassen_test.ipynb │ ├── 1. Fermats_test.ipynb │ └── Untitled.ipynb ├── Lattices │ └── README.md ├── Elliptic-curves │ ├── README.md │ ├── ECDLP │ │ ├── README.md │ │ └── MOV_attack_sage.ipynb │ └── Rational_points_on_elliptic_curves │ │ ├── Chapter_5_Integer_points_on_cubic_curves.ipynb │ │ ├── Chapter_4_Cubic_curves_over_finie_fields.ipynb │ │ ├── Chapter_2_Points_of_finite_order.ipynb │ │ └── Chapter_3_The_group_of_rational_points.ipynb ├── Discrete-Logarithm-Problem │ ├── README.md │ └── 3. Pollard_Rho.ipynb └── Factorization │ ├── README.md │ ├── Pollard_p_minus_1.ipynb │ ├── Fermat_fact_p_q_are_close.ipynb │ └── Coppersmith_factorization_sage.ipynb ├── S4-Authenticated-Encryption ├── AE and AEAD.pdf └── README.md ├── P2-Digital-Signatures ├── 1. Digital Signatures.pdf ├── 2. Hash-Based Signatures.pdf ├── ECDSA │ └── Vulnerabilities │ │ ├── README.md │ │ └── Reset_attack_nonce_reused.ipynb ├── README.md └── RSA-sign │ └── Vulnerabilities │ ├── No_hashing.ipynb │ └── Duplicate signature key selection.ipynb ├── E2-Secret-sharing-schemes ├── Secret_sharing_schemes.pdf └── README.md ├── E3-Homomorphic-Encryption ├── 1. Homomorphic Encryption.pdf ├── Paillier Encryption Scheme.ipynb └── pre_fhe.ipynb ├── S1-PRNGs-and-stream-ciphers ├── Pseudorandomness and Stream Ciphers.pdf ├── README.md └── Linear_congruential_generator.ipynb ├── E-1-Books └── README.md └── README.md /E0-Security-Theory/Overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E0-Security-Theory/Overview.pdf -------------------------------------------------------------------------------- /S2-Block-ciphers/Block ciphers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/S2-Block-ciphers/Block ciphers.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .ipynb_checkpoints 3 | docs 4 | E1 Mathematics/Algebraic Geometry/ 5 | imgs 6 | test.py 7 | test.sage 8 | -------------------------------------------------------------------------------- /E0-Security-Theory/Types of attacks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E0-Security-Theory/Types of attacks.pdf -------------------------------------------------------------------------------- /P1-Public-key/1. Public key Encryption.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/P1-Public-key/1. Public key Encryption.pdf -------------------------------------------------------------------------------- /S3-Message-Integrity/Hashes (keyless).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/S3-Message-Integrity/Hashes (keyless).pdf -------------------------------------------------------------------------------- /E1-Mathematics/Abstract-Algebra/3. Rings.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E1-Mathematics/Abstract-Algebra/3. Rings.pdf -------------------------------------------------------------------------------- /P1-Public-key/2. Problems in public key.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/P1-Public-key/2. Problems in public key.pdf -------------------------------------------------------------------------------- /S4-Authenticated-Encryption/AE and AEAD.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/S4-Authenticated-Encryption/AE and AEAD.pdf -------------------------------------------------------------------------------- /E0-Security-Theory/Chosen plaintext attack.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E0-Security-Theory/Chosen plaintext attack.pdf -------------------------------------------------------------------------------- /E0-Security-Theory/Definitions and concepts.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E0-Security-Theory/Definitions and concepts.pdf -------------------------------------------------------------------------------- /E1-Mathematics/Abstract-Algebra/2. Groups.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E1-Mathematics/Abstract-Algebra/2. Groups.pdf -------------------------------------------------------------------------------- /E1-Mathematics/Abstract-Algebra/4. Fields.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E1-Mathematics/Abstract-Algebra/4. Fields.pdf -------------------------------------------------------------------------------- /P2-Digital-Signatures/1. Digital Signatures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/P2-Digital-Signatures/1. Digital Signatures.pdf -------------------------------------------------------------------------------- /E1-Mathematics/Abstract-Algebra/5. Polynomials.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E1-Mathematics/Abstract-Algebra/5. Polynomials.pdf -------------------------------------------------------------------------------- /E2-Secret-sharing-schemes/Secret_sharing_schemes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E2-Secret-sharing-schemes/Secret_sharing_schemes.pdf -------------------------------------------------------------------------------- /P2-Digital-Signatures/2. Hash-Based Signatures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/P2-Digital-Signatures/2. Hash-Based Signatures.pdf -------------------------------------------------------------------------------- /S3-Message-Integrity/Message Authentication Code.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/S3-Message-Integrity/Message Authentication Code.pdf -------------------------------------------------------------------------------- /E3-Homomorphic-Encryption/1. Homomorphic Encryption.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/E3-Homomorphic-Encryption/1. Homomorphic Encryption.pdf -------------------------------------------------------------------------------- /E0-Security-Theory/README.md: -------------------------------------------------------------------------------- 1 | # Suggested reading order 2 | 1. Overview 3 | 2. Intro stuff 4 | 3. Types of attacks 5 | 6 | Then go read the pdf from the stream ciphers directory 7 | -------------------------------------------------------------------------------- /S1-PRNGs-and-stream-ciphers/Pseudorandomness and Stream Ciphers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zademn/EverythingCrypto/HEAD/S1-PRNGs-and-stream-ciphers/Pseudorandomness and Stream Ciphers.pdf -------------------------------------------------------------------------------- /S4-Authenticated-Encryption/README.md: -------------------------------------------------------------------------------- 1 | # Authenticated Encryption 2 | (Medium difficulty) 3 | 4 | If Encryption takes care of confidentiality and MACs take care of Message Integrity we now study construction that will take care of both at the same time 5 | - AE - Authenticated Encryption 6 | - AEAD - Authenticated encryption and additional data 7 | 8 | # Suggested reading order 9 | 1. AE and AEAD pdf 10 | 2. GCM mode -> GCM Forbidden attack -------------------------------------------------------------------------------- /S2-Block-ciphers/README.md: -------------------------------------------------------------------------------- 1 | # Block ciphers 2 | (Easy-medium difficulty) 3 | 4 | A block cipher is an encryption method that applies a deterministic algorithm along with a symmetric key to encrypt a block of text, rather than encrypting one bit at a time as in stream ciphers. For example, a common block cipher, AES, encrypts 128 bit blocks with a key of predetermined length. 5 | 6 | # Suggested reading order 7 | 1. Block ciphers pdf 8 | 2. Modes of operation 9 | 3. Block cipher design 10 | 4. Cryptanalysis methods -------------------------------------------------------------------------------- /S3-Message-Integrity/README.md: -------------------------------------------------------------------------------- 1 | # Message integrity 2 | 3 | Here we deal with methods to check if a message has been tampered with 4 | - Make sure the message sent is the same as the message received 5 | 6 | # Suggested reading order 7 | 1. Message auth codes pdf 8 | 2. Hashes pdf 9 | 3. Notebooks => any, they contain the prerequisites 10 | - Birthday attack 11 | - Merkle-Damgard Paradigm 12 | - Length Extension attacks 13 | - HMAC 14 | - The Sponge construction 15 | 16 | Difficulty: easy-medium -------------------------------------------------------------------------------- /E1-Mathematics/README.md: -------------------------------------------------------------------------------- 1 | # Mathematics 2 | 3 | Here you will find the basic structures(groups, curves, etc) and algorithms that we build our cryptographic primitives on 4 | 5 | # Suggested reading order 6 | 1. **Number theory** - The starting point. No prerequisites. Nada. The most basic stuff is here 7 | 2. Pick your poison 8 | 9 | # Difficulty 10 | - Number Theory - Easy 11 | - Factorization - Easy -> Hard 12 | - Lattices - Medium 13 | - Elliptic curves - Medium 14 | - ECDLP - Medium 15 | - Primes and Primality - Easy -> Medium -------------------------------------------------------------------------------- /E2-Secret-sharing-schemes/README.md: -------------------------------------------------------------------------------- 1 | # Secret Sharing Schemes 2 | (Easy difficulty) 3 | 4 | One of the problems that cryptogrpahy tries to solve is how to split a **secret** into **shares** to give to multiple parties in a safe way and satisfying different proprieties such as: 5 | - The secret can be computed only if some parties gather their shares together 6 | - There is no information revealed about the secret from it's shares independently 7 | - etc 8 | 9 | # Suggested reading order 10 | 1. Secret sharing schemes pdf 11 | 2. SSSS 12 | -------------------------------------------------------------------------------- /E1-Mathematics/Primes-and-Primality-tests/README.md: -------------------------------------------------------------------------------- 1 | # Primality tests 2 | 3 | The algorithms in this section are methods by which arbitrary positive integers are tested to provide **partial information** regarding their primality. (Probabilistic tests) 4 | 5 | We will explore the following tests: (I recommend to go through the Fermat's test first since there is the framework for general primality tests) 6 | 7 | 1. Probabilistic tests 8 | - Fermat's test 9 | - Solovan-Strassen test 10 | - Miller-Rabin test 11 | - Lucas test 12 | 2. Deterministic tests 13 | 14 | 15 | -------------------------------------------------------------------------------- /P1-Public-key/Diffie-Hellman/Vulnerabilities/README.md: -------------------------------------------------------------------------------- 1 | # Vulnerabilities 2 | 3 | Here I collected some of the common vulnerabilities of DH. 4 | 5 | Each notebook has 6 | 7 | 1. prerequisites for the attack 8 | 2. Theory 9 | - The vulnerability(task) we want to exploit 10 | - Some background theory + resources that helped me understand it 11 | 3. Code 12 | - Toy implementation 13 | - If there is a library that makes our life easier 14 | 4. More resources 15 | 16 | # The order to study them 17 | 18 | 1. Beginner 19 | - Bad groups 20 | - Man in the middle attacks 21 | 2. Easy 22 | 3. Intermediate: 23 | 4. Hard 24 | -------------------------------------------------------------------------------- /E1-Mathematics/Lattices/README.md: -------------------------------------------------------------------------------- 1 | # Lattices 2 | (Difficulty: Medium to Hard) 3 | 4 | Lattice based cryptography is one of the advanced topics in cryptography. Before jumping into it I suggest 5 | - A good grasp of Linear Algebra (taken at least 1 course) 6 | - A good understanding of Abstract algebra (Rings, groups, fields, polynomials) 7 | - Visual memory might help 8 | 9 | In these notebooks I try to build up the lattice knowledge needed to build cryptosystems. 10 | 11 | I numbered the order you should study them in. 12 | 13 | Sadly, I had no time to write down reduction proofs but you'll find them in the resources / videos linked. 14 | 15 | Good resource: https://cryptohack.gitbook.io/cryptobook/lattices/definitions 16 | 17 | -------------------------------------------------------------------------------- /E1-Mathematics/Elliptic-curves/README.md: -------------------------------------------------------------------------------- 1 | # Elliptic curves 2 | 3 | In this directory you will find the theory I collected about Elliptic curves. This theory will come in handy later when we study different attacks on ECDLP 4 | 5 | The order I studied them and I recommend them to be studied: 6 | 7 | 1. Elliptic_curves and Elliptic_curves_over_finite_fields notebooks 8 | - You will develop a basic intuition and understanding of curves 9 | - You will understand the basic ECDLP algorithms 10 | 2. The Rational Points on Elliptic curves folder => From Silverman's Book 11 | - Going through these notebooks + reading the book should prepare your for intermediate attacks such as 12 | - Attacks on anomalous curves 13 | - Attacks on singular curves 14 | 3. Bilinear pairings 15 | - MOV attack 16 | 17 | 18 | -------------------------------------------------------------------------------- /P2-Digital-Signatures/ECDSA/Vulnerabilities/README.md: -------------------------------------------------------------------------------- 1 | # Vulnerabilities 2 | Here I collected some of the common vulnerabilities of ECDSA. 3 | 4 | Each notebook has 5 | 1. prerequisites for the attack 6 | 2. Theory 7 | - The vulnerability(task) we want to exploit 8 | - Some background theory + resources that helped me understand it 9 | 3. Code 10 | - Toy implementation 11 | - If there is a library that makes our life easier 12 | 4. More resources 13 | 14 | # The order to study them 15 | 16 | 1. Easy 17 | - **Reset_attack**: Reuse of the same nonce when signing different messages 18 | - **Curveball or Chain of fools**: Not checking the signature algorithm parameters (curve parameters) when issuing certificates 19 | 2. Intermediate 20 | - **Biased_k**: Lattice attack against small nonces given a set of messages and their signature 21 | -------------------------------------------------------------------------------- /E1-Mathematics/Discrete-Logarithm-Problem/README.md: -------------------------------------------------------------------------------- 1 | # Discrete Logarithm Problem 2 | The Discrete Logarithm Problem is important in cryptography because sometimes the cryptosystem is based on the difficulty of computing the discrete logarithm in some group of some order. 3 | Given an element g of high order and an element a = g^x mod N find x 4 | Usually we try to abuse bad choices of groups 5 | 6 | Here is a collection of DLP algorithms and their applications 7 | 8 | Each notebook has 9 | 1. prerequisites for the attack 10 | 2. Theory 11 | - Background theory + resources that helped me understand it 12 | 3. Code 13 | - Toy implementation 14 | - If there is a library that makes our life easier (if i found one) 15 | 4. More resources 16 | 17 | # The order to study them 18 | 19 | 2. Easy 20 | - **Baby Step Giant Step** = Collision algorithm for solving the DLP 21 | - **Pohlig-Hellman** = When the order of the group is a smooth number00 22 | 3. Intermediate: 23 | - **Pollard-Rho** = Space-Time efficient way of computing the DLP 24 | 4. Hard 25 | -------------------------------------------------------------------------------- /P2-Digital-Signatures/README.md: -------------------------------------------------------------------------------- 1 | # Digital signatures 2 | 3 | - https://en.wikipedia.org/wiki/Digital_signature 4 | - https://www.youtube.com/watch?v=JR4_RBb8A9Q 5 | 6 | A **digital signature** is a mathematical scheme for verifying the authenticity of digital messages or documents (Like the pen and paper signatures) 7 | 8 | - only you can sign arbitrary messages (or other words, nobody should be able to forge your signature) 9 | - anybody can verify a signature on messages that you’ve signed 10 | 11 | A digital signature scheme typically consists of three algorithms; 12 | 13 | 1. A *key generation algorithm* that selects a private key uniformly at random from a set of possible private keys. The algorithm outputs the **private key** and a corresponding **public key**. 14 | 2. A *signing algorithm* that, given a message and a private key, produces a **signature**. 15 | 3. A *signature verifying algorithm* that, given the message, public key and signature, either **accepts** or **rejects** the message's claim to authenticity. 16 | 17 | # Suggested reading order 18 | 1. DSA signatures -> read online 19 | 2. RSA signatures 20 | 3. Elliptic curve DSA -------------------------------------------------------------------------------- /E1-Mathematics/Factorization/README.md: -------------------------------------------------------------------------------- 1 | # Factorizations 2 | Factorizations are important in cryptography because sometimes the cryptosystem is based on the difficulty of factorizing some number N 3 | Usually N = p * q or some combination of multiple primes. We are going to explore different prorieties of these primes and we are going go exploit them with different techniques 4 | 5 | Here is a collection of factorization algorithms and their applications 6 | 7 | Each notebook has 8 | 1. prerequisites for the attack 9 | 2. Theory 10 | - The vulnerability(task) we want to exploit 11 | - Some background theory + resources that helped me understand it 12 | 3. Code 13 | - Toy implementation 14 | - If there is a library that makes our life easier (if i found one) 15 | 4. More resources 16 | 17 | # The order to study them 18 | 19 | 1. Beginner 20 | - **Fermat's factorization**: When p and q are close 21 | 2. Easy 22 | - **Lentsra's EC factorization**: use elliptic curve proprieties to factor some N 23 | 3. Intermediate: 24 | - **Coppersmith's attacks** a method to find small roots of polynomials modulo 25 | - **ROCA** 2017 vulnerability of primes p that have a special form 26 | 4. Hard 27 | -------------------------------------------------------------------------------- /E-1-Books/README.md: -------------------------------------------------------------------------------- 1 | # Books to read 2 | 3 | ## General purpose 4 | 5 | 1. An introduction to mathematical cryptography - Second edition by Jeffrey Hoffstein, Jill Pipher and Joseph H. Silverman 6 | [some notes i made](https://github.com/zademn/math_crypto_nb) 7 | - Public key crypto, Mathematical approach 8 | 9 | 2. [A graduate course in applied cryptography - Dan Boneh and Victor Shoup](http://toc.cryptobook.us/) 10 | 11 | 3. Cryptography made simple - Nigel Smart 12 | - I used it as a helper book 13 | 14 | 4. [The joy of cryptography](https://web.engr.oregonstate.edu/~rosulekm/crypto/) 15 | - A friendly approach to crypto 16 | 17 | 5. [Intensive introduction to cryptography](https://files.boazbarak.org/crypto/lnotes_book.pdf) 18 | - Fun 19 | 20 | 6. [Modern Cryptanalysis](https://swenson.io/Modern%20Cryptanalysis%20v1.1%202022-01-23.pdf) 21 | 22 | 23 | ## Elliptic curves specific 24 | 1. Rational Points on Elliptic curves - Silverman 25 | - Undergraduate 26 | 2. The arithmetic of Elliptic curves - Silverman 27 | - Graduate 28 | 3. Elliptic Curves Number Theory and Cryptography - Lawrence C. Washington 29 | - Medium difficulty 30 | 4. Elliptic curves - Lectures by Damiano Testa, Notes by Samuele Anni 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /E1-Mathematics/Elliptic-curves/ECDLP/README.md: -------------------------------------------------------------------------------- 1 | # Elliptic Curve Discrete Logarithm Problem 2 | The Elliptic Curve Discrete Logarithm Problem is important in cryptography because sometimes the cryptosystem is based on the difficulty of computing the elliptic curve discrete logarithm with points on some curves 3 | 4 | Given the points P,Q on an elliptic curve E with Q = nP -> find n 5 | Usually we try to abuse bad choices of parameters of curves or different types of curves 6 | 7 | Here is a collection of ECDLP algorithms and their applications 8 | 9 | Each notebook has 10 | 1. prerequisites for the attack 11 | 2. Theory 12 | - Background theory + resources that helped me understand it 13 | 3. Code 14 | - Toy implementation 15 | - If there is a library that makes our life easier (if i found one) 16 | 4. More resources 17 | 18 | # The order to study them 19 | 20 | 2. Easy (All of these are already implemented in sage) 21 | - **Baby step giant step** 22 | - **Pohlig-Hellman on EC** = Order of the curve is smooth 23 | - **Pollard-rho** on EC* 24 | 3. Intermediate: 25 | - **Smart attack** 26 | - **Singular curves** 27 | 4. Hard 28 | - **MOV attack** - You can transition the problem from a curve into a finite group where it's easier to solve 29 | -------------------------------------------------------------------------------- /P1-Public-key/RSA/Vulnerabilities/README.md: -------------------------------------------------------------------------------- 1 | # Vulnerabilities 2 | Here I collected some of the common vulnerabilities of RSA. 3 | 4 | Each notebook has 5 | 1. prerequisites for the attack 6 | 2. Theory 7 | - The vulnerability(task) we want to exploit 8 | - Some background theory + resources that helped me understand it 9 | 3. Code 10 | - Toy implementation 11 | - If there is a library that makes our life easier 12 | 4. More resources 13 | 14 | # The order to study them 15 | 16 | 1. Beginner 17 | - **Begginer mistakes**: easy exploitation of bad RSA parameters 18 | 2. Easy 19 | - **Known (e, d) pair**: Decrypt any message if you know the pair (e,d) 20 | - **Halstad's broadcast attack**: decrypt a message if it was send to k users and encrypted with different moduli N (k>e) 21 | - **Wiener attack**: Small d 22 | 3. Intermediate: 23 | - **Coppersmith's attacks** a method to find small roots of polynomials modulo 24 | - **Halstad's broadcast attack part 2**: hastad but with linear padding 25 | - **Franklin-Reiter attack**: Lineary Related messages with e = 3 26 | 4. Hard 27 | - **Boneh-Durfee attack** improvement on Coppersmith 28 | - **Jochemsz-May attack** A multivariate polynomial case (TO DO) 29 | - **Multivariate coppersmith** (TO DO) 30 | 31 | 32 | -------------------------------------------------------------------------------- /S1-PRNGs-and-stream-ciphers/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Random number generators 3 | (medium difficulty) 4 | 5 | Random number generators (RNGs) are essential to cryptography since many algorithms require random numbers 6 | - Block ciphers key / iv 7 | - Stream cipher keystream 8 | 9 | --- 10 | 11 | Yet not all RNG are created equal 12 | - TRNG - True random number generators - physical events(throwing a dice, time of keytaps) 13 | - PRNG - Algorithmically determined - Appear to be random 14 | 15 | In practice we use PRNG since we don't always have a TRNG at disposal 16 | 17 | --- 18 | 19 | Now, not all PRNGs are created equal 20 | - Some PRNGs are designed for speed and don't care if you are able to predict them given some outputs 21 | - Others are **cryptographically secure pseudo random generators** which you are unable to predict given some outputs 22 | 23 | --- 24 | 25 | # Stream ciphers 26 | A stream cipher is a symmetric key cipher where plaintext digits are combined with a pseudorandom cipher digit stream (keystream). In a stream cipher, each plaintext digit is encrypted one at a time with the corresponding digit of the keystream, to give a digit of the ciphertext stream. 27 | 28 | `C = P xor KS` 29 | 30 | `KS = key-scheduling-algo(K)` where `K` involves some secret key 31 | 32 | # Suggested reading order 33 | 1. PRG 34 | 2. PRF_PRP 35 | 3. Choose your PRNG / stream cipher -------------------------------------------------------------------------------- /E1-Mathematics/Elliptic-curves/Rational_points_on_elliptic_curves/Chapter_5_Integer_points_on_cubic_curves.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 5. Integer Points on Cubic Curves" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## 5.1 How many integer points" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "**Theorem (Siegel’s Theorem)**.\n", 22 | "\n", 23 | "Let $C$ be a non-singular cubic curve givenby an equation $F(x, y)=0$ with integer coefficients. Then $C$ has only **finitely** many points with integer coordinates.\n", 24 | "\n", 25 | "**Remark**:\n", 26 | "- The singular cubic curves $C_1:y^2=x^3$ and $C_2:y^2=x^3−x^2 $ have infinite many integer points (obvious from the isomorphisms)" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [] 35 | } 36 | ], 37 | "metadata": { 38 | "kernelspec": { 39 | "display_name": "Python 3", 40 | "language": "python", 41 | "name": "python3" 42 | }, 43 | "language_info": { 44 | "codemirror_mode": { 45 | "name": "ipython", 46 | "version": 3 47 | }, 48 | "file_extension": ".py", 49 | "mimetype": "text/x-python", 50 | "name": "python", 51 | "nbconvert_exporter": "python", 52 | "pygments_lexer": "ipython3", 53 | "version": "3.7.3" 54 | } 55 | }, 56 | "nbformat": 4, 57 | "nbformat_minor": 2 58 | } 59 | -------------------------------------------------------------------------------- /E1-Mathematics/Discrete-Logarithm-Problem/3. Pollard_Rho.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prerequisites" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": { 13 | "ExecuteTime": { 14 | "end_time": "2020-09-09T19:31:51.871155Z", 15 | "start_time": "2020-09-09T19:31:51.868153Z" 16 | } 17 | }, 18 | "source": [ 19 | "- Group theory\n", 20 | "- DLP\n", 21 | "- Baby Step Giant Step\n", 22 | "- Pohlig-Hellman\n" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "# Theory" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "# Code" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "# Resources\n", 44 | "- https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [] 53 | } 54 | ], 55 | "metadata": { 56 | "kernelspec": { 57 | "display_name": "Python 3 (ipykernel)", 58 | "language": "python", 59 | "name": "python3" 60 | }, 61 | "language_info": { 62 | "codemirror_mode": { 63 | "name": "ipython", 64 | "version": 3 65 | }, 66 | "file_extension": ".py", 67 | "mimetype": "text/x-python", 68 | "name": "python", 69 | "nbconvert_exporter": "python", 70 | "pygments_lexer": "ipython3", 71 | "version": "3.10.4" 72 | }, 73 | "toc": { 74 | "base_numbering": 1, 75 | "nav_menu": {}, 76 | "number_sections": true, 77 | "sideBar": true, 78 | "skip_h1_title": false, 79 | "title_cell": "Table of Contents", 80 | "title_sidebar": "Contents", 81 | "toc_cell": false, 82 | "toc_position": {}, 83 | "toc_section_display": true, 84 | "toc_window_display": false 85 | } 86 | }, 87 | "nbformat": 4, 88 | "nbformat_minor": 4 89 | } 90 | -------------------------------------------------------------------------------- /S2-Block-ciphers/DES.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prerequisites" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "- Block ciphers\n", 15 | "- PRG, PRF, PRP" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "# Theory" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "## Feistel Cipher" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "- https://en.wikipedia.org/wiki/Feistel_cipher\n", 37 | "- https://www.youtube.com/watch?v=FGhj3CGxl8I&t" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "The Feistel cipher is a symmetric structure used in he construction of block ciphers" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## Feistel Code" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "## DES" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "## DES Code" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "# Resources" 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [] 88 | } 89 | ], 90 | "metadata": { 91 | "kernelspec": { 92 | "display_name": "Python 3", 93 | "language": "python", 94 | "name": "python3" 95 | }, 96 | "language_info": { 97 | "codemirror_mode": { 98 | "name": "ipython", 99 | "version": 3 100 | }, 101 | "file_extension": ".py", 102 | "mimetype": "text/x-python", 103 | "name": "python", 104 | "nbconvert_exporter": "python", 105 | "pygments_lexer": "ipython3", 106 | "version": "3.7.3" 107 | } 108 | }, 109 | "nbformat": 4, 110 | "nbformat_minor": 2 111 | } 112 | -------------------------------------------------------------------------------- /P1-Public-key/RSA/Vulnerabilities/Jochemsz_May_methods.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prerequisites" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "- RSA\n", 15 | "- Coppersmith attacks\n", 16 | "- Boneh-Durfee attacks" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Theory" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "- We'll follow this paper: http://www.cits.rub.de/imperia/md/content/may/paper/jochemszmay.pdf" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "In the case of RSA:\n", 38 | " $$ed - 1 = k \\cdot (N-(p+q - 1)) \\text{ for some unknown } k$$ \n", 39 | "- We aim to find $(d, k, p+q-1)$ of the polynomial $f(x, y, z) = ex - yN + yz - 1$\n", 40 | "- or find $(k, p+q-1)$ of $f_e(y,z) = y(N-z) + 1 \\ mod \\ e$\n", 41 | "\n", 42 | "Coppersmith tehnique depends on the size of the root => We have bounds on roots (Ex: Boneh-Durfee for finding $d " 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "## HKDF" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "## PBKDF" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "# Code" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "## Library" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "- https://pycryptodome.readthedocs.io/en/latest/src/protocol/kdf.html " 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 5, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "name": "stdout", 84 | "output_type": "stream", 85 | "text": [ 86 | "b'Y\\x89\\xc3t\\x85\\x9fz:\\xb1\\t\"\\xd5\\x82`L5\\xaa=>;\\xf7\\xcb\\x84i\\xa0\\xabz\\xf4q\\xedFz'\n", 87 | "b'G#\\xb5\\x9c\\xe8\"\\xfd\\xc3\\xc76\\x88\\xd3\\'\\xaf\\xd3Z\\xe1t2v\\x8a\\xb2{s\\xbd0\\xab\\xebG\\x0bh|'\n" 88 | ] 89 | } 90 | ], 91 | "source": [ 92 | "from Crypto.Protocol.KDF import PBKDF2\n", 93 | "from Crypto.Hash import SHA512\n", 94 | "from Crypto.Random import get_random_bytes\n", 95 | "\n", 96 | "password = b'my super secret'\n", 97 | "salt = get_random_bytes(16)\n", 98 | "keys = PBKDF2(password, salt, 64, count=1000000, hmac_hash_module=SHA512)\n", 99 | "key1 = keys[:32]\n", 100 | "key2 = keys[32:]\n", 101 | "print(key1)\n", 102 | "print(key2)" 103 | ] 104 | }, 105 | { 106 | "cell_type": "markdown", 107 | "metadata": {}, 108 | "source": [ 109 | "# Resources" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "- https://crypto.stackexchange.com/questions/40757/key-derivation-functions-kdf-what-are-main-purposes-how-can-they-be-used\n", 117 | "- https://eprint.iacr.org/2010/264.pdf\n", 118 | "- https://qvault.io/2019/12/30/very-basic-intro-to-key-derivation-functions-argon2-scrypt-etc/" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [] 127 | } 128 | ], 129 | "metadata": { 130 | "kernelspec": { 131 | "display_name": "Python 3", 132 | "language": "python", 133 | "name": "python3" 134 | }, 135 | "language_info": { 136 | "codemirror_mode": { 137 | "name": "ipython", 138 | "version": 3 139 | }, 140 | "file_extension": ".py", 141 | "mimetype": "text/x-python", 142 | "name": "python", 143 | "nbconvert_exporter": "python", 144 | "pygments_lexer": "ipython3", 145 | "version": "3.7.7" 146 | } 147 | }, 148 | "nbformat": 4, 149 | "nbformat_minor": 4 150 | } 151 | -------------------------------------------------------------------------------- /P1-Public-key/Diffie-Hellman/Vulnerabilities/Bad_Groups.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prerequisites" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "- Diffie hellman key exchange\n", 15 | "- Group theory\n", 16 | "- Modular arithmetic" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Using an additive group" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "$p$ = prime, $g$ = element with high order, $a, b$ = secret keys\n", 31 | "- $A = ag \\ \\bmod \\ p$\n", 32 | "- $B = bg \\ \\bmod \\ p$\n", 33 | "\n", 34 | "The vulnerability is pretty obvious as we can easily calculate the inverses of $A$ and $B$ and multiply with them to find out $a, b$" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "# Subgroups" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "Observation: the discrete logarithm problem in a group $G$ is only as hard as the discrete logarithm problem in the largest subgroup of prime order in $G$ where $G$ is a finite abelian group" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "## Choosing a bad element to generate public keys" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "For this case suppose $|G|$ is not prime. Not every element in a group is a generator for that group => there are cyclic subgroups generated by various elements. The number of elements in these subgroups is smaller then then number of elements in the original group therefore limiting the posibilities of the public keys A and B.\n", 63 | "\n", 64 | "Let $g$ be an element in the group $G$ => $g$ generates some subgroup $H = {g, g^2, g^3, ...}$ with $|H| < |G|$\n", 65 | "- $A = g^a \\ \\bmod \\ p \\Rightarrow A \\in H$\n", 66 | "- $B = g^b \\ \\bmod \\ p \\Rightarrow B \\in H$\n", 67 | "\n", 68 | "From [Lagrange's theorem](https://en.wikipedia.org/wiki/Lagrange%27s_theorem_(group_theory)) we know $|H|$ divides $|G|$.\n", 69 | "If $|H|$ is small enough we can brute force an attack to find $a$ or $b$." 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Let QR = Quadratic residue, NQR = non-quadratic residue\n", 77 | "\n", 78 | "**A compromise**: Even if you're choosing the best $g$ you will make some compromise: \n", 79 | "- if $g$ is a QR => $|H| = |G| / 2$ because $g$ can only generate QR\n", 80 | "- if $g$ is not a QR => you will leak the LSB of $a$ and $b$\n", 81 | " - if $A$ is QR => $A = g^{2y} => a = 2y => $ a is even\n", 82 | " - if $A$ is NQR => $a$ is odd\n", 83 | " " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [] 92 | } 93 | ], 94 | "metadata": { 95 | "kernelspec": { 96 | "display_name": "Python 3 (ipykernel)", 97 | "language": "python", 98 | "name": "python3" 99 | }, 100 | "language_info": { 101 | "codemirror_mode": { 102 | "name": "ipython", 103 | "version": 3 104 | }, 105 | "file_extension": ".py", 106 | "mimetype": "text/x-python", 107 | "name": "python", 108 | "nbconvert_exporter": "python", 109 | "pygments_lexer": "ipython3", 110 | "version": "3.10.4" 111 | }, 112 | "toc": { 113 | "base_numbering": 1, 114 | "nav_menu": {}, 115 | "number_sections": true, 116 | "sideBar": true, 117 | "skip_h1_title": false, 118 | "title_cell": "Table of Contents", 119 | "title_sidebar": "Contents", 120 | "toc_cell": false, 121 | "toc_position": {}, 122 | "toc_section_display": true, 123 | "toc_window_display": false 124 | } 125 | }, 126 | "nbformat": 4, 127 | "nbformat_minor": 4 128 | } 129 | -------------------------------------------------------------------------------- /P2-Digital-Signatures/RSA-sign/Vulnerabilities/No_hashing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2020-09-22T05:56:50.331638Z", 9 | "start_time": "2020-09-22T05:56:50.325634Z" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "from Crypto.Util.number import getPrime, inverse, bytes_to_long, long_to_bytes, GCD\n", 15 | "import random\n", 16 | "\n", 17 | "def rsa_ds_key_creation():\n", 18 | " p = getPrime(256)\n", 19 | " q = getPrime(256)\n", 20 | " N = p * q\n", 21 | " while True:\n", 22 | " e = random.randint(N//4,N-1)\n", 23 | " if(GCD(e, (p-1)*(q-1)) == 1):\n", 24 | " break\n", 25 | " return (p, q), (N, e)\n", 26 | "\n", 27 | "def rsa_ds_sign(D, p, q, N):\n", 28 | " d = inverse(e, (p-1)*(q-1)) #compute private key\n", 29 | " S = pow(D, d, N) #compute signature\n", 30 | " return S\n", 31 | "\n", 32 | "def rsa_ds_verif(D, S, e, N):\n", 33 | " return pow(S, e, N) == D #verify using public key" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "# Theory" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "Let\n", 48 | "- $N = pq, \\ e $ be the public parameters\n", 49 | "- let $d$ be the private key s.t. $e\\cdot d \\equiv 1 \\ mod\\ (p-1)(q-1)$ \n", 50 | "\n", 51 | "Let $m$ be a message and $c = m^e \\ mod \\ N$ its encryption\n", 52 | "\n", 53 | "Then if you sign the message => $c^d \\equiv m^{ed} \\equiv m \\ mod \\ N$\n", 54 | "\n", 55 | "**Remark** \n", 56 | "- In real world applications we use hashing functions on messages (and we verify the digests) and padding on encryption therefore we will not encounter this vulnerability outside beginner ctfs" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "# Code" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 5, 69 | "metadata": { 70 | "ExecuteTime": { 71 | "end_time": "2020-09-22T06:01:02.483590Z", 72 | "start_time": "2020-09-22T06:01:02.437556Z" 73 | } 74 | }, 75 | "outputs": [ 76 | { 77 | "data": { 78 | "text/plain": [ 79 | "2475606886358795585208927056902413668319714169289735961720429880592442798887264656896318042234906683532476203464902475482671308266238422031120311362832828" 80 | ] 81 | }, 82 | "execution_count": 5, 83 | "metadata": {}, 84 | "output_type": "execute_result" 85 | } 86 | ], 87 | "source": [ 88 | "(p,q), (N, e) = rsa_ds_key_creation()\n", 89 | "m = bytes_to_long(b'secret_message')\n", 90 | "c = pow(m, e, N)\n", 91 | "c" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": 7, 97 | "metadata": { 98 | "ExecuteTime": { 99 | "end_time": "2020-09-22T06:01:25.434452Z", 100 | "start_time": "2020-09-22T06:01:25.429433Z" 101 | } 102 | }, 103 | "outputs": [ 104 | { 105 | "data": { 106 | "text/plain": [ 107 | "b'secret_message'" 108 | ] 109 | }, 110 | "execution_count": 7, 111 | "metadata": {}, 112 | "output_type": "execute_result" 113 | } 114 | ], 115 | "source": [ 116 | "m_decr = rsa_ds_sign(c, p, q, N)\n", 117 | "long_to_bytes(m_decr)" 118 | ] 119 | } 120 | ], 121 | "metadata": { 122 | "kernelspec": { 123 | "display_name": "Python 3", 124 | "language": "python", 125 | "name": "python3" 126 | }, 127 | "language_info": { 128 | "codemirror_mode": { 129 | "name": "ipython", 130 | "version": 3 131 | }, 132 | "file_extension": ".py", 133 | "mimetype": "text/x-python", 134 | "name": "python", 135 | "nbconvert_exporter": "python", 136 | "pygments_lexer": "ipython3", 137 | "version": "3.7.7" 138 | }, 139 | "toc": { 140 | "base_numbering": 1, 141 | "nav_menu": {}, 142 | "number_sections": true, 143 | "sideBar": true, 144 | "skip_h1_title": false, 145 | "title_cell": "Table of Contents", 146 | "title_sidebar": "Contents", 147 | "toc_cell": false, 148 | "toc_position": {}, 149 | "toc_section_display": true, 150 | "toc_window_display": false 151 | } 152 | }, 153 | "nbformat": 4, 154 | "nbformat_minor": 4 155 | } 156 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hello there! 2 | 3 | In this repository I collect my adventures in the Cryptography world. 4 | What to expect? 5 | - Medium-Highly detailed explanations of algorithms / concepts 6 | - Implementations in Python / Sage (Every notebook is self contained up to prerequisites which you'll still find here) 7 | - Common libraries for solving the problems 8 | - Everything is full of resources (from Youtube videos with intuitive explanations to detailed papers on the subject) 9 | 10 | # IMPORTANT NOTE 11 | I **HIGHLY** recommend using nbviewer if you're reading these online: https://nbviewer.jupyter.org/github/zademn/EverythingCrypto/tree/master/ 12 | - Github doesn't render the all mathematics inside the notebooks 13 | - Github doesn't render images properly inside the notebooks 14 | 15 | If **nbviewer** is down for some reason download them locally and run them on your machine and everything will render normally. 16 | 17 | ## Disclaimer 18 | - This whole repository is for educational purposes 19 | - DO NOT USE ANY OF THE ALGORITHMS IN REAL WORLD APPLICATIONS 20 | 21 | # Structure? 22 | 23 | ## Notebooks 24 | - For educational and "ease to follow" purposes I decided to work in notebooks. Notebook are structured as follows: 25 | - Prerequisites = list of subjects/notebooks that you need to cover before attempting the subject 26 | - Theory = Mathematical explanation + intuitions 27 | - Code = Python,Sage or other library 28 | - Resources = List of resources for further reading 29 | ## PDF's 30 | - Some basic theory in the form of pdf's here and there 31 | 32 | ## Directories 33 | 34 | Directories are organized by categories (S = Symmetric, P = Public, E = Extra) 35 | 36 | ### Extra 37 | - Books 38 | - A collection of books I went through and found helpful 39 | - Security theory 40 | - Basic definitions and what to expect (Start with this) 41 | - Mathematics = Here you will find the basic structures(groups, curves, etc) and algorithms that I studied 42 | - Number theory - Start with this 43 | - Abstract algebra - Groups, Rings, Fields, Polynomials 44 | - Elliptic Curves - Theory 45 | - Discrete Logarithm Problem 46 | - Elliptic Curve Discrete Logarithm Problem 47 | - Factorizations 48 | - Lattices 49 | - Primes and primality tests 50 | - Secret sharing schemes 51 | - General Idea and SSSS 52 | 53 | ### Public 54 | - Public Key = Each cryptosystem will have an introduction and a folder with vulnerabilities (NOTE: mathematical vulnerabilities (Ex: factorizations, dlp) will not be covered to avoid monotony. I assume you can connect the dots) 55 | - RSA + vulnerabilities 56 | - Diffie Hellman + vulnerabilities 57 | - Elgamal 58 | - Digital signatures 59 | - ECDSA + vulnerabilities 60 | - RSADSA + vulnerabilities 61 | 62 | ### Symmetric 63 | - PRNG's 64 | - Pseudorandom generators, pseudorandom functions, 65 | - Implementations: chacha20, LFSRs, Geffe (Correlation attack) 66 | - Block Ciphers 67 | - AES, DES 68 | - Block ciphers modes of operation - pdf 69 | - Cryptanalysis methods 70 | - Message Integrity 71 | - MACs and hashes theory - pdf 72 | - Constructions - Merkle damgard and sponge 73 | - Length Extension attack 74 | - HMAC 75 | - Authenticated Encryption 76 | - AE and AEAD - pdf 77 | - GCM and the the forbidden attack 78 | 79 | Each directory will have a README.md that will contain the MY difficulty ranking of different subjects, attacks etc. 80 | 81 | # How to tackle this repository? 82 | Whatever fits your needs (Start with the security theory folder though to know what to expect) 83 | 1. Follow along with a book (There is a book directory) 84 | 2. Depth-first fashion (for people that have good foundations): 85 | - Pick a bigger subject 86 | - Study it thoroughly (from the lowest difficulty to the highest) 87 | 3. Breadth-first fashion (for starters): 88 | - Go through every topic at the lowest difficulty 89 | - Raise the difficulty and start again 90 | 4. My Take 91 | - Security theory dir -> Symmetric / Public 92 | - Symmetric encryption 93 | - PRGNG -> Block ciphers -> Message Integrity -> Authenticated Encryption 94 | - Public Encryption 95 | - Maths/Number Theory -> Public Key Encryption -> Digital Signatures 96 | - Maths when needed 97 | 98 | # TODO 99 | Not necessarily in this order 100 | (As of 26 jan 21) 101 | - [x] Hashes - 26 Dec 20 102 | - [x] Authenticated Encryption - 1 Jan 21 103 | - [x] RC4 and FMS 104 | - [ ] Code for DES and Feistel ciphers 105 | - [x] Block cipher design + Linear cryptanalysis - 27 jun 21 106 | - [x] Differential cryptanalysis - 29 jun 21 107 | - [x] Lattice theory - 26 Jan 21 108 | - [x] SIS, LWE - 4 Feb 21 109 | - [x] Lattice Cryptosystems 110 | - [ ] Homomorphic encryption 111 | - [x] Public key theory - 6 Jan 21 112 | - [ ] Zero knowledge proofs 113 | - [ ] Protocols (might make another repo) 114 | - [ ] Reductions 115 | - [ ] Add test vectors for algorithms 116 | -------------------------------------------------------------------------------- /P2-Digital-Signatures/RSA-sign/Vulnerabilities/Duplicate signature key selection.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 4, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from Crypto.Util.number import getPrime, inverse, bytes_to_long, long_to_bytes, GCD\n", 10 | "from Crypto.Hash.SHA256 import SHA256Hash\n", 11 | "import random" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 9, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "def key_creation():\n", 21 | " p = getPrime(128)\n", 22 | " q = getPrime(128)\n", 23 | " N = p * q\n", 24 | " while True:\n", 25 | " e = random.randint(N//4,N-1)\n", 26 | " if(GCD(e, (p-1)*(q-1)) == 1):\n", 27 | " break\n", 28 | " return (p, q), (N, e)\n", 29 | "\n", 30 | "def rsa_ds_sign(D, p, q, N):\n", 31 | " D = bytes_to_long(D)\n", 32 | " d = inverse(e, (p-1)*(q-1)) #compute private key\n", 33 | " S = pow(D, d, N) #compute signature\n", 34 | " return long_to_bytes(S)\n", 35 | "\n", 36 | "def rsa_ds_verif(D, S, e, N):\n", 37 | " D = bytes_to_long(D)\n", 38 | " S = bytes_to_long(S)\n", 39 | " return pow(S, e, N) == D #verify using public key" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "# Prerequisites\n", 47 | "- RSA signatures\n", 48 | "- Modular arithmetic\n" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "# Theory" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "Let $(G, E, D)$ be our signing algorithm based on RSA\n", 63 | "- $p, q$ primes\n", 64 | "- $N = pq;\\ \\varphi(N) = (p-1)(q-1)$\n", 65 | "- $d \\equiv e^{-1} \\bmod \\varphi(N)$ \n", 66 | "\n", 67 | "RSADSA \n", 68 | "- Sign: $\\sigma = m^d \\bmod N$\n", 69 | "- Verify: $m == \\sigma^e \\bmod N$" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "**Task**\n", 77 | "> Given a signature $\\sigma$ an attacker can choose a new message $m'$ and a $k_{pub} =(N', e')$ such that $m' == \\sigma^{e'} \\bmod N'$" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "The attacker can choose can choose $e = 1$\n", 85 | "\n", 86 | "We know \n", 87 | "- $s \\equiv m' \\bmod (s - m') \\iff s - (s - m') \\equiv m' \\bmod (s - m') \\iff m' \\equiv m' \\bmod (s - m')$\n", 88 | "- Therefore the attacker sends $(N', e') = (s-m', 1)$\n", 89 | "\n" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "# Code" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 5, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "(p, q), (N, e) = key_creation()" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 10, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "m = b'secret_message'\n", 115 | "s = rsa_ds_sign(m, p, q, N)" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 12, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [ 124 | "#compute our public key\n", 125 | "N_ = bytes_to_long(s) - bytes_to_long(m)\n", 126 | "e_ = 1" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 14, 132 | "metadata": {}, 133 | "outputs": [ 134 | { 135 | "data": { 136 | "text/plain": [ 137 | "True" 138 | ] 139 | }, 140 | "execution_count": 14, 141 | "metadata": {}, 142 | "output_type": "execute_result" 143 | } 144 | ], 145 | "source": [ 146 | "#verif\n", 147 | "rsa_ds_verif(m, s, e_, N_)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "# Resources" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "- https://www.agwa.name/blog/post/duplicate_signature_key_selection_attack_in_lets_encrypt\n", 162 | "- https://crypto.stackexchange.com/questions/47445/rsa-duplicate-signature-attack\n", 163 | "- https://mailarchive.ietf.org/arch/msg/acme/F71iz6qq1o_QPVhJCV4dqWf-4Yc/" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [] 172 | } 173 | ], 174 | "metadata": { 175 | "kernelspec": { 176 | "display_name": "Python 3", 177 | "language": "python", 178 | "name": "python3" 179 | }, 180 | "language_info": { 181 | "codemirror_mode": { 182 | "name": "ipython", 183 | "version": 3 184 | }, 185 | "file_extension": ".py", 186 | "mimetype": "text/x-python", 187 | "name": "python", 188 | "nbconvert_exporter": "python", 189 | "pygments_lexer": "ipython3", 190 | "version": "3.7.7" 191 | } 192 | }, 193 | "nbformat": 4, 194 | "nbformat_minor": 4 195 | } 196 | -------------------------------------------------------------------------------- /E1-Mathematics/Elliptic-curves/Rational_points_on_elliptic_curves/Chapter_4_Cubic_curves_over_finie_fields.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 4. Cubic Curves over FiniteFields" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## 4. 1 Rational Points over Finite fields" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "We can look at polynomials $C: F(x,y) = 0$ with coefficients in $\\mathbb{F}_p$ and search for solutions$(x,y)$ with $x,y \\in \\mathbb{F}_p$.\n", 22 | "\n", 23 | "More generally we can search for solutions $x,y \\in \\mathbb{F}_q$ where $\\mathbb{F}_q$ is an extension field of $\\mathbb{F}_p$ with $q = p^e$ elements. A solution is a point on the curve C. If the coordinates $x$ and $y$ of a solution lie in $\\mathbb{F}_p$, we call it a *rational point*" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "Consider the curve $y^2=x^3+ax^2+bx+c$ in $\\mathbb{F}_p$ with $D=−4a^3c+a^2b^2+18abc−4b^3−27c^2$ Except a few cases we can define the addition between two points $P_1, P_2$ using the line $y=λx+ν$\n", 31 | "\n", 32 | "- $\\lambda = \\begin{cases} \\cfrac {y_2 - y_1} {x_2 - x_1} \\text{ if } x_1 \\neq x_2\\\\\n", 33 | "\\cfrac {3x_1^2 + 2ax_1 + b} {2y_2} \\text{ if } P_1 = P_2\n", 34 | "\\end{cases}$\n", 35 | "\n", 36 | "- $ν=y_1−λx_1=y_2−λx_2$\n", 37 | "\n", 38 | "Then $P3=(x_3,y_3)=P_1+P_2$ is given by the formulas \n", 39 | "- $x_3=λ^2−a−x_1−x_2$\n", 40 | "- $y3=−λx_3−ν$\n", 41 | "\n", 42 | "The set of rational points $C(\\mathbb{F}_p)=\\{(x, y):x, y∈\\mathbb{F}_p \\text{ and }F(x, y)=0\\}$" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "**The number of points on a curve**\n", 50 | "\n", 51 | "**Theorem (Hasse-Weil)**\n", 52 | "If $C$ is a non-singular irreducible curve of genus $g$ defined over a finite field $\\mathbb{F}_p$, then the number of points on $C$ with coordinates in $\\mathbb{F}_p$ is equal to $p+1 - \\epsilon$, where the “error term” $\\epsilon$ satisfies $|\\epsilon|≤2 g \\sqrt p$\n", 53 | "\n", 54 | "**Note**: \n", 55 | "- Genus: https://en.wikipedia.org/wiki/Genus_(mathematics)\n", 56 | "- any non-singular curve given by a cubic equation is a curve of genus $1$\n" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "## 4.3 Points of Finite Order " 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "Let $C$ be a cubic curve, given as usual by a Weierstrass equation $C:y^2=x^3+ax^2+bx+c$ with integer coefficients $a,b,c$\n", 71 | "\n", 72 | "Consider the map **reduction modulo p**\n", 73 | "- $z\\longrightarrow \\tilde z$\n", 74 | "- $\\mathbb{Z} \\longrightarrow \\mathbb{Z} / p\\mathbb{Z} = \\mathbb{F}_p$\n", 75 | "\n", 76 | "We get a new curve $\\tilde C: y^2=x^3+ \\tilde a x^2 + \\tilde b x +\\tilde c$ which will be non-singular for $p > 2$ and the non-zero discriminant $\\tilde D=−4 \\tilde a^3\\tilde c+ \\tilde a^2 \\tilde b^2+18 \\tilde a \\tilde b \\tilde c−4 \\tilde b3−27 \\tilde c^2 = D \\ mod \\ p$ ( non-singular if $p$ doesnt divide $D$)\n", 77 | "\n", 78 | "Now we can take points $P = (x,y) \\in C(\\mathbb{Q})$ and reduce them modulo $p$ => $\\tilde P = (\\tilde x, \\tilde y) \\in \\tilde C(\\mathbb{F}_p)$\n", 79 | "\n", 80 | "Let $\\Phi=\\{P=(x, y)∈C(\\mathbb{Q}):P \\text { has finite order } \\}∪\\{\\mathcal{O}\\}$ = *the torsion subgroup* of $C(\\mathbb{Q})$ = the one from the Nagell-Lutz theorem\n", 81 | "\n", 82 | "For any prime $p$ we define the map \n", 83 | "- $\\Phi \\longrightarrow \\tilde C(\\mathbb{F}_p)$\n", 84 | "- $P \\longmapsto \\tilde P = \n", 85 | "\\begin{cases} \n", 86 | "(\\tilde x, \\tilde y) \\text{ if } P = (x,y) \\\\\n", 87 | " \\tilde {\\mathcal{O}} \\text{ if } P = \\mathcal{O}\n", 88 | "\\end{cases} $\n", 89 | "\n", 90 | "If $p$ does not divide $2D$ => the reduction mod $p$ map is an isomorphism of $\\Phi$ onto a subgroup of $\\tilde C(\\mathbb{F}_p)$\n", 91 | "\n" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "**Pollard's p-1 and Lenstra's algorithm are described in the factorization directory**\n", 99 | "\n", 100 | "**ECDLP has his own folder**" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [] 109 | } 110 | ], 111 | "metadata": { 112 | "kernelspec": { 113 | "display_name": "SageMath 9.0", 114 | "language": "sage", 115 | "name": "sagemath" 116 | }, 117 | "language_info": { 118 | "codemirror_mode": { 119 | "name": "ipython", 120 | "version": 3 121 | }, 122 | "file_extension": ".py", 123 | "mimetype": "text/x-python", 124 | "name": "python", 125 | "nbconvert_exporter": "python", 126 | "pygments_lexer": "ipython3", 127 | "version": "3.7.3" 128 | } 129 | }, 130 | "nbformat": 4, 131 | "nbformat_minor": 2 132 | } 133 | -------------------------------------------------------------------------------- /P1-Public-key/RSA/Vulnerabilities/Hastad_broadcast_part2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 4, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrime\n", 10 | "import random" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Prerequisites" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "- Hastad broadcast attack\n", 25 | "- Coppersmith's method" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "# Theory" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "- https://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf#page=4" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "# Code" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 6, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "e = 3\n", 56 | "m = bytes_to_long(b'secret_message')" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 9, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "def encrypt(m, e):\n", 66 | " p = getPrime(1024)\n", 67 | " q = getPrime(1024)\n", 68 | " N = p*q\n", 69 | " a = random.randint(2, N)\n", 70 | " b = random.randint(2, N)\n", 71 | " c = (a*m + b) % N\n", 72 | " c = pow(c, e, N)\n", 73 | " return a, b, N, c" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 11, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "a_list = []\n", 83 | "b_list = []\n", 84 | "c_list = []\n", 85 | "N_list = []\n", 86 | "num_polys = e \n", 87 | "for i in range(num_polys):\n", 88 | " a, b, N, c = encrypt(m, e)\n", 89 | " a_list.append(a)\n", 90 | " b_list.append(b)\n", 91 | " c_list.append(c)\n", 92 | " N_list.append(N)" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 25, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "def hastad_broadcast_linear_padding(a_list, b_list, c_list, N_list, e, num_polys):\n", 102 | " R_list = [PolynomialRing(Zmod(N_list[i]), 'x') for i in range(num_polys)]\n", 103 | "\n", 104 | " f_list = [R_list[i]([b_list[i],a_list[i]])**e - c_list[i] for i in range(num_polys)]\n", 105 | "\n", 106 | " # make f monic\n", 107 | " for i in range(num_polys):\n", 108 | " f_list[i] = f_list[i] * inverse_mod(f_list[i][e], N_list[i])\n", 109 | " \n", 110 | " T_list = []\n", 111 | " for i in range(num_polys):\n", 112 | " crt_a_list = [0] * num_polys\n", 113 | " crt_a_list[i] = 1\n", 114 | " ti = crt(crt_a_list, N_list)\n", 115 | " T_list.append(ti)\n", 116 | "\n", 117 | " N_prod = product(N_list)\n", 118 | " R_prod. = PolynomialRing(Zmod(N_prod))\n", 119 | " \n", 120 | " #F is a linear combination of the polynomials above\n", 121 | " F = sum([T_list[i] * R_prod(f_list[i].list()) for i in range(num_polys)])\n", 122 | "\n", 123 | " roots = F.small_roots()\n", 124 | " return roots[0]" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 26, 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [ 133 | "root = hastad_broadcast_linear_padding(a_list, b_list, c_list, N_list, e, num_polys)" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 27, 139 | "metadata": {}, 140 | "outputs": [ 141 | { 142 | "data": { 143 | "text/plain": [ 144 | "b'secret_message'" 145 | ] 146 | }, 147 | "execution_count": 27, 148 | "metadata": {}, 149 | "output_type": "execute_result" 150 | } 151 | ], 152 | "source": [ 153 | "long_to_bytes(root)" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "# Resources" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": {}, 166 | "source": [ 167 | "- https://en.wikipedia.org/wiki/Coppersmith%27s_attack\n", 168 | "- https://duksctf.github.io/2017/04/22/PCTF2017-Multicast.html\n", 169 | " " 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": null, 175 | "metadata": {}, 176 | "outputs": [], 177 | "source": [] 178 | } 179 | ], 180 | "metadata": { 181 | "kernelspec": { 182 | "display_name": "SageMath 9.1", 183 | "language": "sage", 184 | "name": "sagemath" 185 | }, 186 | "language_info": { 187 | "codemirror_mode": { 188 | "name": "ipython", 189 | "version": 3 190 | }, 191 | "file_extension": ".py", 192 | "mimetype": "text/x-python", 193 | "name": "python", 194 | "nbconvert_exporter": "python", 195 | "pygments_lexer": "ipython3", 196 | "version": "3.7.3" 197 | } 198 | }, 199 | "nbformat": 4, 200 | "nbformat_minor": 2 201 | } 202 | -------------------------------------------------------------------------------- /E1-Mathematics/Factorization/Pollard_p_minus_1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 4, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2020-09-15T21:07:11.296155Z", 9 | "start_time": "2020-09-15T21:07:11.290152Z" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "from Crypto.Util.number import GCD as gcd\n", 15 | "from Crypto.Util.number import sieve_base" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "# Prerequisites\n" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "- modular arithmetic\n", 30 | "- divisibility\n", 31 | "- gcd" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "# Theory " 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "Let $N = pq$ be the number we want to factor with $p,q$ prime. Then if $p-1$ is divisible by small primes we can efficiently factor $N$\n", 46 | "\n", 47 | "The essential observation is that, by working in the multiplicative group modulo a composite number $N$, we are also working in the multiplicative groups modulo all of $N$'s factors. \n", 48 | "\n", 49 | "- https://en.wikipedia.org/wiki/Pollard%27s_p_%E2%88%92_1_algorithm\n", 50 | "\n", 51 | "From Fermat's little theorem:\n", 52 | "$a^{p-1} \\equiv 1 \\bmod p$ then $p$ divides $\\gcd(a^{p-1}-1, N)$\n", 53 | "\n", 54 | "*Idea*:\n", 55 | "- Since we don't know $p$ we choose some $k$ = product of powers of small primes and compute $\\gcd(a^{k-1}-1, N)$\n", 56 | "- If $p-1 | k$ then $p | a^k-1 => \\gcd(a^{k-1}-1, N) \\geq p >1$ \n", 57 | " - $\\gcd(a^{k-1}-1, N) = 1$ we choose a larger $k$\n", 58 | " - $\\gcd(a^{k-1}-1, N) = N$ we choose another $a$\n", 59 | " - $\\gcd(a^{k-1}-1, N) \\neq N$ we found a factor on N\n", 60 | " \n" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": { 66 | "ExecuteTime": { 67 | "end_time": "2020-09-15T21:17:24.915397Z", 68 | "start_time": "2020-09-15T21:17:24.911395Z" 69 | } 70 | }, 71 | "source": [ 72 | "# Code" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 8, 78 | "metadata": { 79 | "ExecuteTime": { 80 | "end_time": "2020-09-15T21:23:29.227713Z", 81 | "start_time": "2020-09-15T21:23:29.223710Z" 82 | } 83 | }, 84 | "outputs": [], 85 | "source": [ 86 | "def pollard_factorization(n: int, bound: int, a: int = 2):\n", 87 | " \"\"\"Pollard p-1 factorization\n", 88 | "\n", 89 | " Parameters\n", 90 | " ----------\n", 91 | " n : int\n", 92 | " Integer to be factored\n", 93 | "\n", 94 | " bound : int\n", 95 | " Upper bound for the search\n", 96 | "\n", 97 | " a : int, default = 2\n", 98 | " starting value\n", 99 | " \n", 100 | " Returns\n", 101 | " -------\n", 102 | " int or None\n", 103 | " a factor of n or None if none was found\n", 104 | " \"\"\"\n", 105 | " # you can choose a to be other values\n", 106 | " for j in range(2, bound):\n", 107 | " a = pow(a, j, n) # a^(n+1)! = a^(n! * (n+1))\n", 108 | " d = gcd(a - 1, n)\n", 109 | " if 1 < d and d < n:\n", 110 | " return d\n", 111 | " return None" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 9, 117 | "metadata": { 118 | "ExecuteTime": { 119 | "end_time": "2020-09-15T21:23:29.587798Z", 120 | "start_time": "2020-09-15T21:23:29.583780Z" 121 | } 122 | }, 123 | "outputs": [ 124 | { 125 | "data": { 126 | "text/plain": [ 127 | "3823" 128 | ] 129 | }, 130 | "execution_count": 9, 131 | "metadata": {}, 132 | "output_type": "execute_result" 133 | } 134 | ], 135 | "source": [ 136 | "n = 13927189\n", 137 | "pollard_factorization(n, 15)" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 10, 143 | "metadata": { 144 | "ExecuteTime": { 145 | "end_time": "2020-09-15T21:23:30.850694Z", 146 | "start_time": "2020-09-15T21:23:30.846691Z" 147 | } 148 | }, 149 | "outputs": [ 150 | { 151 | "data": { 152 | "text/plain": [ 153 | "350437" 154 | ] 155 | }, 156 | "execution_count": 10, 157 | "metadata": {}, 158 | "output_type": "execute_result" 159 | } 160 | ], 161 | "source": [ 162 | "n = 168441398857\n", 163 | "pollard_factorization(n, 55)" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [] 172 | } 173 | ], 174 | "metadata": { 175 | "kernelspec": { 176 | "display_name": "Python 3 (ipykernel)", 177 | "language": "python", 178 | "name": "python3" 179 | }, 180 | "language_info": { 181 | "codemirror_mode": { 182 | "name": "ipython", 183 | "version": 3 184 | }, 185 | "file_extension": ".py", 186 | "mimetype": "text/x-python", 187 | "name": "python", 188 | "nbconvert_exporter": "python", 189 | "pygments_lexer": "ipython3", 190 | "version": "3.10.4" 191 | }, 192 | "toc": { 193 | "base_numbering": 1, 194 | "nav_menu": {}, 195 | "number_sections": true, 196 | "sideBar": true, 197 | "skip_h1_title": false, 198 | "title_cell": "Table of Contents", 199 | "title_sidebar": "Contents", 200 | "toc_cell": false, 201 | "toc_position": {}, 202 | "toc_section_display": true, 203 | "toc_window_display": false 204 | } 205 | }, 206 | "nbformat": 4, 207 | "nbformat_minor": 4 208 | } 209 | -------------------------------------------------------------------------------- /E1-Mathematics/Primes-and-Primality-tests/2. Solovay_Strassen_test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from Crypto.Util.number import GCD, getPrime, isPrime\n", 10 | "import random" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Prerequisites" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "- Fermat's test\n", 25 | "- Number theory basics\n", 26 | "- Jacobi and Legendre symbols" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 4, 32 | "metadata": {}, 33 | "outputs": [], 34 | "source": [ 35 | "def jacobi_symbol(a, n):\n", 36 | " if a ==0:\n", 37 | " return 0\n", 38 | " if a ==1:\n", 39 | " return 1\n", 40 | " #write a = 2^e *s where a1 is odd\n", 41 | " e =0\n", 42 | " a1 = a\n", 43 | " while a1 & 1==0: #while a1 is even\n", 44 | " a1>>=1\n", 45 | " e+=1\n", 46 | " \n", 47 | " #if e is even set s = 1\n", 48 | " if e & 1 == 0:\n", 49 | " s = 1\n", 50 | " elif n % 8 == 7 or n % 8 == 1:\n", 51 | " s = 1\n", 52 | " elif n % 8 == 3 or n % 8 == 5:\n", 53 | " s = -1\n", 54 | " \n", 55 | " if n % 4 == 3 and a1 % 4 == 3:\n", 56 | " s = -s\n", 57 | " \n", 58 | " n1 = n % a1\n", 59 | " if a1 ==1:\n", 60 | " return s\n", 61 | " else:\n", 62 | " return s * jacobi_symbol(n1, a1)" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "# Theory" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Although superseted by the Miller-Rabin test, this test solves the flaw that Fermat's test has\n", 77 | "\n", 78 | "**Euler criterion**\n", 79 | "\n", 80 | "Let $p$ be an odd prime \n", 81 | "- $a^{(p-1)/2} \\equiv \\left( \\dfrac a p \\right) \\bmod p \\ \\forall a\\in \\mathbb{Z} $ which satisfy $\\gcd(a, p) = 1$\n", 82 | "\n", 83 | "**Idea**: We want to test euler criterion for a composite $n$\n", 84 | "\n", 85 | "Let $n$ be an odd composite integer and let $a$ be an integer, $1≤a≤n−1$\n", 86 | "- If either $\\gcd(a,n)>1$ or $a^{(n−1)/2} \\not ≡\\left(\\dfrac a n\\right) \\bmod n => a$ is called an **Euler witness** (to compositeness) for $n$.\n", 87 | "- Otherwise, i.e., if $\\gcd(a,n)=1$ and $a^{(n−1)/2}≡\\left(\\dfrac a n\\right) \\bmod n$ => $n$is said to be an **Euler pseudoprime** to the base $a$**.\n", 88 | " - That is, $n$ acts like a prime in that it satisfies Euler’s criterion for the particular base $a$\n", 89 | " \n", 90 | "The integer $a$ is called an Euler liar (to primality) for $n$\n" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "# Code" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 16, 103 | "metadata": {}, 104 | "outputs": [], 105 | "source": [ 106 | "def solovay_strassen_test(n, k):\n", 107 | " for i in range(k):\n", 108 | " a = random.randint(2, n-2)\n", 109 | " r = pow(a, (n-1)//2, n)\n", 110 | " if GCD(a, n)!=1: #Remark this should return COMPOSITE (since you found a divisor !=1) \n", 111 | " return 'Composite'\n", 112 | " if r!=1 and r!=n-1: #the only values a jacobi / legendre values can take\n", 113 | " return 'Composite'\n", 114 | " jac = jacobi_symbol(a, n) % n\n", 115 | " if r != jac:\n", 116 | " return 'Composite'\n", 117 | " return 'Probably prime'\n", 118 | " " 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 17, 124 | "metadata": {}, 125 | "outputs": [ 126 | { 127 | "name": "stdout", 128 | "output_type": "stream", 129 | "text": [ 130 | "Composite\n", 131 | "Probably prime\n", 132 | "Composite\n" 133 | ] 134 | } 135 | ], 136 | "source": [ 137 | "print(solovay_strassen_test(2403, 12))\n", 138 | "p = getPrime(512)\n", 139 | "print(solovay_strassen_test(p, 100))\n", 140 | "print(solovay_strassen_test(561, 100))" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "# Resources" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "- https://en.wikipedia.org/wiki/Solovay%E2%80%93Strassen_primality_test" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": null, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [] 163 | } 164 | ], 165 | "metadata": { 166 | "kernelspec": { 167 | "display_name": "Python 3", 168 | "language": "python", 169 | "name": "python3" 170 | }, 171 | "language_info": { 172 | "codemirror_mode": { 173 | "name": "ipython", 174 | "version": 3 175 | }, 176 | "file_extension": ".py", 177 | "mimetype": "text/x-python", 178 | "name": "python", 179 | "nbconvert_exporter": "python", 180 | "pygments_lexer": "ipython3", 181 | "version": "3.9.4" 182 | }, 183 | "toc": { 184 | "base_numbering": 1, 185 | "nav_menu": {}, 186 | "number_sections": true, 187 | "sideBar": true, 188 | "skip_h1_title": false, 189 | "title_cell": "Table of Contents", 190 | "title_sidebar": "Contents", 191 | "toc_cell": false, 192 | "toc_position": {}, 193 | "toc_section_display": true, 194 | "toc_window_display": false 195 | } 196 | }, 197 | "nbformat": 4, 198 | "nbformat_minor": 2 199 | } 200 | -------------------------------------------------------------------------------- /P2-Digital-Signatures/ECDSA/Vulnerabilities/Reset_attack_nonce_reused.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 35, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from hashlib import sha1, sha256\n", 10 | "from Crypto.Util.number import bytes_to_long, long_to_bytes, inverse\n", 11 | "from ecdsa import ellipticcurve\n", 12 | "from ecdsa.ecdsa import curve_256, generator_256, Public_key, Private_key\n", 13 | "from random import randint" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": {}, 19 | "source": [ 20 | "# Prerequisites" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "- ecdsa" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "# Theory" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "**Task**\n", 42 | "- Exploit the fact that 2 signatures corresponding to 2 different messages were crafted using the same nonce $k$\n", 43 | "\n", 44 | "We know \n", 45 | "- the order of the subgroup generated by $G$: $q$\n", 46 | "- messages: $m_1, m_2$ and their hashes $h_1, h_2$\n", 47 | "- the signatures were generated using the same $k$\n", 48 | "- signatures: $(r, s_1), (r, s_2)$ <= $r$ is the same since we use the same $k$ => $Q_1 = Q_2 = kG$\n" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "$\n", 56 | "\\begin{equation}\n", 57 | "s_1 \\equiv k^{-1}(h_1 + dr) \\ mod \\ q \\\\\n", 58 | "s_2 \\equiv k^{-1}(h_2 + dr) \\ mod \\ q\n", 59 | "\\end{equation}$ \n", 60 | "\n", 61 | "Substract $s_2$ from $s_1$\n", 62 | "- $s_1 - s_2 \\equiv k^{-1}(h_1 + dr) - k^{-1}(h_2 + dr) \\equiv k^{-1}(h_1 - h_2) \\ mod \\ q => k \\equiv (h_1 - h_2)(s_1 - s_2)^{-1} \\ mod \\ q$\n", 63 | "\n", 64 | "Therefore we can calculate $d$\n", 65 | "- $d \\equiv (sk - h)r^{-1} \\ mod \\ q$\n", 66 | " \n" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "# Code" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 14, 79 | "metadata": {}, 80 | "outputs": [ 81 | { 82 | "name": "stdout", 83 | "output_type": "stream", 84 | "text": [ 85 | "True\n", 86 | "110293943109482154156062517946490981556599973730885811037950153262390807421596\n" 87 | ] 88 | } 89 | ], 90 | "source": [ 91 | "#generate the parameters\n", 92 | "G = generator_256\n", 93 | "q = G.order()\n", 94 | "print(is_prime(q))" 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 19, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "#generate the public and private key\n", 104 | "d = randint(1, q-1)\n", 105 | "pubkey = Public_key(G, d*G)\n", 106 | "privkey = Private_key(pubkey, d)" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 31, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [ 115 | "#hash the messages\n", 116 | "m1 = b'secret_message'\n", 117 | "m2 = b'another_one'\n", 118 | "h1 = bytes_to_long(sha256(m1).digest())\n", 119 | "h2 = bytes_to_long(sha256(m2).digest())" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 32, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "#random k\n", 129 | "k = randint(1, q-1)" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 33, 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "name": "stdout", 139 | "output_type": "stream", 140 | "text": [ 141 | "True\n" 142 | ] 143 | } 144 | ], 145 | "source": [ 146 | "sign1 = privkey.sign(h1, k)\n", 147 | "sign2 = privkey.sign(h2, k)\n", 148 | "\n", 149 | "s1, r1 = sign1.s, sign1.r\n", 150 | "s2, r2 = sign2.s, sign2.r\n", 151 | "print(r1 == r2) #check if the r's are equal\n", 152 | "\n", 153 | "r = r1" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 41, 159 | "metadata": {}, 160 | "outputs": [ 161 | { 162 | "name": "stdout", 163 | "output_type": "stream", 164 | "text": [ 165 | "True\n" 166 | ] 167 | } 168 | ], 169 | "source": [ 170 | "k_decr = ((h1 - h2) * inverse((s1 - s2), q)) % q\n", 171 | "print(k_decr == k)" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 42, 177 | "metadata": {}, 178 | "outputs": [ 179 | { 180 | "name": "stdout", 181 | "output_type": "stream", 182 | "text": [ 183 | "True\n" 184 | ] 185 | } 186 | ], 187 | "source": [ 188 | "d_decr = ((s1 * k - h1) * inverse(r, q)) % q\n", 189 | "print(d_decr == d)" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "# Resources" 197 | ] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": {}, 202 | "source": [ 203 | "- https://github.com/ashutosh1206/Crypton/tree/master/Digital-Signatures/Elliptic-Curve-DSA/Attack-k-reuse\n", 204 | "- https://crypto.stackexchange.com/questions/64167/ecdsa-with-common-nonce\n", 205 | "- PS3, bitcoin wallet hacks" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": null, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [] 214 | } 215 | ], 216 | "metadata": { 217 | "kernelspec": { 218 | "display_name": "SageMath 9.1", 219 | "language": "sage", 220 | "name": "sagemath" 221 | }, 222 | "language_info": { 223 | "codemirror_mode": { 224 | "name": "ipython", 225 | "version": 3 226 | }, 227 | "file_extension": ".py", 228 | "mimetype": "text/x-python", 229 | "name": "python", 230 | "nbconvert_exporter": "python", 231 | "pygments_lexer": "ipython3", 232 | "version": "3.7.3" 233 | } 234 | }, 235 | "nbformat": 4, 236 | "nbformat_minor": 2 237 | } 238 | -------------------------------------------------------------------------------- /E1-Mathematics/Elliptic-curves/Rational_points_on_elliptic_curves/Chapter_2_Points_of_finite_order.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 2. Points of finite order" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "An element $P$ of any group is said to have order $m$ if \n", 15 | "$$ mP=\\underbrace{P+P+···+P}_{m \\ summands} =\\mathcal{O}$$\n", 16 | "but $m'P \\neq \\mathcal{O} \\ \\forall \\ 1 \\leq m' $P$ has **finite** order, otherwise **infinite**" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "## 2.1 Points of order 2 and 3" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "**Theorem (Points of Order Two and Three)** \n", 33 | "\n", 34 | "Let $C$ be a non-singular cubic curve\n", 35 | "$$C:y^2=f(x)=x^3+ax^2+bx+c $$\n", 36 | "\n", 37 | "1. A point $P=(x, y) \\neq \\mathcal{O}$ on $C$ has order 2 <=> $y=0$ \n", 38 | " - $P = -P$\n", 39 | "2. The curve $C$ has exactly four points of order dividing two. These four points form a group that is a product of two cyclic groups of order two\n", 40 | " - *The Four group* https://en.wikipedia.org/wiki/Klein_four-group\n", 41 | "3. A point $P=(x, y) \\neq \\mathcal{O}$ on $C$ has order 3 <=> $x$ is a root of the polynomial \n", 42 | "$$ψ_3(x)=3x^4+4ax^3+6bx^2+12cx+4ac−b^2$$\n", 43 | " - $2P = -P => x(2P) = x(P)$ => duplication formula of the x-coord\n", 44 | "4. The curve $C$ has exactly nine points of order dividing three. These nine points form a group that is a product of two cyclic groups of order three." 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## 2.2 Real and complex points on cubic curves" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "The real points on our cubic curve $y^2=f(x)=x^3+ax^2+bx+c $ form either one or two components, depending on whether f(x) has one or three real roots\n", 59 | "\n", 60 | "- $C(\\mathbb{Q})=\\{(x, y)∈C:x, y∈\\mathbb{Q}\\}∪\\{\\mathcal{O}\\}$\n", 61 | "- $C(\\mathbb{R})=\\{(x, y)∈C:x, y∈\\mathbb{R}\\}∪\\{\\mathcal{O}\\}$ \n", 62 | " - Continous group (moving 2 points a little moves the intersection a little)\n", 63 | " - Compact one-dimensional Lie group https://en.wikipedia.org/wiki/Lie_group therefore:\n", 64 | " - Isomorphic to the circle group (the group of rotations of the circle = the multiplicative groupof complex numbers of absolute value one) https://en.wikipedia.org/wiki/Circle_group\n", 65 | " - $\\mathbb {T} =\\{z\\in \\mathbb {C} :|z|=1\\}$ => the points of finite order in that group are the **roots of unity**\n", 66 | " - for each positive integer $m$, the points of order dividing $m$ form a cyclic group of order $m$ => $\\{1,e^{2πi/m}, e^{4πi/m} ,...,e^{2(m−1)πi/m}\\}$\n", 67 | " \n", 68 | "- $C(\\mathbb{C})=\\{(x, y)∈C:x, y∈\\mathbb{C}\\}∪\\{\\mathcal{O}\\}$\n", 69 | "\n", 70 | "All of these sets form groups => $\\{\\mathcal{O}\\}⊂C(\\mathbb{Q})⊂C(\\mathbb{R})⊂C(\\mathbb{C})$" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "## 2.3 The discriminant" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "Let us be back to the field of rational numbers\n", 85 | "\n", 86 | "$$y^2=f(x)=x^3+ax^2+bx+c$$\n", 87 | "We will consider our curve has integer coefficients" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "The **Discriminant**: \n", 95 | "- $D=−4a^3c+a^2b^2+18abc−4b^3−27c^2$\n", 96 | "- If $a = 0 => D = -(4b^3 + 27c^2)$\n", 97 | "- Factoring over the complex numbers => $f(x)=(x−α_1)(x−α_2)(x−α_3) => D = (α_1−α_2)^2(α_1−α_3)^2(α_2−α_3)^2 => D \\neq 0 \\iff \\alpha_1 \\neq \\alpha_2 \\neq \\alpha_3 $ <= the roots are distinct" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "## 2.4 The Nagell-Lutz Theorem" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "**Theorem (Nagell–Lutz Theorem)**\n", 112 | "\n", 113 | "Let $y^2=f(x)=x^3+a^x2+bx+c$ be a non-singular cubic curve with integer coefficients $a, b, c$ \n", 114 | "Let $D$ bethe discriminant of the cubic polynomial, $D=−4a^3c+a^2b^2+18abc−4b^3−27c^2$. \n", 115 | "Let $P=(x, y)$ be a rational point of **finite** order. Then \n", 116 | "- $x$ and $y$ are **integers**, and \n", 117 | "- either $y=0$ => $P$ has order 2, or else $y$ divides $D$\n", 118 | " \n", 119 | "\n", 120 | "https://en.wikipedia.org/wiki/Nagell%E2%80%93Lutz_theorem\n", 121 | "\n", 122 | "**Proof**: in the book\n", 123 | "\n", 124 | "**Remarks**:\n", 125 | "- Warning. We are **not** asserting that every point $(x, y) $ with integer coordinates and $y|D$ must have finite order. The Nagell–Lutz theorem is not an “if and only if” statement.\n", 126 | "- This theorem can be used to prove a point has *infinite* order. The idea is to compute $P,2P,3P,...$ until one arrives at a multiple $nP$ whose coordinates are not integers. Then one knows that $nP$ , and also $P$, cannot have finite order." 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "**Theorem (Mazur’s Theorem)** \n", 134 | "\n", 135 | "Let $C$ be a non-singular rational cubic curve, and suppose that $C(\\mathbb{Q})$ contains a point of finite order $m$ . Then \n", 136 | "- either $1≤m≤10$ or $m=12$\n", 137 | "\n", 138 | "More precisely, the set of points of finite order in $C(\\mathbb{Q})$ forms a subgroup that has one of the following forms:\n", 139 | "- A cyclic group of order $N$ with $1≤N≤10$ or $N=12$.\n", 140 | "- The product of a cyclic group of order 2 and a cyclic group of order $2N$ with $1≤N≤4$." 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 26, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "A. = AffineSpace(QQ, 2)\n", 150 | "C = Curve(y^2 - x^3 - x^2 - x - 1)\n", 151 | "P. = PolynomialRing(CC)\n", 152 | "f = X^3 + X^2 + X + 1" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": 44, 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "# Play around if you want" 162 | ] 163 | } 164 | ], 165 | "metadata": { 166 | "kernelspec": { 167 | "display_name": "SageMath 9.2", 168 | "language": "sage", 169 | "name": "sagemath" 170 | }, 171 | "language_info": { 172 | "codemirror_mode": { 173 | "name": "ipython", 174 | "version": 3 175 | }, 176 | "file_extension": ".py", 177 | "mimetype": "text/x-python", 178 | "name": "python", 179 | "nbconvert_exporter": "python", 180 | "pygments_lexer": "ipython3", 181 | "version": "3.7.7" 182 | } 183 | }, 184 | "nbformat": 4, 185 | "nbformat_minor": 4 186 | } 187 | -------------------------------------------------------------------------------- /S1-PRNGs-and-stream-ciphers/Linear_congruential_generator.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from Crypto.Util.number import inverse, getPrime, long_to_bytes, bytes_to_long" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "# Prerequisites" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "- PRG\n", 24 | "- modular arithmetic" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "# Theory" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "- https://en.wikipedia.org/wiki/Linear_congruential_generator\n", 39 | "- https://brilliant.org/problems/breaking-linear-congruential-generators/\n", 40 | "- https://math.stackexchange.com/questions/2724959/how-to-crack-a-linear-congruential-generator-lcg" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "A linear congruential generator (LCG) is an algorithm that yields a sequence of pseudo-randomized numbers calculated with a discontinuous piecewise linear equation.\n", 48 | "\n", 49 | "It is defined by the following recurrence relation:\n", 50 | "- $S_{m+1} = (aS_m + c) \\bmod n$\n", 51 | "\n", 52 | "where\n", 53 | "- $n$ = the modulus\n", 54 | "- $a$ = the multiplier\n", 55 | "- $c$ = the increment\n", 56 | "- $S_0$ = the seed (start value)\n" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "## An attack" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "Let Eve know 3 plaintexts $m_1, m_2, m_3$ for 3 ciphertexts $c_1, c_2, c_3$\n", 71 | "- first she computes $S_1, S_2, S_3$\n", 72 | "- Then she has\n", 73 | " - $S_2 \\equiv a\\cdot S_1 + c \\bmod n$\n", 74 | " - $S_3 \\equiv a\\cdot S_3 + c \\bmod n$\n", 75 | "- Which is a system of equations => \n", 76 | " - $a = (S_2 - S_3) (S_1 - S_2)^{-1} \\bmod n$\n", 77 | " - $c = S_2 - S_1 (S_2 - S_3)(S_1 - S_2)^{-1} \\bmod n$\n", 78 | "- From now on we can compute everything" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "# Code" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 8, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "def lcg(modulus, a, c, seed):\n", 102 | " \"\"\"Linear congruential generator.\"\"\"\n", 103 | " while True:\n", 104 | " seed = (a * seed + c) % modulus\n", 105 | " yield seed" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 9, 111 | "metadata": {}, 112 | "outputs": [ 113 | { 114 | "name": "stdout", 115 | "output_type": "stream", 116 | "text": [ 117 | "110924620051623968447266268873007437161656047175321232942762078096800785291629 78330055002505665395054081034167722403903079478840676381279591427631187922487 7554986015269310430292520786725319659626669517486107306231817531558561772180102176996548849487708798671234713961543501834980727440531691912787827507581477\n" 118 | ] 119 | } 120 | ], 121 | "source": [ 122 | "n = getPrime(512)\n", 123 | "a = getPrime(256)\n", 124 | "c = getPrime(256)\n", 125 | "s0 = getPrime(256)\n", 126 | "print(a, c, n)" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 21, 132 | "metadata": {}, 133 | "outputs": [ 134 | { 135 | "name": "stdout", 136 | "output_type": "stream", 137 | "text": [ 138 | "\n" 139 | ] 140 | } 141 | ], 142 | "source": [ 143 | "s_list = []\n", 144 | "for i, s in enumerate(lcg(n, a, c, s0)):\n", 145 | " if i == 100:\n", 146 | " break\n", 147 | " s_list.append(s)\n", 148 | "s_list = s_list[-3:]\n", 149 | "print()" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 22, 155 | "metadata": {}, 156 | "outputs": [ 157 | { 158 | "data": { 159 | "text/plain": [ 160 | "[7069843410600921750773216882817131747030272542317631706718102992809185998190651209087209896703063661290035343302422897997519948973036744711053617418084672,\n", 161 | " 6381658174375721988221849622225151332002647602829904206260936732096794761994834683367137126578371140647084566044901718545192610854134126214359859505195708,\n", 162 | " 1164514516946568060322739436593388053704035783550399779338228888731094291364275001726254939824356384434223109829070637246326191067862562083514228611484436]" 163 | ] 164 | }, 165 | "execution_count": 22, 166 | "metadata": {}, 167 | "output_type": "execute_result" 168 | } 169 | ], 170 | "source": [ 171 | "s_list" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": 23, 177 | "metadata": {}, 178 | "outputs": [], 179 | "source": [ 180 | "a_decr = ((s_list[1] - s_list[2]) * inverse((s_list[0] - s_list[1]), n)) % n\n", 181 | "c_decr = (s_list[1] - s_list[0] * (s_list[1] - s_list[2]) * inverse(s_list[0] - s_list[1], n)) % n" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": 24, 187 | "metadata": {}, 188 | "outputs": [ 189 | { 190 | "data": { 191 | "text/plain": [ 192 | "(110924620051623968447266268873007437161656047175321232942762078096800785291629,\n", 193 | " 78330055002505665395054081034167722403903079478840676381279591427631187922487)" 194 | ] 195 | }, 196 | "execution_count": 24, 197 | "metadata": {}, 198 | "output_type": "execute_result" 199 | } 200 | ], 201 | "source": [ 202 | "a_decr, c_decr" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 25, 208 | "metadata": {}, 209 | "outputs": [ 210 | { 211 | "data": { 212 | "text/plain": [ 213 | "(True, True)" 214 | ] 215 | }, 216 | "execution_count": 25, 217 | "metadata": {}, 218 | "output_type": "execute_result" 219 | } 220 | ], 221 | "source": [ 222 | "a_decr == a, c_decr == c" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "# Resources" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "https://www.youtube.com/watch?v=PtEivGPxwAI" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [] 245 | } 246 | ], 247 | "metadata": { 248 | "kernelspec": { 249 | "display_name": "Python 3", 250 | "language": "python", 251 | "name": "python3" 252 | }, 253 | "language_info": { 254 | "codemirror_mode": { 255 | "name": "ipython", 256 | "version": 3 257 | }, 258 | "file_extension": ".py", 259 | "mimetype": "text/x-python", 260 | "name": "python", 261 | "nbconvert_exporter": "python", 262 | "pygments_lexer": "ipython3", 263 | "version": "3.7.3" 264 | } 265 | }, 266 | "nbformat": 4, 267 | "nbformat_minor": 2 268 | } 269 | -------------------------------------------------------------------------------- /P1-Public-key/Elgamal/Elgamal_intro.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 3, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from Crypto.Util.number import long_to_bytes, bytes_to_long, GCD, getPrime, inverse\n", 10 | "import random" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Prerequisites" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "- Diffie hellman\n", 25 | "- Discrete logarithm Problem \n", 26 | "- Cyclic groups" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "# Theory" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "https://www.youtube.com/watch?v=6ARDqCckjfs" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "- Elgamal encryption is an public-key cryptosystem. It uses asymmetric key encryption for communicating between two parties and encrypting the message.\n", 48 | "- This cryptosystem is based on the difficulty of finding discrete logarithm in a cyclic group that is even if we know $g^a$ and $g^b$, it is extremely difficult to compute $g^{ab}$.\n", 49 | "- Elgamal is based on DLP. The same vulnerabilities apply here too" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "Parameter creation\n", 57 | "- Choose large prime $p$. Choose $g$ with large prime order $q$ (generator of $\\mathbb{Z}_p^*$)\n", 58 | "\n", 59 | "Key generation(Alice): \n", 60 | "- Choose private key $1 \\leq a \\leq p-1$ Compute $A=g^{a}(\\bmod p)$ \n", 61 | "- Publish the public key $(g, A, p)$\n", 62 | "\n", 63 | "Encryption(Bob): \n", 64 | "- Choose plaintext $m \\in \\{0, 1, \\dots, p-1\\}$ \n", 65 | "- Choose random element $1 \\leq k \\leq p-2$ \n", 66 | "- Use Alice's public key $A$ to compute \n", 67 | " - $c_{1} \\equiv g^{k} \\bmod p $ = ephemeral key (random each time)\n", 68 | " - $c_{2} \\equiv m A^{k} \\equiv m \\cdot g^{ak} \\bmod p$\n", 69 | " \n", 70 | "- Send ciphertext $\\left(c_{1}, c_{2}\\right)$ to Alice.\n", 71 | "\n", 72 | "Decryption(Alice): \n", 73 | "- Compute $\\left(c_{1}^{a}\\right)^{-1} \\cdot c_{2}(\\bmod p)$\n", 74 | "- This quantity is equal to $m$" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "**Decryption Proof**:\n", 82 | "\n", 83 | "$x \\equiv\\left(c_{1}^{a}\\right)^{-1}(\\bmod p)$\n", 84 | "\n", 85 | "$\\begin{aligned} x \\cdot c_{2} & \\equiv\\left(c_{1}^{a}\\right)^{-1} \\cdot c_{2} &(\\bmod p), & \\text { since } x \\equiv\\left(c_{1}^{a}\\right)^{-1}(\\bmod p) \\\\ & \\equiv\\left(g^{a k}\\right)^{-1} \\cdot\\left(m A^{k}\\right) &(\\bmod p), & \\text { since } c_{1} \\equiv g^{k}, c_{2} \\equiv m A^{k}(\\bmod p) \\\\ & \\equiv\\left(g^{a k}\\right)^{-1} \\cdot\\left(m\\left(g^{a}\\right)^{k}\\right)(\\bmod p), & & \\text { since } A \\equiv g^{a}(\\bmod p) \\end{aligned}$\n", 86 | "$\\equiv m$\n", 87 | "$(\\bmod p)$\n", 88 | "since the $g^{a k}$ terms cancel out." 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "**Remark**:\n", 96 | "- $+$ since $k$ is random every time => encrypting the same message twice will output the different results\n", 97 | "- $-$ a general ElGamal encryption produces a 2:1 expansion in size from plaintext to ciphertext (we need c1 and c2).\n", 98 | "- $\\pm$ Encryption under ElGamal requires two exponentiations; however, these exponentiations are independent of the message (precomputed) and can be computed ahead of time if need be" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "**Security**\n", 106 | "- DLP weaknesses (If we have an DLP algorithm)\n", 107 | " - we can compute $a$ from $g^a \\equiv A \\bmod p$ => we can compute the shared key $g^{ak}$ (ephemeral key) => we can decrypt\n", 108 | " - we can compute $k$" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "# Code" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 9, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [ 124 | "def gen_params():\n", 125 | " p = getPrime(1024)\n", 126 | " g = 2\n", 127 | " return g, p\n", 128 | "\n", 129 | "\n", 130 | "def gen_keys(g, p):\n", 131 | " a = random.randint(1, p-1)\n", 132 | " return pow(g, a, p), a\n", 133 | "\n", 134 | "\n", 135 | "def elg_encryption(m, A, g, p):\n", 136 | " k = random.randint(1, p-1)\n", 137 | " c1 = pow(g, k, p)\n", 138 | " c2 = (m * pow(A, k, p))% p\n", 139 | " return c1, c2\n", 140 | "\n", 141 | "def elg_decryption(c1, c2, a, p):\n", 142 | " x = inverse(pow(c1, a, p), p)\n", 143 | " m_decr =(x * c2) % p\n", 144 | " return m_decr" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 10, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [ 153 | "g, p = gen_params()\n", 154 | "A, a = gen_keys(g, p)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 11, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [ 163 | "m = bytes_to_long(b'secret_message')\n", 164 | "c1, c2 = elg_encryption(m, A, g, p)\n", 165 | "m_decr = elg_decryption(c1, c2, a, p)" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 14, 171 | "metadata": {}, 172 | "outputs": [ 173 | { 174 | "name": "stdout", 175 | "output_type": "stream", 176 | "text": [ 177 | "True\n", 178 | "b'secret_message'\n" 179 | ] 180 | } 181 | ], 182 | "source": [ 183 | "print(m_decr == m)\n", 184 | "print(long_to_bytes(m_decr))" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "# Resources" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "- https://github.com/ashutosh1206/Crypton/tree/master/Elgamal-Encryption\n", 199 | "- https://en.wikipedia.org/wiki/ElGamal_encryption\n", 200 | "- https://mathstats.uncg.edu/sites/pauli/112/HTML/secelgamal.html\n", 201 | "- http://cryptowiki.net/index.php?title=El_Gamal_Scheme\n", 202 | "- https://www.youtube.com/watch?v=pyirxbHuvOw" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [] 211 | } 212 | ], 213 | "metadata": { 214 | "kernelspec": { 215 | "display_name": "Python 3", 216 | "language": "python", 217 | "name": "python3" 218 | }, 219 | "language_info": { 220 | "codemirror_mode": { 221 | "name": "ipython", 222 | "version": 3 223 | }, 224 | "file_extension": ".py", 225 | "mimetype": "text/x-python", 226 | "name": "python", 227 | "nbconvert_exporter": "python", 228 | "pygments_lexer": "ipython3", 229 | "version": "3.9.1" 230 | }, 231 | "toc": { 232 | "base_numbering": 1, 233 | "nav_menu": {}, 234 | "number_sections": true, 235 | "sideBar": true, 236 | "skip_h1_title": false, 237 | "title_cell": "Table of Contents", 238 | "title_sidebar": "Contents", 239 | "toc_cell": false, 240 | "toc_position": {}, 241 | "toc_section_display": true, 242 | "toc_window_display": false 243 | } 244 | }, 245 | "nbformat": 4, 246 | "nbformat_minor": 2 247 | } 248 | -------------------------------------------------------------------------------- /E1-Mathematics/Primes-and-Primality-tests/1. Fermats_test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 3, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2021-04-18T10:42:36.285247Z", 9 | "start_time": "2021-04-18T10:42:36.267236Z" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "from Crypto.Util.number import inverse, GCD, isPrime, getPrime" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# Prerequisites" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "- Number theory basics" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "# Theory" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "- https://en.wikipedia.org/wiki/Primality_test" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "## Probabilistic primality tests" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "- methods by which arbitrary positive integers are tested to provide **partial information** regarding their primality. \n", 57 | "\n", 58 | "How do they work?\n", 59 | "For each odd positive integern,a set $W(n)⊂\\mathbb{Z}_n$ is defined such that the following properties hold:\n", 60 | "1. given $a∈\\mathbb{Z}_n$, it can be checked in deterministic polynomial time whether $a∈W(n)$;\n", 61 | "2. if $n$ is prime, then $W(n)=∅$(the empty set)\n", 62 | "3. if $n$ is composite, then $|W(n)|≥\\dfrac n 2$.\n", 63 | "\n", 64 | "**Def**\n", 65 | "- If $n$ is composite, the elements of $W(n)$are called **witnesses** to the compositeness of $n$, and the elements of the complementary set $L(n)=\\mathbb{Z}_n−W(n)$ are called **liars**\n", 66 | "\n", 67 | "**Framework**:\n", 68 | "- Choose a random $a\\in \\mathbb{Z}_n$\n", 69 | "- Check if $a \\in W(n)$\n", 70 | "- If $a \\in W(n)$\n", 71 | " - return composite (the test is failed with respect to base $a$ => $n$ is **certain** to be composite\n", 72 | "- Else\n", 73 | " - return prime (the test is passed with respect to base $a$) => no conclusion can be drawn => $n$ is **probably prime**\n", 74 | " \n", 75 | "**Remark**:\n", 76 | "- The more tests if passes the higher the probability our probable prime has to be prime\n", 77 | "- We trade computing time for a better approximation of our probable prime" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "## Fermat's test" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "- https://en.wikipedia.org/wiki/Fermat_primality_test" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "**Fermat's theorem**:\n", 99 | "- Let $p$ be a prime number and $a$ be an integer not divisible by $p$. Then $a^{p-1} - 1$ is always divisible by $p$, or $a^{p-1} \\equiv 1 \\pmod{p}$\n", 100 | "\n", 101 | "**Idea**: \n", 102 | "- Use the converse :\n", 103 | " - if for some $a$ not divisible by $n$ we have $a^{n-1} \\not\\equiv 1 \\pmod{n}$, then $n$ is definitely composite\n", 104 | " \n", 105 | "**Algorithm**: \n", 106 | "- input $n>3$,the number to be tested and $k$, the number of tests / a bound\n", 107 | "- Repeat k times:\n", 108 | " - Pick a random $a \\in \\{2, n-2\\}$\n", 109 | " - if $a^{n-1} \\not\\equiv 1 \\bmod n$\n", 110 | " - return composite\n", 111 | " - else\n", 112 | " - continue\n", 113 | "- if no composite is returned then return probably prime\n", 114 | " " 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 4, 120 | "metadata": { 121 | "ExecuteTime": { 122 | "end_time": "2021-04-18T10:42:38.831898Z", 123 | "start_time": "2021-04-18T10:42:38.811882Z" 124 | } 125 | }, 126 | "outputs": [], 127 | "source": [ 128 | "import random\n", 129 | "\n", 130 | "def fermat_test(n, k):\n", 131 | " for i in range(k):\n", 132 | " a = random.randint(2, n-2)\n", 133 | " #print(a)\n", 134 | " if GCD(a, n)!=1: ##Remark this should return COMPOSITE (since you found a divisor !=1) but to show the flaw we did it this way\n", 135 | " i-=1\n", 136 | " continue\n", 137 | " if pow(a, n-1, n) != 1:\n", 138 | " return 'Composite'\n", 139 | " return 'Probably prime'" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 5, 145 | "metadata": { 146 | "ExecuteTime": { 147 | "end_time": "2021-04-18T10:42:39.116928Z", 148 | "start_time": "2021-04-18T10:42:38.964928Z" 149 | } 150 | }, 151 | "outputs": [ 152 | { 153 | "name": "stdout", 154 | "output_type": "stream", 155 | "text": [ 156 | "Composite\n", 157 | "Probably prime\n" 158 | ] 159 | } 160 | ], 161 | "source": [ 162 | "print(fermat_test(2403, 12))\n", 163 | "p = getPrime(512)\n", 164 | "print(fermat_test(p, 100))" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "### Flaw" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "Carmichael numbers pass the test yet they aren't prime:\n", 179 | "- Let $n$ be a Carmichael number, then $a^{n-1} \\equiv 1 \\bmod n$ for **all** $a$ with $\\gcd(a,n) =1$\n", 180 | "- Therefore the search for composite is the same as a search for its factors\n" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": 12, 186 | "metadata": { 187 | "ExecuteTime": { 188 | "end_time": "2021-04-18T10:44:20.180541Z", 189 | "start_time": "2021-04-18T10:44:20.171544Z" 190 | } 191 | }, 192 | "outputs": [ 193 | { 194 | "name": "stdout", 195 | "output_type": "stream", 196 | "text": [ 197 | "561 is Probably prime but 561 % 3 = 0\n", 198 | "41041 is Probably prime but 41041 % 11 = 0\n" 199 | ] 200 | } 201 | ], 202 | "source": [ 203 | "print(f\"561 is {fermat_test(561, 100)} but 561 % 3 = {561 % 3}\")\n", 204 | "print(f\"41041 is {fermat_test(41041, 100)} but 41041 % 11 = {41041 % 11}\")" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "# Resources" 212 | ] 213 | }, 214 | { 215 | "cell_type": "markdown", 216 | "metadata": {}, 217 | "source": [ 218 | "- https://www.youtube.com/watch?v=oUMotDWVLpw\n", 219 | "- https://www.youtube.com/watch?v=jbiaz_aHHUQ" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "metadata": {}, 226 | "outputs": [], 227 | "source": [] 228 | } 229 | ], 230 | "metadata": { 231 | "kernelspec": { 232 | "display_name": "Python 3", 233 | "language": "python", 234 | "name": "python3" 235 | }, 236 | "language_info": { 237 | "codemirror_mode": { 238 | "name": "ipython", 239 | "version": 3 240 | }, 241 | "file_extension": ".py", 242 | "mimetype": "text/x-python", 243 | "name": "python", 244 | "nbconvert_exporter": "python", 245 | "pygments_lexer": "ipython3", 246 | "version": "3.9.4" 247 | }, 248 | "toc": { 249 | "base_numbering": 1, 250 | "nav_menu": {}, 251 | "number_sections": true, 252 | "sideBar": true, 253 | "skip_h1_title": false, 254 | "title_cell": "Table of Contents", 255 | "title_sidebar": "Contents", 256 | "toc_cell": false, 257 | "toc_position": {}, 258 | "toc_section_display": true, 259 | "toc_window_display": false 260 | } 261 | }, 262 | "nbformat": 4, 263 | "nbformat_minor": 2 264 | } 265 | -------------------------------------------------------------------------------- /E3-Homomorphic-Encryption/Paillier Encryption Scheme.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prerequisites\n", 8 | "- Homomorphic encryption pdf\n", 9 | "- Modular arithmetic" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "# Theory" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "**Key generation**\n", 24 | "- Choose large primes $p, q$ s.t $\\gcd(p\\cdot q, (p-1)(q-1)) = 1$\n", 25 | "- Let \n", 26 | " - $n = pq$\n", 27 | " - $\\lambda = \\text{lcm}(p-1, q-1)$\n", 28 | " \n", 29 | "- Select random $g \\in \\mathbb{Z}^*_{n^2}$ \n", 30 | "- ensure $n$ divides $|g|$ by checking if $\\mu = (L(g^\\lambda \\bmod n^2))^{-1} \\bmod n$ exists where $L = \\dfrac {x-1} n$ where division represents the quotient \n", 31 | "- *Public (encryption) key:* $(n,g)$\n", 32 | "- *Private(decryption) key:* $(\\lambda,\\mu)$\n", 33 | "\n", 34 | "**Encryption**\n", 35 | "- Let $m \\in \\mathbb{Z}_n$ be a message\n", 36 | "- Let $r \\in \\mathbb{Z}_n^*$ be a random number with $\\gcd(r, n) = 1$\n", 37 | "- Return $c = g^m \\cdot r^n \\bmod n^2$\n", 38 | "\n", 39 | "**Decryption**\n", 40 | "- $m = L(c^\\lambda \\bmod n^2) \\cdot \\mu \\bmod n$" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "## Homomorphic properties" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "Let there be 2 encrypted messages\n", 55 | "- $c_1 = E(m_1,pk) = g^{m_1} \\cdot r^{n}_1 \\bmod n^2$\n", 56 | "- $c_2 = E(m_2,pk) = g^{m_2} \\cdot r^{n}_2 \\bmod n^2$" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "### Addition\n", 64 | "> The *product* of the ciphertext decrypts to the *sum* of the plaintexts\n", 65 | "> $$D(c_1 \\cdot c_2 \\bmod n^2) = m_1 + m_2 \\bmod n$$\n", 66 | "\n", 67 | "**Proof**\n", 68 | "\n", 69 | "$\\begin{equation}\n", 70 | "\\begin{split}\n", 71 | "c_1 \\cdot c_2 & = (g^{m_1} \\cdot r^{n}_1)(g^{m_2} \\cdot r^{n}_2) \\bmod n^2 \\\\\n", 72 | "& = g^{m_1 + m_2}(r_1r_2)^n \\bmod n^2 \\\\\n", 73 | "& = E(m_1 + m_2, pk) \n", 74 | "\\end{split}\n", 75 | "\\end{equation}$" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "### Multiplication\n", 83 | "\n", 84 | "> An encrypted plaintext raised to the power of another plaintext will decrypt to the product of the two plaintexts,\n", 85 | "> $$D(c_1^{m_2} \\bmod n^2) = m_1\\ m_2 \\bmod n \\\\ D(c_2^{m_1} \\bmod n^2) = m_1\\ m_2 \\bmod n$$\n", 86 | "\n", 87 | "**Proof**\n", 88 | "\n", 89 | "$\\begin{equation}\n", 90 | "\\begin{split}\n", 91 | "c_1 \\cdot c_2 & = (g^{m_1} \\cdot r^{n}_1)^{m_2} \\bmod n^2 \\\\\n", 92 | "& = g^{m_1m_2}(r_1^{m_2})^n \\bmod n^2 \\\\\n", 93 | "& = E(m_1m_2, pk) \n", 94 | "\\end{split}\n", 95 | "\\end{equation}$" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "# Code" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 1, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "import random\n", 112 | "from Crypto.Util.number import GCD, bytes_to_long, getPrime, inverse, long_to_bytes" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 2, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "def keygen():\n", 122 | " p = getPrime(1024)\n", 123 | " q = getPrime(1024)\n", 124 | " assert GCD(p * q, (p - 1) * (q - 1)) == 1, \"GCD != 1\"\n", 125 | "\n", 126 | " n = p * q\n", 127 | " phi = (p - 1) * (q - 1)\n", 128 | " lambdaa = phi\n", 129 | " g = n + 1\n", 130 | " mu = inverse(phi, n)\n", 131 | "\n", 132 | " return (n, g), (lambdaa, mu)\n", 133 | "\n", 134 | "\n", 135 | "def encrypt(m, n, g):\n", 136 | " while True:\n", 137 | " r = random.randint(1, n - 1)\n", 138 | " if GCD(n, r) == 1:\n", 139 | " break\n", 140 | " c = (pow(g, m, n**2) * pow(r, n, n**2)) % (n**2)\n", 141 | "\n", 142 | " return c\n", 143 | "\n", 144 | "\n", 145 | "def decrypt(c, n, g, lambdaa, mu):\n", 146 | " temp = pow(c, lambdaa, n**2)\n", 147 | " temp = (temp - 1) // n\n", 148 | " m = (temp * mu) % n\n", 149 | "\n", 150 | " return m" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 3, 156 | "metadata": {}, 157 | "outputs": [], 158 | "source": [ 159 | "(n, g), (lambdaa, mu) = keygen()\n", 160 | "# (n, g), (lambdaa, mu)" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": 4, 166 | "metadata": {}, 167 | "outputs": [ 168 | { 169 | "name": "stdout", 170 | "output_type": "stream", 171 | "text": [ 172 | "b'secret_message'\n" 173 | ] 174 | } 175 | ], 176 | "source": [ 177 | "# Encryption\n", 178 | "\n", 179 | "m = bytes_to_long(b\"secret_message\")\n", 180 | "c = encrypt(m, n, g)\n", 181 | "m_decr = decrypt(c, n, g, lambdaa, mu)\n", 182 | "\n", 183 | "print(long_to_bytes(m_decr))" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 5, 189 | "metadata": {}, 190 | "outputs": [ 191 | { 192 | "data": { 193 | "text/plain": [ 194 | "(3000, 3000)" 195 | ] 196 | }, 197 | "execution_count": 5, 198 | "metadata": {}, 199 | "output_type": "execute_result" 200 | } 201 | ], 202 | "source": [ 203 | "# Addition\n", 204 | "(n, g), (lambdaa, mu) = keygen()\n", 205 | "\n", 206 | "m1 = 1000\n", 207 | "m2 = 2000\n", 208 | "\n", 209 | "c1 = encrypt(m1, n, g)\n", 210 | "c2 = encrypt(m2, n, g)\n", 211 | "\n", 212 | "c3 = c1 * c2\n", 213 | "m3 = decrypt(c3, n, g, lambdaa, mu)\n", 214 | "\n", 215 | "m1 + m2, m3" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 6, 221 | "metadata": {}, 222 | "outputs": [ 223 | { 224 | "data": { 225 | "text/plain": [ 226 | "(2000000, 2000000)" 227 | ] 228 | }, 229 | "execution_count": 6, 230 | "metadata": {}, 231 | "output_type": "execute_result" 232 | } 233 | ], 234 | "source": [ 235 | "# Multiplication\n", 236 | "\n", 237 | "(n, g), (lambdaa, mu) = keygen()\n", 238 | "\n", 239 | "m1 = 1000\n", 240 | "m2 = 2000\n", 241 | "\n", 242 | "c1 = encrypt(m1, n, g)\n", 243 | "\n", 244 | "c3 = pow(c1, m2, n**2)\n", 245 | "m3 = decrypt(c3, n, g, lambdaa, mu)\n", 246 | "\n", 247 | "m1 * m2, m3" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "# Resources" 255 | ] 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "metadata": {}, 260 | "source": [ 261 | "- [Wikipedia](https://en.wikipedia.org/wiki/Paillier_cryptosystem)\n", 262 | "- [Opendmined blog](https://blog.openmined.org/the-paillier-cryptosystem/)\n", 263 | "- [original paper](https://www.cs.tau.ac.il/~fiat/crypt07/papers/Pai99pai.pdf )\n", 264 | "- Paillier_cryptosystemhttp://cryptowiki.net/index.php?title=Partially_homomorphic_encryption_schemes" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": null, 270 | "metadata": {}, 271 | "outputs": [], 272 | "source": [] 273 | } 274 | ], 275 | "metadata": { 276 | "kernelspec": { 277 | "display_name": "Python 3 (ipykernel)", 278 | "language": "python", 279 | "name": "python3" 280 | }, 281 | "language_info": { 282 | "codemirror_mode": { 283 | "name": "ipython", 284 | "version": 3 285 | }, 286 | "file_extension": ".py", 287 | "mimetype": "text/x-python", 288 | "name": "python", 289 | "nbconvert_exporter": "python", 290 | "pygments_lexer": "ipython3", 291 | "version": "3.10.4" 292 | } 293 | }, 294 | "nbformat": 4, 295 | "nbformat_minor": 4 296 | } 297 | -------------------------------------------------------------------------------- /P1-Public-key/Diffie-Hellman/Vulnerabilities/Man_in_the_middle.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 34, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2020-09-11T07:35:15.504637Z", 9 | "start_time": "2020-09-11T07:35:15.499633Z" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "import hashlib\n", 15 | "import random\n", 16 | "\n", 17 | "from Crypto.Cipher import AES\n", 18 | "from Crypto.Util.number import GCD, inverse, sieve_base\n", 19 | "from Crypto.Util.Padding import pad, unpad\n", 20 | "\n", 21 | "## Helper functions\n", 22 | "\n", 23 | "\n", 24 | "def generate_private_key(p):\n", 25 | " secret_key = random.randint(1, p - 1)\n", 26 | " return secret_key\n", 27 | "\n", 28 | "\n", 29 | "def generate_public_key(g, secret_key, p):\n", 30 | " return pow(g, secret_key, p)" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "# Prerequisites" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "ExecuteTime": { 44 | "end_time": "2020-09-11T06:36:10.111665Z", 45 | "start_time": "2020-09-11T06:36:10.107648Z" 46 | } 47 | }, 48 | "source": [ 49 | "- DLP and its vulnerabilities\n", 50 | "- DH basics\n", 51 | "- Group theory" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "# Theory + Attacks" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "- https://en.wikipedia.org/wiki/Man-in-the-middle_attack\n", 66 | "- https://stackoverflow.com/questions/10471009/how-does-the-man-in-the-middle-attack-work-in-diffie-hellman\n", 67 | "- Computerphile https://www.youtube.com/watch?v=vsXMMT2CqqE&t=276s&ab_channel=Computerphile\n", 68 | "\n", 69 | "Basic Diffie Hellman key exchange can be broken if Eve is in the middle of the conversation and mingles with parameters \n", 70 | "We will present some ways this can happen" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "# Attacks" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 12, 83 | "metadata": { 84 | "ExecuteTime": { 85 | "end_time": "2020-09-11T06:47:53.652705Z", 86 | "start_time": "2020-09-11T06:47:53.648692Z" 87 | } 88 | }, 89 | "outputs": [ 90 | { 91 | "data": { 92 | "text/plain": [ 93 | "1536" 94 | ] 95 | }, 96 | "execution_count": 12, 97 | "metadata": {}, 98 | "output_type": "execute_result" 99 | } 100 | ], 101 | "source": [ 102 | "g = 2\n", 103 | "# Good small-sized p\n", 104 | "p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF\n", 105 | "p.bit_length()" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "## If you can intercepted Alice and can send parameters to Bob" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "You know $A, p, g$ \n", 120 | "Send to Bob:\n", 121 | "- p = p\n", 122 | "- g = A\n", 123 | "- A = A\n", 124 | "\n", 125 | "Bob will compute \n", 126 | "- $B = A^b = g^{ab}$ as his public key that you will know\n", 127 | "- $A^b = g^{ab}$ as the secret key\n", 128 | "\n", 129 | "Therefore you'll know $B$ as the secret_key and send it back to Alice\n", 130 | "\n", 131 | "**Note** This method works to decrypt past messages too if Bob uses a *static* key (doesn't change it)" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 32, 137 | "metadata": { 138 | "ExecuteTime": { 139 | "end_time": "2020-09-11T07:02:29.014935Z", 140 | "start_time": "2020-09-11T07:02:28.967903Z" 141 | } 142 | }, 143 | "outputs": [], 144 | "source": [ 145 | "a = generate_private_key(p) # you don't know this\n", 146 | "A = generate_public_key(g, a, p) # you know this\n", 147 | "\n", 148 | "# Send p = p, g = A, A = A\n", 149 | "b = generate_private_key(p) # you don't know this\n", 150 | "B = generate_public_key(A, b, p) # you know this\n", 151 | "\n", 152 | "# secret\n", 153 | "shared_secret = pow(A, b, p)" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 33, 159 | "metadata": { 160 | "ExecuteTime": { 161 | "end_time": "2020-09-11T07:02:29.530544Z", 162 | "start_time": "2020-09-11T07:02:29.527533Z" 163 | } 164 | }, 165 | "outputs": [ 166 | { 167 | "data": { 168 | "text/plain": [ 169 | "True" 170 | ] 171 | }, 172 | "execution_count": 33, 173 | "metadata": {}, 174 | "output_type": "execute_result" 175 | } 176 | ], 177 | "source": [ 178 | "shared_secret == B" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "## You can only change the prime $p$" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "- Suppose Alice and Bob exchanged parameters once already $(p, g)$. You can send $(p', g')$\n", 193 | "\n", 194 | "If Bob verifies $g = g'$ and you are allowed only to change the prime $p$ then you can setup a group weak to Pohlig-Hellman DLP\n", 195 | "- if $p$ is strong => $p = 2q+1$ with $q$ prime => $p-1$ is divisible only by $2$ and some big prime\n", 196 | "- make your $p' = 2 \\cdot \\Pi_{k=1}^{n} P_i^{e_i} + 1$ for some $n$ you chose and some small primes $P_i$ of your choice. This group is vulnerable to Pohlig-Hellman since $p'-1$ is smooth. The order of 2 must be the same order as in $p-1$ to ensure the solutions are the same\n", 197 | "- If Bob uses this group to compute $g^b = B \\ mod \\ p' $ Then you can efficiently solve the DLP and find his $b$\n", 198 | "\n", 199 | "**Note** This method works to decrypt past messages too if Bob uses a *static* key (doesn't change it)" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": {}, 205 | "source": [ 206 | "# Downgrading" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": {}, 212 | "source": [ 213 | "*Idea*: \n", 214 | "- Before exchanging messages Bob and Alice need to exchange the security protocol (bitsize / type of encryption)\n", 215 | "- Eve can mingle with these negotiations and downgrade the encryption\n", 216 | "\n", 217 | "Logjam attack: \n", 218 | "- https://www.youtube.com/watch?v=Qi8ynAB2dpM&ab_channel=DevanSingh\n", 219 | "- https://en.wikipedia.org/wiki/Logjam_(computer_security)\n", 220 | "- https://cryptologie.net/article/270/the-logjam-attack/\n", 221 | " " 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [] 230 | } 231 | ], 232 | "metadata": { 233 | "kernelspec": { 234 | "display_name": "Python 3 (ipykernel)", 235 | "language": "python", 236 | "name": "python3" 237 | }, 238 | "language_info": { 239 | "codemirror_mode": { 240 | "name": "ipython", 241 | "version": 3 242 | }, 243 | "file_extension": ".py", 244 | "mimetype": "text/x-python", 245 | "name": "python", 246 | "nbconvert_exporter": "python", 247 | "pygments_lexer": "ipython3", 248 | "version": "3.10.4" 249 | }, 250 | "toc": { 251 | "base_numbering": 1, 252 | "nav_menu": {}, 253 | "number_sections": true, 254 | "sideBar": true, 255 | "skip_h1_title": false, 256 | "title_cell": "Table of Contents", 257 | "title_sidebar": "Contents", 258 | "toc_cell": false, 259 | "toc_position": {}, 260 | "toc_section_display": true, 261 | "toc_window_display": false 262 | } 263 | }, 264 | "nbformat": 4, 265 | "nbformat_minor": 4 266 | } 267 | -------------------------------------------------------------------------------- /E1-Mathematics/Factorization/Fermat_fact_p_q_are_close.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2020-08-30T07:32:04.694706Z", 9 | "start_time": "2020-08-30T07:32:04.688702Z" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "import math\n", 15 | "import random\n", 16 | "\n", 17 | "import numpy as np\n", 18 | "from Crypto.Util.number import (\n", 19 | " GCD,\n", 20 | " bytes_to_long,\n", 21 | " getPrime,\n", 22 | " inverse,\n", 23 | " isPrime,\n", 24 | " long_to_bytes,\n", 25 | ")\n", 26 | "\n", 27 | "# helper functions\n", 28 | "\n", 29 | "\n", 30 | "def isqrt(n):\n", 31 | " x = n\n", 32 | " y = (x + 1) // 2\n", 33 | " while y < x:\n", 34 | " x = y\n", 35 | " y = (x + n // x) // 2\n", 36 | " return x\n", 37 | "\n", 38 | "\n", 39 | "def is_square(apositiveint):\n", 40 | " x = apositiveint // 2\n", 41 | " seen = set([x])\n", 42 | " while x * x != apositiveint:\n", 43 | " x = (x + (apositiveint // x)) // 2\n", 44 | " if x in seen:\n", 45 | " return False\n", 46 | " seen.add(x)\n", 47 | " return True" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "# Prerequisites" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "* $a^2 - b^2 = (a+b)(a-b)$" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": { 67 | "ExecuteTime": { 68 | "end_time": "2020-08-30T06:53:12.064452Z", 69 | "start_time": "2020-08-30T06:53:12.061450Z" 70 | } 71 | }, 72 | "source": [ 73 | "# Theory" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "[Video Explanation](https://www.youtube.com/watch?v=tUUE41Gc5Q8&list=PLKXdxQAT3tCssgaWOy5vKXAR4WTPpRVYK&index=70)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "Let $N$ be the number to be factored\n", 88 | "\n", 89 | "[Every odd number is a difference of two squares](https://math.stackexchange.com/questions/263101/prove-every-odd-integer-is-the-difference-of-two-squares)\n", 90 | "\n", 91 | "$N = a^2 - b^2 = (a+b)(a-b) \\\\\n", 92 | "\\text{Let} \\\\\n", 93 | "a = p+q \\\\\n", 94 | "b = p-q \\\\\n", 95 | "a + b = 2p\\\\\n", 96 | "a - b = 2q\\\\\n", 97 | "\\text{Then} \\ N = pq = \\left( \\dfrac {p + q} 2 \\right) ^2 - \\left( \\dfrac {p - q} 2 \\right) ^2 \n", 98 | "$\n" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": { 104 | "ExecuteTime": { 105 | "end_time": "2020-08-30T07:18:28.478808Z", 106 | "start_time": "2020-08-30T07:18:28.474802Z" 107 | } 108 | }, 109 | "source": [ 110 | "**Task**:\n", 111 | "\n", 112 | "Find $b^2$ such that $N+b^2 = a^2$" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "## Solution 1: Try all" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "1. Try all $k = 1, 2, ....$ until we find a $N + k^2 = \\text{square}$ \n", 127 | "\n", 128 | "or\n", 129 | "\n", 130 | "2. Let $k$ be the smallest positive integer s.t $k^2 > n$ => $k = \\lceil \\sqrt(n) \\rceil$ \n", 131 | "* if $k^2-n = h^2$ then $n = (k+h)(k-h)$\n", 132 | "* else increment k" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "**Efficiency trick**: $(k+1)^2 = k^2 + 2squaresk + 1$ => we can find the next square recursively" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "# Code" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 2, 152 | "metadata": { 153 | "ExecuteTime": { 154 | "end_time": "2020-08-30T07:44:52.672764Z", 155 | "start_time": "2020-08-30T07:44:52.668762Z" 156 | } 157 | }, 158 | "outputs": [], 159 | "source": [ 160 | "def fermat_fact(n: int):\n", 161 | " \"\"\"Fermat factorization\n", 162 | "\n", 163 | " Parameters\n", 164 | " ----------\n", 165 | " n : int\n", 166 | " number to be factored\n", 167 | "\n", 168 | " Returns\n", 169 | " -------\n", 170 | " (int, int)\n", 171 | " Factors of n\n", 172 | " \"\"\"\n", 173 | " a = isqrt(n) + 1\n", 174 | " b2 = pow(a, 2) - n\n", 175 | " while not is_square(b2):\n", 176 | " b2 = b2 + 2 * a + 1\n", 177 | " a = a + 1\n", 178 | " return a - isqrt(b2), a + isqrt(b2) # the factors of N" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 3, 184 | "metadata": { 185 | "ExecuteTime": { 186 | "end_time": "2020-08-30T07:42:23.966274Z", 187 | "start_time": "2020-08-30T07:42:23.962256Z" 188 | } 189 | }, 190 | "outputs": [], 191 | "source": [ 192 | "n = 383347712330877040452238619329524841763392526146840572232926924642094891453979246383798913394114305368360426867021623649667024217266529000859703542590316063318592391925062014229671423777796679798747131250552455356061834719512365575593221216339005132464338847195248627639623487124025890693416305788160905762011825079336880567461033322240015771102929696350161937950387427696385850443727777996483584464610046380722736790790188061964311222153985614287276995741553706506834906746892708903948496564047090014307484054609862129530262108669567834726352078060081889712109412073731026030466300060341737504223822014714056413752165841749368159510588178604096191956750941078391415634472219765129561622344109769892244712668402761549412177892054051266761597330660545704317210567759828757156904778495608968785747998059857467440128156068391746919684258227682866083662345263659558066864109212457286114506228470930775092735385388316268663664139056183180238043386636254075940621543717531670995823417070666005930452836389812129462051771646048498397195157405386923446893886593048680984896989809135802276892911038588008701926729269812453226891776546037663583893625479252643042517196958990266376741676514631089466493864064316127648074609662749196545969926051" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 4, 198 | "metadata": { 199 | "ExecuteTime": { 200 | "end_time": "2020-08-30T07:42:33.436997Z", 201 | "start_time": "2020-08-30T07:42:33.410978Z" 202 | } 203 | }, 204 | "outputs": [], 205 | "source": [ 206 | "p, q = fermat_fact(n)" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": 5, 212 | "metadata": { 213 | "ExecuteTime": { 214 | "end_time": "2020-08-30T07:42:38.838559Z", 215 | "start_time": "2020-08-30T07:42:38.834542Z" 216 | } 217 | }, 218 | "outputs": [ 219 | { 220 | "data": { 221 | "text/plain": [ 222 | "True" 223 | ] 224 | }, 225 | "execution_count": 5, 226 | "metadata": {}, 227 | "output_type": "execute_result" 228 | } 229 | ], 230 | "source": [ 231 | "p * q == n" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "# Resources" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "* https://en.wikipedia.org/wiki/Fermat%27s_factorization_method#Basic_method\n", 246 | "* https://www.nku.edu/~christensen/Mathematical%20attack%20on%20RSA.pdf\n", 247 | "* https://mathworld.wolfram.com/FermatsFactorizationMethod.html\n", 248 | "* https://www.geeksforgeeks.org/fermats-factorization-method/" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": null, 254 | "metadata": {}, 255 | "outputs": [], 256 | "source": [] 257 | } 258 | ], 259 | "metadata": { 260 | "kernelspec": { 261 | "display_name": "Python 3 (ipykernel)", 262 | "language": "python", 263 | "name": "python3" 264 | }, 265 | "language_info": { 266 | "codemirror_mode": { 267 | "name": "ipython", 268 | "version": 3 269 | }, 270 | "file_extension": ".py", 271 | "mimetype": "text/x-python", 272 | "name": "python", 273 | "nbconvert_exporter": "python", 274 | "pygments_lexer": "ipython3", 275 | "version": "3.10.4" 276 | }, 277 | "toc": { 278 | "base_numbering": 1, 279 | "nav_menu": {}, 280 | "number_sections": true, 281 | "sideBar": true, 282 | "skip_h1_title": false, 283 | "title_cell": "Table of Contents", 284 | "title_sidebar": "Contents", 285 | "toc_cell": false, 286 | "toc_position": {}, 287 | "toc_section_display": true, 288 | "toc_window_display": false 289 | } 290 | }, 291 | "nbformat": 4, 292 | "nbformat_minor": 4 293 | } 294 | -------------------------------------------------------------------------------- /E1-Mathematics/Factorization/Coppersmith_factorization_sage.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prerequisites" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "- RSA\n", 15 | "- Coppersmith attacks" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "# Theory" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "Explanation https://youtu.be/RgbrpmJ49r4?t=2321" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "**Theorem** Howgrave-Graham \n", 37 | "Given a polynomial $f$ of degree $d$ and integer $N$, we can find in polynomial time roots $r$ modulo divisors $B$ of $N$ satisfying\n", 38 | "$$f(r) \\equiv 0 \\ \\bmod \\ B$$ \n", 39 | "for $|B| > N^\\beta$ when $|r| < N^{\\beta^2 / d}$\n", 40 | "\n", 41 | "Same idea as Coppersmith but we find a vector in a lattice less than $N^\\beta < B$" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "**Theorem**:\n", 49 | " \n", 50 | "Given half of the MSB / LSB bits of a factor $p$, we can factor and RSA modulus $N = pq$ in polynomial time\n", 51 | "\n", 52 | "**Proof**:\n", 53 | "\n", 54 | "Let $f(x) = x + a$ where $a$ are the MSB of $p$, and $r$ are the LSB of $p$, so $a+r = p$\n", 55 | "- $f(x) \\equiv 0 \\ \\bmod \\ p > N^{1/2}$\n", 56 | "- Apply Howgrave-Graham for $d = 1$ and $\\beta = 1/2 \\Rightarrow |r| < N^{\\beta^2/d} = N^{1/4}$\n" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "We chose the polynomial basis:\n", 64 | "$(x+a)^2, x+a, N$ which corresponds to the lattice\n", 65 | "$$\\begin{bmatrix}\n", 66 | "R^2 & 2Ra & a^2 \\\\\n", 67 | "0 &R &a \\\\\n", 68 | "0 &0 &N\n", 69 | "\\end{bmatrix}\n", 70 | "$$\n", 71 | "with $\\dim L = 3$ and $\\det L = R^3N$\n", 72 | "\n", 73 | "From LLL => $|v| \\approx \\det L^{1/\\dim L}$\n", 74 | "\n", 75 | "The algorithm will find the root $r$ when $|g(r)| \\leq |v| \\approx \\det L^{1/\\dim L}

= PolynomialRing(Zmod(N))\n", 264 | " f = P(f)\n", 265 | " beta = .5\n", 266 | " dd = f.degree() # Degree of the polynomial (e for the above polynomial)\n", 267 | " epsilon = beta/7 #\n", 268 | " R = ceil(N**((beta**2/dd) - epsilon)) #The bound\n", 269 | " r = f.small_roots(R, beta, epsilon)\n", 270 | " return r" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": 24, 276 | "metadata": {}, 277 | "outputs": [], 278 | "source": [ 279 | "r = factorization_n(f, N)" 280 | ] 281 | }, 282 | { 283 | "cell_type": "code", 284 | "execution_count": 25, 285 | "metadata": {}, 286 | "outputs": [ 287 | { 288 | "data": { 289 | "text/plain": [ 290 | "True" 291 | ] 292 | }, 293 | "execution_count": 25, 294 | "metadata": {}, 295 | "output_type": "execute_result" 296 | } 297 | ], 298 | "source": [ 299 | "a + r[0] == p" 300 | ] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "metadata": {}, 305 | "source": [ 306 | "# Resources:" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "- [Coppersmith paper](https://cr.yp.to/bib/2001/coppersmith.pdf)\n", 314 | "- LLL for RSA - A survey: https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.9408&rep=rep1&type=pdf" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": null, 320 | "metadata": {}, 321 | "outputs": [], 322 | "source": [] 323 | } 324 | ], 325 | "metadata": { 326 | "kernelspec": { 327 | "display_name": "SageMath 9.5", 328 | "language": "sage", 329 | "name": "sagemath" 330 | }, 331 | "language_info": { 332 | "codemirror_mode": { 333 | "name": "ipython", 334 | "version": 3 335 | }, 336 | "file_extension": ".py", 337 | "mimetype": "text/x-python", 338 | "name": "python", 339 | "nbconvert_exporter": "python", 340 | "pygments_lexer": "ipython3", 341 | "version": "3.10.4" 342 | } 343 | }, 344 | "nbformat": 4, 345 | "nbformat_minor": 4 346 | } 347 | -------------------------------------------------------------------------------- /E1-Mathematics/Elliptic-curves/Rational_points_on_elliptic_curves/Chapter_3_The_group_of_rational_points.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 3. The group of rational points" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "The group of rational points $ C(\\mathbb{Q})$ is finitely generated" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## 3.1 Heights and descent" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "**Height**:\n", 29 | "\n", 30 | "The height of a rational point measures how complicated the point is from the viewpoint of number theory \n", 31 | "$$H(x)=H(\\frac m n)=\\max(|m|,|n|); \\ \\ H(x) \\in \\mathbb{Z}_+$$\n", 32 | "\n", 33 | "**Propriety**: *Finiteness Property of the Height*: The set of all rational numbers whose height is less than some fixed number is a finite set\n", 34 | "- If the height of $x=m/n$ is less than some fixed constant, then both $|m|$ and $|n|$ are less than that constant, so there are only finitely many possibilities for $m$ and $n$" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "If $y^2=f(x)=x^3+ax^2+bx+ci$ s a non-singular cubic curve with integer coefficients $a, b, c$ , and if $P=(x, y)$ is a rational point on the curve, we define the height of $P$ to be simply the height of its $x$-coordinate\n", 42 | "- $H(P)=H(x)$ (By convention, we set $H(\\mathcal{O})=1$.)\n", 43 | "\n", 44 | "**Propriety**: We will see that the height behaves somewhat multiplicatively relative to the addition law on the curve. \n", 45 | "- Ex: we will want to compare $H(P+Q)$ to the product $H(P)H(Q)$\n", 46 | "\n", 47 | "**Small h height**:\n", 48 | "$h(P)=\\log H(P)$" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "**Notation**: \n", 56 | "- For any commutative group $Γ$ ,the multiplication-by-$m$ map \n", 57 | " - $Γ →Γ$, $P →\\underbrace{P+···+P}_{\\text{m-terms}}=mP$ \n", 58 | "is a homomorphism, and the image of this homomorphism is the **subgroup** $mΓ$ of $Γ$\n", 59 | "- index of a group https://en.wikipedia.org/wiki/Index_of_a_subgroup\n", 60 | "- $\\Gamma = C(\\mathbb{Q})$ to ease notation\n", 61 | "\n", 62 | "\n", 63 | "**Theorem (Desecent Theorem)**\n", 64 | "\n", 65 | "Let $Γ$ be a commutative group, and suppose that there is a function $h: Γ→[0,∞)$ with the following three properties:\n", 66 | "1. $\\forall M \\in \\mathbb{R}$ the set $\\{P∈Γ:h(P)≤M\\}$ is finite.\n", 67 | "2. For every $P_0∈Γ$ there is a constant $κ_0$ so that $h(P+P_0)≤2h(P)+κ_0 \\ \\forall \\ P∈Γ $. -> height of any $P_0 + P$ is (roughly) less than twice the height of $P$\n", 68 | "3. There is a constant $κ$ so that $h(2P)≥4h(P)−κ \\ \\forall \\ P∈Γ$. -> when you double a point the height goes up a bit\n", 69 | "\n", 70 | "Suppose further that\n", 71 | "4. The subgroup $2Γ$ has finite index in $Γ$.\n", 72 | "\n", 73 | "Then $Γ$ is **finitely** generated.\n", 74 | "\n", 75 | "**Proof**: In the book\n", 76 | "\n", 77 | "*intuition for proof*: \n", 78 | "- https://en.wikipedia.org/wiki/Proof_by_infinite_descent\n", 79 | "- Start with arbitrary $P \\in C(\\mathbb{Q})$ => clever manipulations => smaller point (measured by some size = height in our case)\n", 80 | "\n" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "**The rest of the chapter is mostly proving this theorem and some examples**" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "## 3.7 Singular curves" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "Let $C$ be a cubic curve with a singular point $S∈C$. Then any line through $S$ intersects $C$ at $S$ with multiplicity at least two. If there were a second singular point $S′∈C$, then the line connecting $S$ and $S′$ would intersect $C$ at least twice at $S$ and at least twice at $S′$ ,so $L$ would intersect $C$ at least four times. But a line and a cubic intersect only three times counting multiplicities. Thus a cubic curve can have **at most one singular point**." 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "We want to make the points of C into a group:\n", 109 | "- Let $C_{ns}=\\{P∈C:P \\text{ is not a singular point }\\}$; \n", 110 | "- Let $C_{ns}(\\mathbb{Q})$ denote the subset of $C_{ns}$ consisting of the points with rational coordinates\n", 111 | "- We can use the same geometric interpretation \n", 112 | "- Then one canchecks that $C_{ns}$ is an abelian group, and if $\\mathcal{O}$ is in $C_{ns}(\\mathbb{Q})$,then $C_{ns}(\\mathbb{Q})$ is asubgroup of $C_{ns}$" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "There are 3 possible pictures for the singularity $S$ depending on whether $f$ has a double root or triple root, and if a double root, whether the tangent directions are real or complex" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "### Cusp\n" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "Let our curve be: $C'': y^2 = x^3$\n", 134 | "\n", 135 | "We take the map\n", 136 | "- $\\mathbb{Q} \\longrightarrow C(\\mathbb{Q})$\n", 137 | "- $r \\longmapsto (r^2 - 1, r^3 - 1)$\n", 138 | "\n", 139 | "And the inverse map\n", 140 | "- $C(\\mathbb{Q}) \\longrightarrow \\mathbb{Q}$\n", 141 | "- $(x,y) \\longmapsto y/x$\n", 142 | "\n", 143 | "We can use slightly different maps but we get group homomorphisms (not isomorphism)\n", 144 | "\n" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "### Node" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "Let our curve be: $C: y^2 = x^3 + x^2 = x^2(x+1)$\n", 159 | "\n", 160 | "Then the map\n", 161 | "- $\\phi: C_{ns}(\\mathbb{Q}) \\longrightarrow \\mathbb{Q}^*$\n", 162 | "- $\\phi(P) = \n", 163 | "\\begin{cases} \n", 164 | "&\\cfrac {y - x} {y + x} \\ \\text{if} \\ P = (x,y) \\\\\n", 165 | "&1 \\ \\text{if} \\ P = \\mathcal{O} \n", 166 | "\\end{cases}\n", 167 | "$\n", 168 | "\n", 169 | "is a group isomorphism from $C_{ns}(\\mathbb{Q})$ to $\\mathbb{Q}^*$ ( the multiplicative group of non-zero rational numbers)\n", 170 | "\n", 171 | "The inverse map\n", 172 | "- $ψ:\\mathbb{Q}^∗ \\longrightarrow C_{ns}(\\mathbb{Q})$\n", 173 | "- $ ψ(t)=\n", 174 | "\\begin{cases}\n", 175 | "&\\left( \\cfrac {4t} {(1−t)^2} , \\cfrac {4t(1 + t)} {(1−t)^3} \\right) \\ \\text{if} \\ t \\neq 1 \\\\\n", 176 | "& \\mathcal{O} \\ \\text{if} \\ t=1\n", 177 | "\\end{cases}\n", 178 | "$\n" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "**Observation**:\n", 186 | "- The Mordell–Weil theorem tells us that if $C$ is a non-singular cubic curve, then the group $C(\\mathbb{Q})$ is finitely generated. On the other hand, it is easy to see that the groups $(\\mathbb{Q}^∗,∗)$ and $(\\mathbb{Q},+)$ are not finitely generated.\n", 187 | "- So the singular curves don't generate finite groups => they behave differently" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "**More stuff**\n", 195 | "\n", 196 | "Let $ C$ be the cubic curve given by an equation $y^2=x^3+ax^2+bx+c$. Let $S = (x_0, y_0)$ be the singular point. With a change of coordinates $x=X+x_0$ and $y=Y$ =>\n", 197 | "a new form $Y^2=X^3+AX^2$\n", 198 | "\n", 199 | "Let our curve be: $C: y^2 = x^3 + Ax^2 = x^2(x+A)$\n", 200 | "\n", 201 | "Then the map\n", 202 | "- $\\phi: C_{ns}(\\mathbb{Q}) \\longrightarrow H(\\mathbb{Q}) \\longrightarrow $some subgroup of $K^*$ where $K^* = \\mathbb{Q}(\\sqrt A)$ <- $(u + v \\sqrt A, \\ (u,v) \\in H(\\mathbb{Q}))$ \n", 203 | "- $\\phi(P) = \n", 204 | "\\begin{cases} \n", 205 | "&\\cfrac {y - x \\sqrt A } {y + x \\sqrt A } \\ \\text{if} \\ P = (x,y) \\\\\n", 206 | "&1 \\ \\text{if} \\ P = \\mathcal{O} \n", 207 | "\\end{cases}\n", 208 | "$" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": {}, 215 | "outputs": [], 216 | "source": [] 217 | } 218 | ], 219 | "metadata": { 220 | "kernelspec": { 221 | "display_name": "SageMath 9.0", 222 | "language": "sage", 223 | "name": "sagemath" 224 | }, 225 | "language_info": { 226 | "codemirror_mode": { 227 | "name": "ipython", 228 | "version": 3 229 | }, 230 | "file_extension": ".py", 231 | "mimetype": "text/x-python", 232 | "name": "python", 233 | "nbconvert_exporter": "python", 234 | "pygments_lexer": "ipython3", 235 | "version": "3.7.3" 236 | } 237 | }, 238 | "nbformat": 4, 239 | "nbformat_minor": 2 240 | } 241 | -------------------------------------------------------------------------------- /P1-Public-key/RSA/Vulnerabilities/Hastad_Broadcast_Attack.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2020-08-29T07:49:34.398737Z", 9 | "start_time": "2020-08-29T07:49:34.292646Z" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "import numpy as np\n", 15 | "import math\n", 16 | "from Crypto.Util.number import getPrime, inverse, bytes_to_long, long_to_bytes, GCD\n", 17 | "import random" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": 17, 23 | "metadata": { 24 | "ExecuteTime": { 25 | "end_time": "2020-08-29T08:48:07.330289Z", 26 | "start_time": "2020-08-29T08:48:07.326287Z" 27 | } 28 | }, 29 | "outputs": [], 30 | "source": [ 31 | "def iroot(k, n):\n", 32 | " u, s = n, n+1\n", 33 | " while u < s:\n", 34 | " s = u\n", 35 | " t = (k-1) * s + n // pow(s, k-1)\n", 36 | " u = t // k\n", 37 | " return s" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 3, 43 | "metadata": { 44 | "ExecuteTime": { 45 | "end_time": "2020-08-29T07:49:34.573146Z", 46 | "start_time": "2020-08-29T07:49:34.568132Z" 47 | } 48 | }, 49 | "outputs": [], 50 | "source": [ 51 | "def encrypt_rsa(m, e, N):\n", 52 | " assert m < N\n", 53 | " c = pow(m, e, N)\n", 54 | " return c" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "# Prerequisites" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "1. RSA + its prerequisites\n", 69 | "2. Chinese remainder theorem\n", 70 | "* https://en.wikipedia.org/wiki/Chinese_remainder_theorem\n", 71 | "* https://www.youtube.com/watch?v=oKMYNKbFHBE&list=PLKXdxQAT3tCssgaWOy5vKXAR4WTPpRVYK&index=58" 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "# Theory" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "**Task**: \n", 86 | "\n", 87 | "Given k moduli: \n", 88 | "$c_1 = m^e \\bmod N_1 \\\\\n", 89 | "c_2 = m^e \\bmod N_2 \\\\\n", 90 | "... \\\\\n", 91 | "$ with $\\gcd(N_i,N_j) = 1 \\forall i \\neq j$\n", 92 | "\n", 93 | "find $m$" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "## CRT:" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": { 106 | "ExecuteTime": { 107 | "end_time": "2020-08-29T08:40:23.450208Z", 108 | "start_time": "2020-08-29T08:40:23.418161Z" 109 | } 110 | }, 111 | "source": [ 112 | "\n", 113 | "Let $m_{1}, m_{2}, \\ldots, m_{k}$ be a collection of pairwise relatively prime integers. This means that \n", 114 | "$\n", 115 | "\\operatorname{gcd}\\left(m_{i}, m_{j}\\right)=1 \\quad \\text { for all } i \\neq j\n", 116 | "$ \n", 117 | "\n", 118 | "Let $a_{1}, a_{2}, \\ldots, a_{k}$ be arbitrary integers. \n", 119 | "\n", 120 | "Then the system of simultaneous congruences \n", 121 | "$ \n", 122 | "x \\equiv a_{1}\\left(\\bmod m_{1}\\right), \\\\\n", 123 | "x \\equiv a_{2}\\left(\\bmod m_{2}\\right), \\\\\n", 124 | "\\ldots\\\\\n", 125 | "x \\equiv a_{k}\\left(\\bmod m_{k}\\right)\n", 126 | "$ \n", 127 | "has a solution $x=c .$ \n", 128 | "\n", 129 | "Further, if $x=c$ and $x=c^{\\prime}$ are both solutions, then\n", 130 | "$\n", 131 | "c \\equiv c^{\\prime} \\quad\\left(\\bmod m_{1} m_{2} \\cdots m_{k}\\right)\n", 132 | "$" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "Explanation: https://www.youtube.com/watch?v=aS57JCzJw_o" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "Condition to work: $k \\geq e$" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "Since $m < N_i \\forall i \\in {1..k} => m^e < \\Pi_{i=1}^k N_i$\n", 154 | "\n", 155 | "Solve CRT for $m^e$\n", 156 | "\n", 157 | "Extract the e-root and voila\n", 158 | "\n" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "## Hastad's findings:" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "If $c \\equiv m^e \\bmod \\ N$ then we can find $m$ in polynomial time if $m < N^{1/e}$" 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": {}, 178 | "source": [ 179 | "# Code" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "## Crt" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 15, 192 | "metadata": { 193 | "ExecuteTime": { 194 | "end_time": "2020-08-29T08:47:29.283117Z", 195 | "start_time": "2020-08-29T08:47:29.278115Z" 196 | } 197 | }, 198 | "outputs": [], 199 | "source": [ 200 | "def solve_simple_eq(a, b, c, p):\n", 201 | " \"\"\"\n", 202 | " Solves the equation a + bx = c mod p\n", 203 | " Returns c % p\n", 204 | " \"\"\"\n", 205 | " c = c - a\n", 206 | " c = (c * inverse(b, p)) % p\n", 207 | " return c % p\n", 208 | "\n", 209 | "\n", 210 | "def crt(a_list, m_list):\n", 211 | " \"\"\"\n", 212 | " Chinese remainder theorem for x = a % m for a, m in zip(a_list, m_list)\n", 213 | " \"\"\"\n", 214 | " x = 0\n", 215 | " # starting values\n", 216 | " a = 0\n", 217 | " m = 1\n", 218 | " for i in range(len(m_list)):\n", 219 | " # general solution for the first equations x = a + m * y\n", 220 | " # plug it in into the next equation and solve\n", 221 | " x = solve_simple_eq(a, m, a_list[i], m_list[i])\n", 222 | "\n", 223 | " a = a + m * x\n", 224 | " m = m * m_list[i]\n", 225 | " # print(a, m)\n", 226 | " return a, m" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 10, 232 | "metadata": { 233 | "ExecuteTime": { 234 | "end_time": "2020-08-29T08:46:38.113883Z", 235 | "start_time": "2020-08-29T08:46:35.814216Z" 236 | } 237 | }, 238 | "outputs": [], 239 | "source": [ 240 | "N_list = []\n", 241 | "c_list = []\n", 242 | "e = 3<=>\n", 243 | "m = bytes_to_long(b'verylongsecret' * 10)\n", 244 | "for _ in range(3):\n", 245 | " p = getPrime(1024)\n", 246 | " q = getPrime(1024)\n", 247 | " #assert GCD(e, (p-1)*(q-1)) == 1\n", 248 | " N = p * q\n", 249 | " c = pow(m, e, N)\n", 250 | " N_list.append(N)\n", 251 | " c_list.append(c)\n", 252 | " \n", 253 | " " 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 18, 259 | "metadata": { 260 | "ExecuteTime": { 261 | "end_time": "2020-08-29T08:48:12.763096Z", 262 | "start_time": "2020-08-29T08:48:12.758093Z" 263 | } 264 | }, 265 | "outputs": [], 266 | "source": [ 267 | "m_decr_e, _ = crt(c_list, N_list)" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 19, 273 | "metadata": { 274 | "ExecuteTime": { 275 | "end_time": "2020-08-29T08:48:32.786129Z", 276 | "start_time": "2020-08-29T08:48:32.750117Z" 277 | } 278 | }, 279 | "outputs": [ 280 | { 281 | "name": "stdout", 282 | "output_type": "stream", 283 | "text": [ 284 | "b'verylongsecretverylongsecretverylongsecretverylongsecretverylongsecretverylongsecretverylongsecretverylongsecretverylongsecretverylongsecret'\n" 285 | ] 286 | } 287 | ], 288 | "source": [ 289 | "m_decr = iroot(e, m_decr_e)\n", 290 | "print(long_to_bytes(m_decr))" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "# Resources" 298 | ] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "metadata": {}, 303 | "source": [ 304 | "* https://en.wikipedia.org/wiki/Coppersmith%27s_attack#H%C3%A5stad's_broadcast_attack\n", 305 | "- https://koclab.cs.ucsb.edu/teaching/cren/project/2017/chennagiri.pdf" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": {}, 312 | "outputs": [], 313 | "source": [] 314 | } 315 | ], 316 | "metadata": { 317 | "kernelspec": { 318 | "display_name": "Python 3 (ipykernel)", 319 | "language": "python", 320 | "name": "python3" 321 | }, 322 | "language_info": { 323 | "codemirror_mode": { 324 | "name": "ipython", 325 | "version": 3 326 | }, 327 | "file_extension": ".py", 328 | "mimetype": "text/x-python", 329 | "name": "python", 330 | "nbconvert_exporter": "python", 331 | "pygments_lexer": "ipython3", 332 | "version": "3.10.4" 333 | }, 334 | "toc": { 335 | "base_numbering": 1, 336 | "nav_menu": {}, 337 | "number_sections": true, 338 | "sideBar": true, 339 | "skip_h1_title": false, 340 | "title_cell": "Table of Contents", 341 | "title_sidebar": "Contents", 342 | "toc_cell": false, 343 | "toc_position": {}, 344 | "toc_section_display": true, 345 | "toc_window_display": false 346 | } 347 | }, 348 | "nbformat": 4, 349 | "nbformat_minor": 4 350 | } 351 | -------------------------------------------------------------------------------- /P1-Public-key/RSA/Vulnerabilities/Franklin-Reiter_related_message.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from Crypto.Util.number import long_to_bytes, bytes_to_long, getPrime, inverse, GCD\n", 10 | "import random" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Prerequisites" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "- Coppersmith\n", 25 | "- GCD\n", 26 | "- RSA" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "# Theory" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "**Task**\n", 41 | "- The attack exploits the fact that two messages might be related by some polynomial" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "**Theorem Franklin-Reiter** \n", 49 | "Set $e = 3$ and let $⟨ N , e ⟩$ be an RSA public key. Let $M_1 ≠ M_2 ∈ \\mathbb{Z}^*$ satisfy $ M_{1}\\equiv f(M_{2}) \\bmod {N}$ for some linear polynomial $f = a x + b ∈ \\mathbb{Z}_N[ x ]$ with $b ≠ 0$. Then, given $⟨ N , e , C_1 , C_2 , f ⟩$, an attacker Eve, can recover $M_1 , M_2$ in time quadratic in $\\log_2 (N)$." 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "**Proof**\n", 57 | "- $M_1 \\equiv a*M_2 + b \\bmod N$\n", 58 | "- $C_1 \\equiv M_1^e \\equiv (a*M_2 + b)^e \\bmod N <=> 0 \\equiv (a*M_2 + b)^e - C_1 \\bmod N $\n", 59 | "- $C_2 \\equiv (M_2)^e \\bmod N <=> 0 \\equiv M_2^e - C_2 \\bmod N $\n", 60 | "- If we want to solve for $M_2$ construct the polynomials\n", 61 | " - $g_1(x) = (a*x + b) ^e - C_1 \\in Z_N[x]$\n", 62 | " - $g_2(x) = x^e - C_2 \\in Z_N[x]$\n", 63 | "- $M_2$ is a root to both polynomial => $x - M_2$ divides both polynomials => we can compute the GCD to both polynomials and if it's linear we found $M_2$\n" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "# Code" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 2, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "# Construct rsa keys\n", 80 | "def get_keys():\n", 81 | " p = getPrime(1024)\n", 82 | " q = getPrime(1024)\n", 83 | " N = p * q\n", 84 | " e = 3\n", 85 | " assert GCD(N, e) == 1\n", 86 | " phi = (p-1)*(q-1)\n", 87 | " d = inverse(e, phi)\n", 88 | " return (N, e), (p, q, d)" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 3, 94 | "metadata": {}, 95 | "outputs": [], 96 | "source": [ 97 | "#get keys\n", 98 | "(N, e), (p, q, d) = get_keys()" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 4, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "#Construct polynomial\n", 108 | "R. = PolynomialRing(Zmod(N))\n", 109 | "a = random.randint(2, N-2)\n", 110 | "b = random.randint(2, N-1)\n", 111 | "f = a*x + b\n" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 5, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "def poly_gcd(f1, f2):\n", 121 | " while f2:\n", 122 | " f1, f2, = f2, f1 % f2\n", 123 | " return f1.monic()\n", 124 | "def franklin_reiter(f1, f2, c1, c2, e, N):\n", 125 | " #R = f1.parent()\n", 126 | " g1 = f1**e - c1\n", 127 | " g2 = f2**e - c2\n", 128 | " g = poly_gcd(g1, g2)\n", 129 | " print(g)\n", 130 | " return -g.coefficients()[0]" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": 6, 136 | "metadata": {}, 137 | "outputs": [], 138 | "source": [ 139 | "m2 = int(bytes_to_long(b'this_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_message')) \n", 140 | "m1 = int(f(m2)) #overwrite Integer class in sage" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 7, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "c2 = pow(m2, e, N)\n", 150 | "c1 = pow(m1, e, N)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 11, 156 | "metadata": {}, 157 | "outputs": [ 158 | { 159 | "name": "stdout", 160 | "output_type": "stream", 161 | "text": [ 162 | "x + 21203948306901267409690734889935566282659108778871678850540421071839030494727929669801476386512031853123849490159693445320002025068724545740890762962520393785396760795180105117560107985843716188291578481001836170553565564043720040842980538654474358765009340657862068466488908878538881547302021627565407737248266298492693382271432885042151752160052320890882999893108464403020979808735925803880704617073718450274977513402295476480271240345863198735818606252926319213543623487874482689527748200225173490003401561280539995256927759991161487361413669822488123898287181545677977749483333753357897709470657408575254391642272\n" 163 | ] 164 | } 165 | ], 166 | "source": [ 167 | "f2 = x\n", 168 | "m2_decr = franklin_reiter(f, f2, c1, c2, e, N)\n", 169 | "m2_decr = int(m2_decr)" 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 12, 175 | "metadata": {}, 176 | "outputs": [ 177 | { 178 | "data": { 179 | "text/plain": [ 180 | "b'this_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_message'" 181 | ] 182 | }, 183 | "execution_count": 12, 184 | "metadata": {}, 185 | "output_type": "execute_result" 186 | } 187 | ], 188 | "source": [ 189 | "long_to_bytes(m2_decr)" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 13, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "#Linear linked messages\n", 199 | "#get keys\n", 200 | "(N, e), (p, q, d) = get_keys()\n", 201 | "R. = PolynomialRing(Zmod(N))\n", 202 | "\n", 203 | "a1 = random.randint(2, N-2)\n", 204 | "b1 = random.randint(2, N-1)\n", 205 | "a2 = random.randint(2, N-1)\n", 206 | "b2 = random.randint(2, N-1)\n", 207 | "f1 = a1*x + b2\n", 208 | "f2 = a2*x + b2\n", 209 | "\n", 210 | "m = int(bytes_to_long(b'this_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_message')) \n", 211 | "\n", 212 | "c1 = pow(int(f1(m)), e, N)\n", 213 | "c2 = pow(int(f2(m)), e, N)" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": 16, 219 | "metadata": {}, 220 | "outputs": [ 221 | { 222 | "name": "stdout", 223 | "output_type": "stream", 224 | "text": [ 225 | "x + 21116652330039465980302856239322027310251817155196199544452626409535294311140590939570163149383212599236964200809202005450805701469083139918179697246401954978623125919181358309928632650358971722606970220709098735004380639383898484620714409219747511356848531606299565975288136622406184054996859805722375796322158883819836850185117473561772167249857813727725826314734562290614326294764396581720007564954121290554685681460688173243978421479656192683036631016875061198138953002811803252146943307178959751466404624589771902473529217866756401482175574666481501255378753985035478540357545646801008689185838486002482320873398\n" 226 | ] 227 | } 228 | ], 229 | "source": [ 230 | "m_decr = franklin_reiter(f1, f2, c1, c2, e, N)\n", 231 | "m_decr = int(m_decr)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 17, 237 | "metadata": {}, 238 | "outputs": [ 239 | { 240 | "data": { 241 | "text/plain": [ 242 | "b'this_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_messagethis_is_a_secret_message'" 243 | ] 244 | }, 245 | "execution_count": 17, 246 | "metadata": {}, 247 | "output_type": "execute_result" 248 | } 249 | ], 250 | "source": [ 251 | "long_to_bytes(m_decr)" 252 | ] 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "# Resources" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": {}, 264 | "source": [ 265 | "- https://en.wikipedia.org/wiki/Coppersmith%27s_attack\n", 266 | "- https://eprint.iacr.org/2009/205.pdf\n", 267 | "- https://www.researchgate.net/publication/221010549_A_new_related_message_attack_on_RSA/link/0deec534c1081b034d000000/download\n", 268 | "- https://crypto.stackexchange.com/questions/30884/help-understanding-basic-franklin-reiter-related-message-attack\n", 269 | "- https://translate.google.com/translate?hl=en&sl=zh-CN&u=https://ctf-wiki.github.io/ctf-wiki/crypto/asymmetric/rsa/rsa_coppersmith_attack-zh/&prev=search&pto=aue" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [] 278 | } 279 | ], 280 | "metadata": { 281 | "kernelspec": { 282 | "display_name": "SageMath 9.5", 283 | "language": "sage", 284 | "name": "sagemath" 285 | }, 286 | "language_info": { 287 | "codemirror_mode": { 288 | "name": "ipython", 289 | "version": 3 290 | }, 291 | "file_extension": ".py", 292 | "mimetype": "text/x-python", 293 | "name": "python", 294 | "nbconvert_exporter": "python", 295 | "pygments_lexer": "ipython3", 296 | "version": "3.10.4" 297 | } 298 | }, 299 | "nbformat": 4, 300 | "nbformat_minor": 4 301 | } 302 | -------------------------------------------------------------------------------- /P1-Public-key/RSA/Vulnerabilities/Known_e_d_pair.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 6, 6 | "metadata": { 7 | "ExecuteTime": { 8 | "end_time": "2020-08-29T06:58:37.358819Z", 9 | "start_time": "2020-08-29T06:58:35.069112Z" 10 | } 11 | }, 12 | "outputs": [], 13 | "source": [ 14 | "import math\n", 15 | "import random\n", 16 | "\n", 17 | "import numpy as np\n", 18 | "from Crypto.Util.number import GCD, bytes_to_long, getPrime, inverse, long_to_bytes" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 7, 24 | "metadata": { 25 | "ExecuteTime": { 26 | "end_time": "2020-08-29T06:58:37.364821Z", 27 | "start_time": "2020-08-29T06:58:37.360818Z" 28 | } 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "def isqrt(n: int):\n", 33 | " x = n\n", 34 | " y = (x + 1) // 2\n", 35 | " while y < x:\n", 36 | " x = y\n", 37 | " y = (x + n // x) // 2\n", 38 | " return x" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 8, 44 | "metadata": { 45 | "ExecuteTime": { 46 | "end_time": "2020-08-29T06:58:37.382834Z", 47 | "start_time": "2020-08-29T06:58:37.366822Z" 48 | } 49 | }, 50 | "outputs": [], 51 | "source": [ 52 | "def encrypt_rsa(m: int, e: int, N: int):\n", 53 | " assert m < N\n", 54 | " c = pow(m, e, N)\n", 55 | " return c" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "# Prerequisites" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": { 68 | "ExecuteTime": { 69 | "end_time": "2020-08-29T07:00:05.862204Z", 70 | "start_time": "2020-08-29T07:00:05.858200Z" 71 | } 72 | }, 73 | "source": [ 74 | "1. RSA + its prerequisites" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "# Theory" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "Let: \n", 89 | "$p, q$ = secret primes \n", 90 | "$N = pq $ = modulus \n", 91 | "$\\varphi(N) = (p-1)(q-1)$ " 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "**Task** \n", 99 | "For another known encryption exponent $x$, find $m$ using a known $(e,d)$ pair: \n", 100 | "$c = m^x \\bmod \\ N$ => **Find $m$**" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "What do you know?\n", 108 | "* $(e,d)$ = known pair \n", 109 | "* $c$ = the ciphertext\n", 110 | "* $N$ = the modulus\n", 111 | "* $x$ = the other encryption exponent" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "## Solution 1: Mathematical weakness" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "Observe: $ed \\equiv 1 \\bmod \\varphi(N) \\Rightarrow ed - 1 = k\\cdot \\varphi(N)$ \n", 126 | "\n", 127 | "Then\n", 128 | "$$\n", 129 | "y \\equiv x^{-1} \\bmod k\\varphi(N) \\ \\big | \\cdot x \\Rightarrow \\\\\n", 130 | "xy \\equiv 1 \\bmod \\ \\varphi(N) \\Rightarrow \\\\\n", 131 | "c^y \\equiv m^{xy} \\equiv m^1 \\equiv m \\bmod \\ N$$" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "## Solution 2: Factorize N from (e,d)" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "Algorithm + Explanation: https://crypto.stackexchange.com/questions/62482/algorithm-to-factorize-n-given-n-e-d/62487#62487" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "# Code" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": 3, 158 | "metadata": { 159 | "ExecuteTime": { 160 | "end_time": "2020-08-29T07:16:27.347189Z", 161 | "start_time": "2020-08-29T07:16:27.344187Z" 162 | } 163 | }, 164 | "outputs": [], 165 | "source": [ 166 | "def sol1(c, e, d, x, N):\n", 167 | " kphi = e * d - 1\n", 168 | " y = inverse(x, kphi)s can be factored given any no\n", 169 | " m = pow(c, y, N)\n", 170 | " return m" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 4, 176 | "metadata": { 177 | "ExecuteTime": { 178 | "end_time": "2020-08-29T07:20:09.731131Z", 179 | "start_time": "2020-08-29T07:20:09.724132Z" 180 | } 181 | }, 182 | "outputs": [], 183 | "source": [ 184 | "def factor_N(N, e, d):\n", 185 | " # for any a => a^{ed-1} mod N = 1; Let f = ed - 1\n", 186 | " f = e * d - 1\n", 187 | " t = f\n", 188 | " # write f = 2^s * t with t odd\n", 189 | " s = 0\n", 190 | " while not (t & 1):\n", 191 | " t = t >> 1\n", 192 | " s += 1\n", 193 | " assert t & 1 == True\n", 194 | " assert f % N == pow(2, s, N) * t % N\n", 195 | "\n", 196 | " i = s\n", 197 | " from Crypto.Util.number import sieve_base\n", 198 | "\n", 199 | " for a in sieve_base:\n", 200 | " # exclude the trivial case\n", 201 | " if GCD(a, N) != 1:\n", 202 | " gc = GCD(a, N)\n", 203 | " p = N / gc\n", 204 | " q = N / p\n", 205 | " return p, q\n", 206 | "\n", 207 | " b = pow(a, t, N)\n", 208 | " # make sure b !=1\n", 209 | " if b == 1:\n", 210 | " continue\n", 211 | " while i != 1:\n", 212 | " c = pow(b, 2, N)\n", 213 | " if c != 1:\n", 214 | " b = c\n", 215 | " i -= 1\n", 216 | " else:\n", 217 | " break\n", 218 | " if b == N - 1:\n", 219 | " continue\n", 220 | " p = GCD(b - 1, N)\n", 221 | " q = N // p\n", 222 | " # test p and q\n", 223 | " if p * q == N:\n", 224 | " break\n", 225 | "\n", 226 | " return p, q" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 9, 232 | "metadata": { 233 | "ExecuteTime": { 234 | "end_time": "2020-08-29T07:17:43.307609Z", 235 | "start_time": "2020-08-29T07:17:42.676160Z" 236 | } 237 | }, 238 | "outputs": [], 239 | "source": [ 240 | "p = getPrime(1024)\n", 241 | "q = getPrime(1024)\n", 242 | "N = p * q\n", 243 | "phi = (p - 1) * (q - 1)\n", 244 | "e = 65537\n", 245 | "d = inverse(e, phi)" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": 10, 251 | "metadata": { 252 | "ExecuteTime": { 253 | "end_time": "2020-08-29T07:18:28.450188Z", 254 | "start_time": "2020-08-29T07:18:28.438165Z" 255 | } 256 | }, 257 | "outputs": [], 258 | "source": [ 259 | "x = getPrime(200)" 260 | ] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "execution_count": 11, 265 | "metadata": { 266 | "ExecuteTime": { 267 | "end_time": "2020-08-29T07:19:07.498136Z", 268 | "start_time": "2020-08-29T07:19:07.493125Z" 269 | } 270 | }, 271 | "outputs": [], 272 | "source": [ 273 | "m = bytes_to_long(b\"secret\")\n", 274 | "c = encrypt_rsa(m, x, N)" 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 12, 280 | "metadata": { 281 | "ExecuteTime": { 282 | "end_time": "2020-08-29T07:19:25.914144Z", 283 | "start_time": "2020-08-29T07:19:25.876117Z" 284 | } 285 | }, 286 | "outputs": [ 287 | { 288 | "data": { 289 | "text/plain": [ 290 | "b'secret'" 291 | ] 292 | }, 293 | "execution_count": 12, 294 | "metadata": {}, 295 | "output_type": "execute_result" 296 | } 297 | ], 298 | "source": [ 299 | "m_decr = sol1(c, e, d, x, N)\n", 300 | "long_to_bytes(m_decr)" 301 | ] 302 | }, 303 | { 304 | "cell_type": "code", 305 | "execution_count": 13, 306 | "metadata": { 307 | "ExecuteTime": { 308 | "end_time": "2020-08-29T07:20:11.076150Z", 309 | "start_time": "2020-08-29T07:20:11.045143Z" 310 | } 311 | }, 312 | "outputs": [], 313 | "source": [ 314 | "pf, qf = factor_N(N, e, d)" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 14, 320 | "metadata": { 321 | "ExecuteTime": { 322 | "end_time": "2020-08-29T07:21:27.888104Z", 323 | "start_time": "2020-08-29T07:21:27.846075Z" 324 | } 325 | }, 326 | "outputs": [ 327 | { 328 | "name": "stdout", 329 | "output_type": "stream", 330 | "text": [ 331 | "True\n", 332 | "b'secret'\n" 333 | ] 334 | } 335 | ], 336 | "source": [ 337 | "print((pf, qf) == (p, q))\n", 338 | "d_decr = inverse(x, (pf - 1) * (qf - 1))\n", 339 | "m_decr = pow(c, d_decr, N)\n", 340 | "print(long_to_bytes(m_decr))" 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": null, 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [] 349 | } 350 | ], 351 | "metadata": { 352 | "kernelspec": { 353 | "display_name": "Python 3 (ipykernel)", 354 | "language": "python", 355 | "name": "python3" 356 | }, 357 | "language_info": { 358 | "codemirror_mode": { 359 | "name": "ipython", 360 | "version": 3 361 | }, 362 | "file_extension": ".py", 363 | "mimetype": "text/x-python", 364 | "name": "python", 365 | "nbconvert_exporter": "python", 366 | "pygments_lexer": "ipython3", 367 | "version": "3.10.4" 368 | }, 369 | "toc": { 370 | "base_numbering": 1, 371 | "nav_menu": {}, 372 | "number_sections": true, 373 | "sideBar": true, 374 | "skip_h1_title": false, 375 | "title_cell": "Table of Contents", 376 | "title_sidebar": "Contents", 377 | "toc_cell": false, 378 | "toc_position": {}, 379 | "toc_section_display": true, 380 | "toc_window_display": false 381 | } 382 | }, 383 | "nbformat": 4, 384 | "nbformat_minor": 4 385 | } 386 | -------------------------------------------------------------------------------- /E1-Mathematics/Primes-and-Primality-tests/Untitled.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from Crypto.Util.number import sieve_base, GCD, isPrime, long_to_bytes, bytes_to_long, inverse, getPrime\n", 10 | "import random" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 2, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "def miller_rabin_test_fixed(n, a_list):\n", 20 | " '''returns Composite or Probably prime'''\n", 21 | " \n", 22 | " #check parity\n", 23 | " if not n & int(1):\n", 24 | " return 'Composite'\n", 25 | " \n", 26 | " r = 0\n", 27 | " s = n-1\n", 28 | " #write n-1 = 2^r*s\n", 29 | " while not s & int(1):\n", 30 | " s = s>>1\n", 31 | " r+=1\n", 32 | " assert(pow(2, r)* s == n-1)\n", 33 | " \n", 34 | " for a in a_list:\n", 35 | " x = pow(a, s, n)\n", 36 | " if x == 1 or x == n-1:\n", 37 | " continue #search for another witness\n", 38 | " for _ in range(r):\n", 39 | " x = pow(x, 2, n)\n", 40 | " if x == n-1:\n", 41 | " break \n", 42 | " else:\n", 43 | " #if it doesnt break, neither condition is satisfied => this executes => we found a composite\n", 44 | " return \"Composite\"\n", 45 | " return \"Probably prime\"\n", 46 | " " 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "## Fixed bases -> Bleichenbacher" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "https://www.semanticscholar.org/paper/Breaking-a-Cryptographic-Protocol-with-Pseudoprimes-Bleichenbacher/e9f1f083adc1786466d344db5b3d85f4c268b429?p2df" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "**(Korselt's Criterion)**: A composite integer $n$ is a Carmichael number if and only if the following two conditions are satisfied:\n", 68 | "- $n$ is square-free, i.e., $n$ is not divisible by the square of any prime; \n", 69 | "- $p−1$ divides $n−1$ for every prime divisor $p$ of $n$" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Erdos's idea to construct pseudoprimes\n", 77 | "- Choose $M \\in \\mathbb{Z}$ that has many divisors\n", 78 | "- Let $R$ be the set of primes $r$ such that $r−1$ is a divisor of $M$. \n", 79 | "- If a subset $T⊂R$ can be found such that\n", 80 | "$$ C = \\underset {r\\in T}{\\prod} r \\equiv 1 \\bmod M \\ \\ \\ (1)$$\n", 81 | "Then C is a Carmichael number because C satisfies the Korselt's criterion \n", 82 | "\n", 83 | "**Note**: One can hope to find such sets $$ if $R$ contains more than about $\\log_2(M)$ primes\n", 84 | "\n", 85 | "\n", 86 | "Additionally, a Carmichael number $C$ is a strong pseudoprime for a base $a$ if the order of $a$ modulo $r$ is divisible by the same power of 2 for all primes factors $r$ of $C$. \n", 87 | "If all prime factors $r$ are congruent 3 modulo 4 then this condition is satisfied when $a$ is a quadratic residue modulo either all prime factors $r$ or none at all, because in that case the order of $a$ modulor is either even or odd for all $r$" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "**Algorithm**\n", 95 | "- Choose $M \\in \\mathbb{Z}$\n", 96 | "- Find a set $R$ of primes s.t $\\forall $a$ \\in $A$ \\ \\exists c_i \\in \\{-1,1\\} \\text{ with } \\left(\\dfrac {a_i} r\\right) = c_i \\ \\forall r \\in R$\n", 97 | "- Find a subset $T \\subset R$ that can satisfy equation (1)" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": 3, 103 | "metadata": {}, 104 | "outputs": [], 105 | "source": [ 106 | "def generate_M(a_list, prime_idx_bound, random_bound):\n", 107 | " M = 1\n", 108 | " for a in a_list:\n", 109 | " M *= pow(a, random.randint(1, 3))\n", 110 | " p = a_list[-1]\n", 111 | " for i in range(random_bound):\n", 112 | " p = next_prime(p)\n", 113 | " t = random.choice([0, 1])\n", 114 | " if t == 0:\n", 115 | " i-=1\n", 116 | " continue\n", 117 | " \n", 118 | " M*= p\n", 119 | " \n", 120 | " return M" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 4, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "def find_set_R(a_list, M, r_low, r_high):\n", 130 | " r_list = []\n", 131 | " for r in divisors(M):\n", 132 | " r+=1\n", 133 | " if r < r_low:\n", 134 | " continue\n", 135 | " if r > r_high:\n", 136 | " break\n", 137 | " if isPrime(r):\n", 138 | " for a in a_list:\n", 139 | " if legendre_symbol(a, r) not in [-1, 1]:\n", 140 | " break\n", 141 | " else: #if it (bi / r) is -1 or 1 for all bases \n", 142 | " r_list.append(r)\n", 143 | " return r_list" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": 33, 149 | "metadata": {}, 150 | "outputs": [], 151 | "source": [ 152 | "def find_subsets_T(R, M):\n", 153 | " #we use a meet in the middle approach\n", 154 | " R1 = R[:len(R)//4]\n", 155 | " R2 = R[len(R)//4:]\n", 156 | " \n", 157 | " #precompute table for the first subset\n", 158 | " print(\"computing table - searching through %s subsets\" % len(Subsets(R1)))\n", 159 | " #table = {}\n", 160 | " table = []\n", 161 | " table2 = []\n", 162 | " for T1 in Subsets(R1):\n", 163 | " if len(T1) > 1:\n", 164 | " #print(T1)\n", 165 | " #products are unique since they are made from primes\n", 166 | " #table[inverse_mod(product(T1), M)] = T1\n", 167 | " t = product(T1)\n", 168 | " table.append(inverse_mod(t, M))\n", 169 | " table2.append(t)\n", 170 | " \n", 171 | " print(\"table computed, length %s\" % len(table))\n", 172 | " print(\"Starting search through the table\")\n", 173 | " for T2 in Subsets(R2):\n", 174 | " if len(T2) > 1:\n", 175 | " t = product(T2) % M\n", 176 | "# T1 = table.get(pr, 0)\n", 177 | "# if T1 != 0:\n", 178 | "# T = list(set(T1 + T2))\n", 179 | "# C = product(T)\n", 180 | "# return C\n", 181 | " if t in table:\n", 182 | " idx = table.index(t)\n", 183 | " C = table2[idx] * t\n", 184 | " return C\n", 185 | " return -1\n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " " 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": 20, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "a_list = [2,3,5]\n", 199 | "a_list = [int(a) for a in a_list]" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": 44, 205 | "metadata": {}, 206 | "outputs": [ 207 | { 208 | "data": { 209 | "text/plain": [ 210 | "346500" 211 | ] 212 | }, 213 | "execution_count": 44, 214 | "metadata": {}, 215 | "output_type": "execute_result" 216 | } 217 | ], 218 | "source": [ 219 | "M = generate_M(a_list, 20, 2)\n", 220 | "M" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": 45, 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [ 229 | "#M = 2*5^3*7^2*11^2*13*17*19*23*29*31*37*41*61" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": 46, 235 | "metadata": {}, 236 | "outputs": [ 237 | { 238 | "data": { 239 | "text/plain": [ 240 | "2^2 * 3^2 * 5^3 * 7 * 11" 241 | ] 242 | }, 243 | "execution_count": 46, 244 | "metadata": {}, 245 | "output_type": "execute_result" 246 | } 247 | ], 248 | "source": [ 249 | "factor(M)" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": 47, 255 | "metadata": {}, 256 | "outputs": [], 257 | "source": [ 258 | "r_list = find_set_R(a_list, M, 256, 2^60)" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": 48, 264 | "metadata": {}, 265 | "outputs": [ 266 | { 267 | "name": "stdout", 268 | "output_type": "stream", 269 | "text": [ 270 | "computing table - searching through 64 subsets\n", 271 | "table computed, length 57\n", 272 | "Starting search through the table\n" 273 | ] 274 | } 275 | ], 276 | "source": [ 277 | "C= find_subsets_T(r_list, M)" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 49, 283 | "metadata": {}, 284 | "outputs": [ 285 | { 286 | "data": { 287 | "text/plain": [ 288 | "331 * 397 * 421 * 463 * 631 * 661 * 14851" 289 | ] 290 | }, 291 | "execution_count": 49, 292 | "metadata": {}, 293 | "output_type": "execute_result" 294 | } 295 | ], 296 | "source": [ 297 | "factor(C)" 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": 50, 303 | "metadata": {}, 304 | "outputs": [ 305 | { 306 | "data": { 307 | "text/plain": [ 308 | "'Composite'" 309 | ] 310 | }, 311 | "execution_count": 50, 312 | "metadata": {}, 313 | "output_type": "execute_result" 314 | } 315 | ], 316 | "source": [ 317 | "miller_rabin_test_fixed(C, a_list)" 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "execution_count": 52, 323 | "metadata": {}, 324 | "outputs": [], 325 | "source": [ 326 | "from sage.crypto.util import carmichael_lambda" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 53, 332 | "metadata": {}, 333 | "outputs": [ 334 | { 335 | "data": { 336 | "text/plain": [ 337 | "207900" 338 | ] 339 | }, 340 | "execution_count": 53, 341 | "metadata": {}, 342 | "output_type": "execute_result" 343 | } 344 | ], 345 | "source": [ 346 | "carmichael_lambda(C)" 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": null, 352 | "metadata": {}, 353 | "outputs": [], 354 | "source": [] 355 | } 356 | ], 357 | "metadata": { 358 | "kernelspec": { 359 | "display_name": "SageMath 9.3", 360 | "language": "sage", 361 | "name": "sagemath" 362 | }, 363 | "language_info": { 364 | "codemirror_mode": { 365 | "name": "ipython", 366 | "version": 3 367 | }, 368 | "file_extension": ".py", 369 | "mimetype": "text/x-python", 370 | "name": "python", 371 | "nbconvert_exporter": "python", 372 | "pygments_lexer": "ipython3", 373 | "version": "3.7.10" 374 | } 375 | }, 376 | "nbformat": 4, 377 | "nbformat_minor": 4 378 | } 379 | -------------------------------------------------------------------------------- /E1-Mathematics/Elliptic-curves/ECDLP/MOV_attack_sage.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Prerequisites" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "- ECDLP\n", 15 | "- Elliptic curves\n", 16 | "- Pairings" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Theory" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "**Task**: Reduce the ECDLP to an easier problem (Ex: an easier group)\n", 31 | "\n", 32 | "*Idea*: Use the Weil/Tate pairing to convert a discrete log problem in $E(\\mathbb{F}_p)$ to one in $\\mathbb{F}^\\times_{p^k}$\n", 33 | "\n", 34 | "Since discrete log problems in finite fields can be attacked by index calculus (or other) methods, they can be solved faster than elliptic curve discrete log problems, as long as the field $\\mathbb{F}_{p^k}$ is not much larger than $\\mathbb{F}_p$" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "Recall that for an elliptic curve $E$ defined over $\\mathbb{F}_p$ \n", 42 | "- we let $E[m]$ denote the set of points of order dividing $m$ with coordinates in the algebraic closure. \n", 43 | "- If $\\gcd(p, m)=1$ and $S, T\\in E[m]$, then the Weil pairing $e_m(S, T)$ is an $m$th root of unity and can be computed fairly quickly. \n", 44 | "- The pairing is bilinear, and if $\\{S, T\\}$ is a basis for $E[m]$, then $e_m(S, T)$ is a primitive $m$th root of unity.\n", 45 | "- For any $S => e_m(S, S) = 1$.\n", 46 | "\n", 47 | "There exists $n$ such that $Q=nP \\iff mQ=\\mathcal{O}$ and the Weil paring $e_m(P, Q)=1$." 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "- Let $E$ be an elliptic curve over $\\mathbb{F}_p$. \n", 55 | "- Let $P, Q\\in E(\\mathbb{F}_p)$. \n", 56 | "- Let $m$ be the order of $P$. \n", 57 | "- Assume that $\\gcd(m, p)=1$\n", 58 | "\n", 59 | "We want to find $n$ such that $Q=nP$\n", 60 | "\n", 61 | "**Lemma**: $\\exists \\ n \\ $ such that $ Q = nP \\iff mQ = \\mathcal{O} $ and $e_m(P,Q) = 1$" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "## The MOV attack\n", 69 | "\n", 70 | "- https://crypto.stanford.edu/pbc/notes/elliptic/movattack.html\n", 71 | "- https://crypto.stackexchange.com/questions/1871/how-does-the-mov-attack-work" 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "Choose embedding degree $k$ such that $E[m] \\subset E(\\mathbb{F}_{p^k})$\n", 79 | "\n", 80 | "1. Compute the number of points $N = |E(\\mathbb{F}_{p^k})|$\n", 81 | "2. Choose a random point $T \\in E(\\mathbb{F}_{p^k}), \\ T \\not \\in E(\\mathbb{F}_p)$\n", 82 | "3. Compute the order $t$ of $T$\n", 83 | "4. let $d = \\gcd(t, m)$, let $T' = (\\frac t d)T => T'$ has order $d$ which divides $m => T \\in E[m]$\n", 84 | " - We can use $N//m$ instead of $d$ but takes more computation\n", 85 | "5. Compute \n", 86 | " - $\\alpha = e_m(P, T')$ \n", 87 | " - $\\beta = e_m(Q, T')$\n", 88 | "6. Solve $\\alpha = \\beta^n$ in $\\mathbb{F}_{p^k}$ => $n$ mod $d$\n", 89 | "7. If there are more $n$'s, crt the results" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "# Code" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 1, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "p = 1331169830894825846283645180581\n", 106 | "a = -35\n", 107 | "b = 98\n", 108 | "E = EllipticCurve(GF(p), [a,b])\n", 109 | "G = E(479691812266187139164535778017, 568535594075310466177352868412)\n", 110 | "A = E(1110072782478160369250829345256, 800079550745409318906383650948)" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 2, 116 | "metadata": {}, 117 | "outputs": [], 118 | "source": [ 119 | "log_p = log(p, 2).n(digits = 10) #a range to search\n", 120 | "G_order = G.order()\n", 121 | "k = 1\n", 122 | "for i in range(1, int(log_p)):\n", 123 | " if pow(p, i, G_order) == 1:\n", 124 | " k = i\n", 125 | " break\n", 126 | " " 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 3, 132 | "metadata": {}, 133 | "outputs": [ 134 | { 135 | "data": { 136 | "text/plain": [ 137 | "2" 138 | ] 139 | }, 140 | "execution_count": 3, 141 | "metadata": {}, 142 | "output_type": "execute_result" 143 | } 144 | ], 145 | "source": [ 146 | "k" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 7, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "def MOV(E, P, Q, k, p):\n", 156 | " \"\"\"\n", 157 | " Parameters:\n", 158 | " -----------\n", 159 | " \n", 160 | " E: EllipticCurve\n", 161 | " The elliptic curve \n", 162 | " P: Point\n", 163 | " a point of order l\n", 164 | " Q: Point\n", 165 | " Point such that Q = nP\n", 166 | " k: int\n", 167 | " embedding degree\n", 168 | " p: int\n", 169 | " prime order\n", 170 | " \n", 171 | " Returns: \n", 172 | " --------\n", 173 | " int: \n", 174 | " n such that Q = nP\n", 175 | " \n", 176 | " \"\"\"\n", 177 | " #Step 1 compute the number of points in E(F_{p^k}) => N\n", 178 | " \n", 179 | " \n", 180 | " E_k = E.base_extend(GF(p^k))\n", 181 | " N = E_k.order()\n", 182 | " m = P.order()\n", 183 | " PK = E_k(P)\n", 184 | " QK = E_k(Q)\n", 185 | " \n", 186 | " while True:\n", 187 | " #Step 2 Select a random point T which is on E_k but not on E\n", 188 | " T = E_k.random_point() \n", 189 | " try:\n", 190 | " E(*T.xy())\n", 191 | " continue\n", 192 | " except:\n", 193 | " pass\n", 194 | " \n", 195 | " #Step 3 Compute T_prime = (T_order / gcd(T_order, m)) * T; if T = 0 select another T. Otherwise T_prime has order m\n", 196 | " t = T.order()\n", 197 | " d = gcd(m, t)\n", 198 | " T_prime = (t//d) * T #=> point of order m\n", 199 | " #print(N//m, t//d)\n", 200 | " if T_prime.is_zero():\n", 201 | " continue\n", 202 | " \n", 203 | " #Step 4 Compute the Weil pairing values. P, Q, and T_prime all have order m\n", 204 | " alpha = PK.weil_pairing(T_prime, m)\n", 205 | " if alpha == 1:\n", 206 | " continue\n", 207 | " beta = QK.weil_pairing(T_prime, m)\n", 208 | " \n", 209 | " #Step 5 Solve dlp for beta = alpha ^ n in F*_{p^k}\n", 210 | " n = beta.log(alpha)\n", 211 | " break\n", 212 | " return n" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": 5, 218 | "metadata": {}, 219 | "outputs": [], 220 | "source": [ 221 | "n = MOV(E, G, A, k, p)" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 6, 227 | "metadata": {}, 228 | "outputs": [ 229 | { 230 | "data": { 231 | "text/plain": [ 232 | "True" 233 | ] 234 | }, 235 | "execution_count": 6, 236 | "metadata": {}, 237 | "output_type": "execute_result" 238 | } 239 | ], 240 | "source": [ 241 | "n*G == A" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 8, 247 | "metadata": {}, 248 | "outputs": [], 249 | "source": [ 250 | "def MOV2(E, P, Q, k, p):\n", 251 | " \"\"\"\n", 252 | " Parameters:\n", 253 | " -----------\n", 254 | " \n", 255 | " E: EllipticCurve\n", 256 | " The elliptic curve \n", 257 | " P: Point\n", 258 | " a point of order l\n", 259 | " Q: Point\n", 260 | " Point such that Q = nP\n", 261 | " k: int\n", 262 | " embedding degree\n", 263 | " p: int\n", 264 | " prime order\n", 265 | " \n", 266 | " Returns: \n", 267 | " --------\n", 268 | " int: \n", 269 | " n such that Q = nP\n", 270 | " \n", 271 | " \"\"\"\n", 272 | " #Step 1 compute the number of points in E(F_{p^k}) => N\n", 273 | " \n", 274 | " m = P.order()\n", 275 | " E_k = E.base_extend(GF(p**k))\n", 276 | " QK = E_k(Q)\n", 277 | " PK = E_k(P)\n", 278 | " \n", 279 | " n_list = []\n", 280 | " d_list = []\n", 281 | " least_common_multiple = 1\n", 282 | " \n", 283 | " while least_common_multiple !=m:\n", 284 | " T = E_k.random_point()\n", 285 | " t = T.order()\n", 286 | " d = gcd(t, m)\n", 287 | " if d in d_list:\n", 288 | " continue\n", 289 | " T_prime = t//d * T #T_prime has order d | m => T_prime is in E[m]\n", 290 | " \n", 291 | " alpha = PK.weil_pairing(T_prime, m)\n", 292 | " beta = QK.weil_pairing(T_prime, m) # => both are roots in \\mu_d in F_{p^k}\n", 293 | " \n", 294 | " n = beta.log(alpha) #this gives n mod d\n", 295 | " n_list.append(n)\n", 296 | " d_list.append(d)\n", 297 | " least_common_multiple = lcm(least_common_multiple, d)\n", 298 | " print(n_list)\n", 299 | " return n_list[-1]\n", 300 | " #return n_list[0] if len(n_list) == 1 else crt(n_list, d_list)\n", 301 | " " 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": 9, 307 | "metadata": {}, 308 | "outputs": [ 309 | { 310 | "name": "stdout", 311 | "output_type": "stream", 312 | "text": [ 313 | "[29618469991922269]\n" 314 | ] 315 | } 316 | ], 317 | "source": [ 318 | "n_fin = MOV2(E, G, A, k, p)" 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": 11, 324 | "metadata": {}, 325 | "outputs": [ 326 | { 327 | "data": { 328 | "text/plain": [ 329 | "True" 330 | ] 331 | }, 332 | "execution_count": 11, 333 | "metadata": {}, 334 | "output_type": "execute_result" 335 | }, 336 | { 337 | "name": "stdout", 338 | "output_type": "stream", 339 | "text": [ 340 | "Exiting Sage (CPU time 4m40.27s, Wall time 9m40.99s)." 341 | ] 342 | } 343 | ], 344 | "source": [ 345 | "n_fin * G==A" 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": null, 351 | "metadata": {}, 352 | "outputs": [], 353 | "source": [ 354 | "# Problem curve - Why?" 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": 253, 360 | "metadata": {}, 361 | "outputs": [], 362 | "source": [ 363 | "curve = EllipticCurve(GF(22216045306240170001), [15703735179364572855, 10469156786243048570])\n", 364 | "gen = curve.gen(1)\n", 365 | "n = int(gen.order())\n", 366 | "l = randint(1, n - 1)" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "metadata": {}, 372 | "source": [ 373 | "# Resources" 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": null, 379 | "metadata": {}, 380 | "outputs": [], 381 | "source": [] 382 | } 383 | ], 384 | "metadata": { 385 | "kernelspec": { 386 | "display_name": "SageMath 9.5", 387 | "language": "sage", 388 | "name": "sagemath" 389 | }, 390 | "language_info": { 391 | "codemirror_mode": { 392 | "name": "ipython", 393 | "version": 3 394 | }, 395 | "file_extension": ".py", 396 | "mimetype": "text/x-python", 397 | "name": "python", 398 | "nbconvert_exporter": "python", 399 | "pygments_lexer": "ipython3", 400 | "version": "3.10.4" 401 | } 402 | }, 403 | "nbformat": 4, 404 | "nbformat_minor": 4 405 | } 406 | -------------------------------------------------------------------------------- /E3-Homomorphic-Encryption/pre_fhe.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "37cc73c5-aa60-4646-886a-6eeb11cda5fa", 6 | "metadata": {}, 7 | "source": [ 8 | "## Prerequisites\n", 9 | "- Homomorphic encryption pdf\n", 10 | "- Modular addition" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "d8b7082a-7eb8-4762-8dc1-2f1e4539c35c", 16 | "metadata": {}, 17 | "source": [ 18 | "# Background\n", 19 | "\n", 20 | "Before Gentry's thesis in 2009 there were a few **partially homomorphic** encryption systems\n", 21 | "\n", 22 | "A FHE scheme lets you use functions that can be combinations of as many additions and multiplications as you want.\n", 23 | "\n", 24 | "Partially HE schemes only let you use addition or multiplication." 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "id": "345c52c2-34da-49fa-989a-b1d5750490fc", 30 | "metadata": {}, 31 | "source": [ 32 | "# Unpadded RSA \n", 33 | "\n", 34 | "- Check RSA notebook for background\n", 35 | "\n", 36 | "Unpadded RSA is multiplicatively homomorphic. \n", 37 | "Let $(n, e)$ be the public key (modulus and encryption exponent) and $E(m) = m^e$ be the encryption function.\n", 38 | "\n", 39 | "$$E(m_1) \\cdot E(m_2) = m_1^e m_2^e = (m_1m_2)^e = E(m_1m_2)$$" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 4, 45 | "id": "7f4549e4-00a1-4b0e-b7fb-f4ae23a2e92b", 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "from Crypto.Util.number import GCD as gcd\n", 50 | "from Crypto.Util.number import getPrime, getRandomInteger, inverse" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 8, 56 | "id": "fe9cb1c7-76de-4764-bb2b-0fb539aae56d", 57 | "metadata": { 58 | "ExecuteTime": { 59 | "end_time": "2020-08-28T13:49:26.381553Z", 60 | "start_time": "2020-08-28T13:49:26.377535Z" 61 | } 62 | }, 63 | "outputs": [], 64 | "source": [ 65 | "def create_key_rsa(nbits: int, e=None):\n", 66 | " p = getPrime(nbits // 2)\n", 67 | " q = getPrime(nbits // 2)\n", 68 | "\n", 69 | " if e is None:\n", 70 | " e = 65567\n", 71 | "\n", 72 | " assert gcd(e, (p - 1) * (q - 1)) == 1\n", 73 | " N = p * q\n", 74 | " return (N, e), (p, q)\n", 75 | "\n", 76 | "\n", 77 | "def encrypt_rsa(m, e, N):\n", 78 | " assert m < N\n", 79 | " c = pow(m, e, N)\n", 80 | " return c\n", 81 | "\n", 82 | "\n", 83 | "def decrypt_rsa(c, p, q, e, N):\n", 84 | " # d = inverse(e, (p - 1) * (q - 1))\n", 85 | " d = pow(e, -1, (p - 1) * (q - 1))\n", 86 | " assert (d * e) % ((p - 1) * (q - 1)) == 1\n", 87 | " m = pow(c, d, N)\n", 88 | " return m" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 9, 94 | "id": "803b1860-15f7-4784-8e1f-8f5f5893c428", 95 | "metadata": {}, 96 | "outputs": [], 97 | "source": [ 98 | "(N, e), (p, q) = create_key_rsa(2048)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 11, 104 | "id": "2b01eb3e-2d57-4c36-a9b2-b996ed099e26", 105 | "metadata": { 106 | "ExecuteTime": { 107 | "end_time": "2020-08-28T13:49:27.229964Z", 108 | "start_time": "2020-08-28T13:49:27.225961Z" 109 | } 110 | }, 111 | "outputs": [ 112 | { 113 | "data": { 114 | "text/plain": [ 115 | "True" 116 | ] 117 | }, 118 | "execution_count": 11, 119 | "metadata": {}, 120 | "output_type": "execute_result" 121 | } 122 | ], 123 | "source": [ 124 | "m1 = 1000\n", 125 | "m2 = 2000\n", 126 | "c1 = encrypt_rsa(m1, e, N)\n", 127 | "c2 = encrypt_rsa(m2, e, N)\n", 128 | "\n", 129 | "decrypt_rsa(c1 * c2, p, q, e, N) == m1 * m2" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 13, 135 | "id": "18aed826-efa3-4d91-aabe-4b8d92f66897", 136 | "metadata": {}, 137 | "outputs": [ 138 | { 139 | "data": { 140 | "text/plain": [ 141 | "False" 142 | ] 143 | }, 144 | "execution_count": 13, 145 | "metadata": {}, 146 | "output_type": "execute_result" 147 | } 148 | ], 149 | "source": [ 150 | "# Not aditively\n", 151 | "decrypt_rsa(c1 + c2, p, q, e, N) == m1 + m2" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "id": "665faf03-eb2f-4d35-8015-10516fecaf67", 157 | "metadata": {}, 158 | "source": [ 159 | "# Paillier " 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "id": "f70fb7e1-3855-4590-afd6-0733e1147a64", 165 | "metadata": {}, 166 | "source": [ 167 | "**Key generation**\n", 168 | "1. Choose large primes $p, q$ such that $\\gcd(p\\cdot q, (p-1)(q-1)) = 1$\n", 169 | "2. Let \n", 170 | " - $n = pq$\n", 171 | " - $\\lambda = \\text{lcm}(p-1, q-1)$\n", 172 | " \n", 173 | "2. Select random $g \\in \\mathbb{Z}_{n^2}^* = \\{1, 2, ... ,n^2 - 1\\}$ \n", 174 | "3. ensure $n$ divides $|g|$ by checking if the modular multiplicative inverse $\\mu = (L(g^\\lambda \\bmod n^2))^{-1} \\bmod n$ exists, where $L(x) = \\dfrac {x-1} n$ (division represents the quotient)\n", 175 | "- *Public (encryption) key:* $(n,g)$\n", 176 | "- *Private(decryption) key:* $(\\lambda,\\mu)$\n", 177 | "\n", 178 | "**Encryption**\n", 179 | "- Let $m \\in \\mathbb{Z}_n$ be a message\n", 180 | "- Let $r \\in \\mathbb{Z}_n^*$ be a random number with $\\gcd(r, n) = 1$\n", 181 | "- Return $c = g^m \\cdot r^n \\bmod n^2$\n", 182 | "\n", 183 | "**Decryption**\n", 184 | "- $m = L(c^\\lambda \\bmod n^2) \\cdot \\mu \\bmod n$" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "id": "7c5213ab-fa35-4df0-a121-aebc8ec195c5", 190 | "metadata": {}, 191 | "source": [ 192 | "**Security** \n", 193 | "Semantic security is based on the [decitional composite residuosity assumption](https://en.wikipedia.org/wiki/Decisional_composite_residuosity_assumption). Given a composite $n$ and an integer $z$ it is hard to decide whether $z$ is an $n$ residue modulo $n^2$. I.e find $y$ s.t.\n", 194 | "$$z \\equiv y^n \\bmod n^2$$" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "id": "59e5b1da-b656-4b8b-8a11-eafb24653bb2", 200 | "metadata": {}, 201 | "source": [ 202 | "## Homomorphic properties" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "id": "68e5d673-e4ef-458c-910f-72e478244223", 208 | "metadata": {}, 209 | "source": [ 210 | "odq)\n", 211 | "Learning With Error & Ring Learniodq)\n", 212 | "Learning With Error & Ring LearniLet there be 2 encrypted messages\n", 213 | "- $c_1 = E(m_1,pk) = g^{m_1} \\cdot r^{n}_1 \\bmod n^2$\n", 214 | "- $c_2 = E(m_2,pk) = g^{m_2} \\cdot r^{n}_2 \\bmod n^2$" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "id": "dfdf1921-9680-415d-8426-ce3c3550f855", 220 | "metadata": {}, 221 | "source": [ 222 | "### Addition\n", 223 | "The *product* of the ciphertext decrypts to the *sum* of the plaintexts\n", 224 | "$$D(c_1 \\cdot c_2 \\bmod n^2) = m_1 + m_2 \\bmod n$$\n", 225 | "\n", 226 | "**Proof**\n", 227 | "\n", 228 | "$$\n", 229 | "\\begin{align*}\n", 230 | "c_1 \\cdot c_2 &= (g^{m_1} \\cdot r_1^n)(g^{m_2} \\cdot r^n_2) \\bmod n^2 \\\\\n", 231 | "&= g^{m_1 + m_2} (r_1r_2)^n \\bmod n^2 \\\\\n", 232 | "&= E(m_1 + m_2, pk) \n", 233 | "\\end{align*}\n", 234 | "$$" 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "id": "a228fef9-643c-4047-b4de-8c5baf068288", 240 | "metadata": {}, 241 | "source": [ 242 | "### Multiplication\n", 243 | "\n", 244 | "An encrypted plaintext raised to the power of another plaintext will decrypt to the product of the two plaintexts,\n", 245 | "$$D(c_1^{m_2} \\bmod n^2) = m_1\\ m_2 \\bmod n \\\\ D(c_2^{m_1} \\bmod n^2) = m_1\\ m_2 \\bmod n$$\n", 246 | "\n", 247 | "**Proof**\n", 248 | "\n", 249 | "$\\begin{equation}\n", 250 | "\\begin{split}\n", 251 | "c_1 \\cdot c_2 & = (g^{m_1} \\cdot r^{n}_1)^{m_2} \\bmod n^2 \\\\\n", 252 | "& = g^{m_1m_2}(r_1^{m_2})^n \\bmod n^2 \\\\\n", 253 | "& = E(m_1m_2, pk) \n", 254 | "\\end{split}\n", 255 | "\\end{equation}$" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "id": "f13b0622-ee6c-4d39-b097-b62e9e349a77", 261 | "metadata": {}, 262 | "source": [ 263 | "# Code\n", 264 | "\n", 265 | "- [Paillier python implementation](https://github.com/data61/python-paillier)" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 1, 271 | "id": "d716e9eb-779e-414b-b97e-dd95a6c22a2e", 272 | "metadata": {}, 273 | "outputs": [], 274 | "source": [ 275 | "import random\n", 276 | "\n", 277 | "from Crypto.Util.number import GCD, bytes_to_long, getPrime, inverse, long_to_bytes" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 2, 283 | "id": "9a7de479-af1d-4950-b4a2-603ce829a220", 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "def keygen():\n", 288 | " p = getPrime(1024)\n", 289 | " q = getPrime(1024)\n", 290 | " assert GCD(p * q, (p - 1) * (q - 1)) == 1, \"GCD != 1\"\n", 291 | "\n", 292 | " n = p * q\n", 293 | " phi = (p - 1) * (q - 1)\n", 294 | " lambdaa = phi\n", 295 | " g = n + 1\n", 296 | " mu = inverse(phi, n)\n", 297 | "\n", 298 | " return (n, g), (lambdaa, mu)\n", 299 | "\n", 300 | "\n", 301 | "def encrypt(m, n, g):\n", 302 | " while True:\n", 303 | " r = random.randint(1, n - 1)\n", 304 | " if GCD(n, r) == 1:\n", 305 | " break\n", 306 | " c = (pow(g, m, n**2) * pow(r, n, n**2)) % (n**2)\n", 307 | "\n", 308 | " return c\n", 309 | "\n", 310 | "\n", 311 | "def decrypt(c, n, g, lambdaa, mu):\n", 312 | " temp = pow(c, lambdaa, n**2)\n", 313 | " temp = (temp - 1) // n\n", 314 | " m = (temp * mu) % n\n", 315 | "\n", 316 | " return m" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": 3, 322 | "id": "5558134a-a936-4df0-be4b-d448c5c9bab6", 323 | "metadata": {}, 324 | "outputs": [], 325 | "source": [ 326 | "(n, g), (lambdaa, mu) = keygen()\n", 327 | "# (n, g), (lambdaa, mu)" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": 4, 333 | "id": "1aebad0d-b046-4ceb-b978-4f0382c61113", 334 | "metadata": {}, 335 | "outputs": [ 336 | { 337 | "name": "stdout", 338 | "output_type": "stream", 339 | "text": [ 340 | "b'secret_message'\n" 341 | ] 342 | } 343 | ], 344 | "source": [ 345 | "# Encryption\n", 346 | "\n", 347 | "m = bytes_to_long(b\"secret_message\")\n", 348 | "c = encrypt(m, n, g)\n", 349 | "m_decr = decrypt(c, n, g, lambdaa, mu)\n", 350 | "\n", 351 | "print(long_to_bytes(m_decr))" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 5, 357 | "id": "459528fb-6a62-49cf-a1d3-cf9eefc46204", 358 | "metadata": {}, 359 | "outputs": [ 360 | { 361 | "data": { 362 | "text/plain": [ 363 | "(3000, 3000)" 364 | ] 365 | }, 366 | "execution_count": 5, 367 | "metadata": {}, 368 | "output_type": "execute_result" 369 | } 370 | ], 371 | "source": [ 372 | "# Addition\n", 373 | "(n, g), (lambdaa, mu) = keygen()\n", 374 | "\n", 375 | "m1 = 1000\n", 376 | "m2 = 2000\n", 377 | "\n", 378 | "c1 = encrypt(m1, n, g)\n", 379 | "c2 = encrypt(m2, n, g)\n", 380 | "\n", 381 | "c3 = c1 * c2\n", 382 | "m3 = decrypt(c3, n, g, lambdaa, mu)\n", 383 | "\n", 384 | "m1 + m2, m3" 385 | ] 386 | }, 387 | { 388 | "cell_type": "code", 389 | "execution_count": 6, 390 | "id": "46ad2d00-e4fe-42a5-b6b7-b0fa5e92f97d", 391 | "metadata": {}, 392 | "outputs": [ 393 | { 394 | "data": { 395 | "text/plain": [ 396 | "(2000000, 2000000)" 397 | ] 398 | }, 399 | "execution_count": 6, 400 | "metadata": {}, 401 | "output_type": "execute_result" 402 | } 403 | ], 404 | "source": [ 405 | "# Multiplication\n", 406 | "\n", 407 | "(n, g), (lambdaa, mu) = keygen()\n", 408 | "\n", 409 | "m1 = 1000\n", 410 | "m2 = 2000\n", 411 | "\n", 412 | "c1 = encrypt(m1, n, g)\n", 413 | "\n", 414 | "c3 = pow(c1, m2, n**2)\n", 415 | "m3 = decrypt(c3, n, g, lambdaa, mu)\n", 416 | "\n", 417 | "m1 * m2, m3" 418 | ] 419 | }, 420 | { 421 | "cell_type": "markdown", 422 | "id": "25cd7fe3-4151-424e-8f20-0c624ba1e255", 423 | "metadata": {}, 424 | "source": [ 425 | "# Resources" 426 | ] 427 | }, 428 | { 429 | "cell_type": "markdown", 430 | "id": "9de26536-167a-4cc3-bb1d-753a637ff49b", 431 | "metadata": {}, 432 | "source": [ 433 | "\n", 434 | "- [Wikipedia entry](https://en.wikipedia.org/wiki/Homomorphic_encryption)\n", 435 | "- [Openmined paillier blog](https://blog.openmined.org/the-paillier-cryptosystem/)\n", 436 | "- [Paillier paper](https://www.cs.tau.ac.il/~fiat/crypt07/papers/Pai99pai.pdf )\n" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": null, 442 | "id": "743dea31-067c-41a8-9e8e-f68bb3a3ee3f", 443 | "metadata": {}, 444 | "outputs": [], 445 | "source": [] 446 | } 447 | ], 448 | "metadata": { 449 | "kernelspec": { 450 | "display_name": "Python 3 (ipykernel)", 451 | "language": "python", 452 | "name": "python3" 453 | }, 454 | "language_info": { 455 | "codemirror_mode": { 456 | "name": "ipython", 457 | "version": 3 458 | }, 459 | "file_extension": ".py", 460 | "mimetype": "text/x-python", 461 | "name": "python", 462 | "nbconvert_exporter": "python", 463 | "pygments_lexer": "ipython3", 464 | "version": "3.10.4" 465 | } 466 | }, 467 | "nbformat": 4, 468 | "nbformat_minor": 5 469 | } 470 | --------------------------------------------------------------------------------