Add RSA
This commit is contained in:
		
							parent
							
								
									3b934c43c2
								
							
						
					
					
						commit
						5fca4cd283
					
				
							
								
								
									
										168
									
								
								TTM4135.ipynb
								
								
								
								
							
							
						
						
									
										168
									
								
								TTM4135.ipynb
								
								
								
								
							| 
						 | 
				
			
			@ -1,5 +1,12 @@
 | 
			
		|||
{
 | 
			
		||||
 "cells": [
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": null,
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "outputs": [],
 | 
			
		||||
   "source": []
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "markdown",
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
| 
						 | 
				
			
			@ -223,9 +230,7 @@
 | 
			
		|||
   "metadata": {},
 | 
			
		||||
   "source": [
 | 
			
		||||
    "# Euler function φ and Z*n\n",
 | 
			
		||||
    "From slides 2020-4135-l07 - Number Theory for Public Key Cryptography\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "> $\\phi(16) = \\phi(2^{4}) = 16*\\left(1-\\frac{1}{2}\\right)$"
 | 
			
		||||
    "From slides 2020-4135-l07 - Number Theory for Public Key Cryptography\n"
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			@ -593,14 +598,13 @@
 | 
			
		|||
    "# Square and multiply\n",
 | 
			
		||||
    "from math import log, floor\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "def square_and_multiply(y,e,n, verbose=True):\n",
 | 
			
		||||
    "def square_and_multiply(y,e,n, verbose=False):\n",
 | 
			
		||||
    "    # prep\n",
 | 
			
		||||
    "    e_bin = bin(e)[:1:-1] # e0, e1, e2, e3, ... , ek\n",
 | 
			
		||||
    "    k = len(e_bin)\n",
 | 
			
		||||
    "    z = 1\n",
 | 
			
		||||
    "    yi = y\n",
 | 
			
		||||
    "    indices = []\n",
 | 
			
		||||
    "    # -------------\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    for i in range(k):\n",
 | 
			
		||||
    "        ei = int(e_bin[i])\n",
 | 
			
		||||
| 
						 | 
				
			
			@ -611,12 +615,10 @@
 | 
			
		|||
    "        if ei:\n",
 | 
			
		||||
    "            indices.append(i)\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    # post calc\n",
 | 
			
		||||
    "    mults = str(e_bin).count(\"1\") - 1\n",
 | 
			
		||||
    "    squarings = floor( log(e, 2) )\n",
 | 
			
		||||
    "    # -------------\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    if verbose:\n",
 | 
			
		||||
    "        mults = str(e_bin).count(\"1\") - 1\n",
 | 
			
		||||
    "        squarings = floor( log(e, 2) )\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "        print(f\"{' * '.join([f'{y}^({2**i})' for i in indices])}\")\n",
 | 
			
		||||
    "        print(f\"squarings: {squarings}\")\n",
 | 
			
		||||
    "        print(f\"mults: {mults}\")\n",
 | 
			
		||||
| 
						 | 
				
			
			@ -630,7 +632,7 @@
 | 
			
		|||
    "e = 102900819\n",
 | 
			
		||||
    "n = 604604729\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "z = square_and_multiply(y,e,n, True)\n",
 | 
			
		||||
    "z = square_and_multiply(y,e,n, verbose=True)\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "print(f\"{y}^{e} mod({n}) = {z}\")"
 | 
			
		||||
   ]
 | 
			
		||||
| 
						 | 
				
			
			@ -702,16 +704,144 @@
 | 
			
		|||
   "cell_type": "markdown",
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "source": [
 | 
			
		||||
    "# Block ciphers\n",
 | 
			
		||||
    "# RSA\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "Notation:\n",
 | 
			
		||||
    "### Key generation\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "- `P`: Plaintext block (length n bits) \n",
 | 
			
		||||
    "- `C`: Ciphertext block (length n bits) \n",
 | 
			
		||||
    "- `K` : Key (length k bits)\n",
 | 
			
		||||
    "- `C = E(P, K)`: Encryption function \n",
 | 
			
		||||
    "- `P = D(C, K)`: Decryption function\n",
 | 
			
		||||
    "- `IV`: Initialisation vector"
 | 
			
		||||
    "1. Let $p$ and $q$ be distinct prime numbers, randomly chosen from the set of all prime numbers of a certain size.\n",
 | 
			
		||||
    "2. Compute $n = pq$.\n",
 | 
			
		||||
    "3. Select $e$ randomly with $gcd(e, \\varphi(n)) = 1$.\n",
 | 
			
		||||
    "4. Compute $d = e−1 \\mod \\varphi(n)$.\n",
 | 
			
		||||
    "5. The public key is the pair $n$ and $e$.\n",
 | 
			
		||||
    "6. The private key consists of the values $p$, $q$ and $d$.\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "### Encryption\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "The public key for encryption is $KE = (n, e)$\n",
 | 
			
		||||
    "1. Input is any value $M$ where $0 < M < n$. \n",
 | 
			
		||||
    "2. Compute $C = E(M,KE) = Me mod n$.\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "### Decryption\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "The private key for decryption is KD = d (values p and q are not used here).\n",
 | 
			
		||||
    "1. Compute D(C,KD) = Cd mod n = M."
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": 24,
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "outputs": [
 | 
			
		||||
    {
 | 
			
		||||
     "name": "stdout",
 | 
			
		||||
     "output_type": "stream",
 | 
			
		||||
     "text": [
 | 
			
		||||
      "p=43, q=59, n=2537, 𝜑(n)=2436, e=5, d=1949\n",
 | 
			
		||||
      "\n",
 | 
			
		||||
      "Public key: n=2537, e=5\n",
 | 
			
		||||
      "Private key: p=43, q=59, d=1949\n",
 | 
			
		||||
      "\n",
 | 
			
		||||
      "{'n': 2537, 'e': 5, 'p': 43, 'q': 59, 'd': 1949}\n"
 | 
			
		||||
     ]
 | 
			
		||||
    }
 | 
			
		||||
   ],
 | 
			
		||||
   "source": [
 | 
			
		||||
    "import random\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "def rsa_keygen(p=None, q=None, e=None, prime_range=1000, verbose=False):\n",
 | 
			
		||||
    "    # Generate a set of primes. In practice, this should be\n",
 | 
			
		||||
    "    # a large number of large primes.\n",
 | 
			
		||||
    "    primes = [i for i in range(0,prime_range) if is_prime(i)]\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    if not p: p = random.choice(primes)\n",
 | 
			
		||||
    "    if not q: q = random.choice(primes)\n",
 | 
			
		||||
    "    n = p*q\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    # Euler function 𝜑(n) \n",
 | 
			
		||||
    "    phi_n = totient(n)\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    # Select e randomly with gcd(e, φ(n)) = 1.\n",
 | 
			
		||||
    "    if not e: e = random.randint(1, phi_n)\n",
 | 
			
		||||
    "    while not gcd(e, phi_n) == 1:\n",
 | 
			
		||||
    "        e = random.randint(1,phi_n)\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    # Compute d = e−1 mod φ(n).\n",
 | 
			
		||||
    "    d = inverse(e, phi_n)\n",
 | 
			
		||||
    "    \n",
 | 
			
		||||
    "    if verbose:\n",
 | 
			
		||||
    "        print(f\"p={p}, q={q}, n={n}, 𝜑(n)={phi_n}, e={e}, d={d}\\n\")\n",
 | 
			
		||||
    "        print(f\"Public key: n={n}, e={e}\")\n",
 | 
			
		||||
    "        print(f\"Private key: p={p}, q={q}, d={d}\\n\")\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    return {\"n\":n, \"e\":e, \"p\":p, \"q\":q, \"d\":d}\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "# Example from slides\n",
 | 
			
		||||
    "rsa_keys = rsa_keygen(p=43, q=59, e=5, verbose=True)\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "# Random keys\n",
 | 
			
		||||
    "#rsa_keys = rsa_keygen(verbose=True)\n",
 | 
			
		||||
    "print(rsa_keys)"
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": 22,
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "outputs": [
 | 
			
		||||
    {
 | 
			
		||||
     "name": "stdout",
 | 
			
		||||
     "output_type": "stream",
 | 
			
		||||
     "text": [
 | 
			
		||||
      "C = M^e (mod n) = 50^102900819 (mod 604604729) = 2488\n",
 | 
			
		||||
      "\n",
 | 
			
		||||
      "Ciphertext: 2488\n"
 | 
			
		||||
     ]
 | 
			
		||||
    }
 | 
			
		||||
   ],
 | 
			
		||||
   "source": [
 | 
			
		||||
    "def rsa_encrypt(M, rsa_keys):\n",
 | 
			
		||||
    "    # e and n are the public key\n",
 | 
			
		||||
    "    e = rsa_keys['e']\n",
 | 
			
		||||
    "    n = rsa_keys['n']\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    # C = M^e (mod n)\n",
 | 
			
		||||
    "    return square_and_multiply(M,e,n)\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "M = 50\n",
 | 
			
		||||
    "C = rsa_encrypt(M, rsa_keys)\n",
 | 
			
		||||
    "print(f\"C = M^e (mod n) = {M}^{e} (mod {n}) = {C}\\n\")\n",
 | 
			
		||||
    "print(f\"Ciphertext: {C}\")"
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": 23,
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "outputs": [
 | 
			
		||||
    {
 | 
			
		||||
     "name": "stdout",
 | 
			
		||||
     "output_type": "stream",
 | 
			
		||||
     "text": [
 | 
			
		||||
      "M = C^d (mod n) = 2488^1 (mod 604604729) = 50\n",
 | 
			
		||||
      "\n",
 | 
			
		||||
      "Message: 50\n"
 | 
			
		||||
     ]
 | 
			
		||||
    }
 | 
			
		||||
   ],
 | 
			
		||||
   "source": [
 | 
			
		||||
    "def rsa_decrypt(C, rsa_keys):\n",
 | 
			
		||||
    "    # private key\n",
 | 
			
		||||
    "    p = rsa_keys['p']\n",
 | 
			
		||||
    "    q = rsa_keys['q']\n",
 | 
			
		||||
    "    d = rsa_keys['d']\n",
 | 
			
		||||
    "    n = p*q\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "    # M = C^d (mod n)\n",
 | 
			
		||||
    "    return square_and_multiply(C,d,n)\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "M = rsa_decrypt(C, rsa_keys)\n",
 | 
			
		||||
    "print(f\"M = C^d (mod n) = {C}^{d} (mod {n}) = {M}\\n\")\n",
 | 
			
		||||
    "print(f\"Message: {M}\")"
 | 
			
		||||
   ]
 | 
			
		||||
  }
 | 
			
		||||
 ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue