{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Cryptography Lecture 2\n", "\n", " Discrete Logarithm problem, Diffie Helman key exchange and El-Gamal. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What is a group?\n", "\n", "A group $(G, \\cdot)$ is a set together with a binary operation $\\cdot: G\\times G \\rightarrow G$ such that\n", "- for all $a,b,c\\in G$ we have that $(a\\cdot b)\\cdot c = a \\cdot (b\\cdot c)$\n", "- There is an element $e$ (called the identity element) in $G$ such that for all $a \\in G$, we have $e \\cdot a = a \\cdot e = a$.\n", "- For every $a\\in G$ there is a corresponding $b\\in G$ such that $a\\cdot b = b\\cdot a = e$. \n", "\n", "Furthermore if for any $a,b\\in G$ one has $a \\cdot b = b\\cdot a$ then we say that the group $(G,\\cdot)$ is commutative. \n", "\n", "We can figure out some quick properties from these,\n", "- If $e$ and $e'$ are both identity elements then $e = e \\cdot e' = e'$. \n", "- If $a \\in G$ is given and $b$ and $b'$ are both inverse elements of $a$, then $b = b\\cdot e= b\\cdot(a \\cdot b') = (b \\cdot a) \\cdot b'= e \\cdot b' = b'$. We call this unique element as $a^{-1}$ or $-a$ depending on whether we denote the group operation additively or multiplicatively.\n", "### Examples of groups:\n", "- The group of residue classes $a \\pmod m$ such that $\\operatorname{gcd}(a,m) = 1$, under multiplication.\n", "- The group of residue classes $a \\pmod m$ under addition.\n", "- Points $(x,y) \\in (\\mathbb{Z}/p\\mathbb{Z})^2$ satisfying the equation $y^2 = x^3 + ax + b$ such that $4a^3 + 27b^2 \\not\\equiv 0\\pmod{p}$ with addition defined as \n", "$$(x_1, y_1) \\oplus (x_2, y_2) = (\\lambda^2 - x_1 - x_2, \\lambda(2x_1 + x_2 - \\lambda^2) -y_1) $$\n", "where $$ \\lambda = \\begin{cases}\\frac{y_2 - y_1}{x_2-x_1} &\\text{ if } x_1 \\neq x_2\\\\ \\frac{3x^2 + a}{2y} &\\text{ if } x_1 = x_2 = x \\end{cases}$$\n", "This is called the modulo $p$ points of an Elliptic curve.\n", "- The set of real numbers $x>0$ with the operation as multiplication.\n", "- The set of upper triangular $5\\times 5$ matrices with 1's on the diagonal, under matrix multiplication.\n", "\n", "\n", "### Order of an element in a group\n", "- The least positive integer $e$ such that $g^e = 1$ in $G$ is called the order of the element $g \\in G$, and the order of $g$ divides $|G|$ by Lagrange's theorem. \n", "- If $e$ is the order of an element $g$, ($\\operatorname{ord}_G(g) = e$) then if $g^f =1 $ in $G$, then $e | f$. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Discrete Logarithm Problem for a group $G$\n", "\n", "For some group $(G,\\cdot)$ given $g$ and $A$ such that $g^a = A$ in $G$ for some integer $a$, find the integer $a$ in an expedient manner. \n", "\n", "In other words, is it easy to find, $a$ such that\n", "$$ \\underbrace{g \\cdot g \\cdot \\ldots g}_{a \\text{ times }} = A.$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Diffie Helman Probelm\n", "The Diffie Helman problem is actually weaker than that (or is it?). The problem is given $g^a$ and $g^b$ is there an efficient algorithm to find $g^{ab}$. It is clear that if one can solve the Discrete Logarithm Problem (DLP) for the group $((\\mathbb{Z}/p\\mathbb{Z})^\\times , *)$ efficiently, then one can solve the Diffie Helman Problem (DHP). It is not known if an efficient solution of the DHP implies an efficient solution for DLP." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD8CAYAAAB5Pm/hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzsnXV4VNfWh989lokrMQIJ7u5QrJQWWlra0lJ391t3+Xp7b723cmvcurfUgBZ3dwgEEhJCEuKuk9Fz9vfHhBSJZyYJZd7n4UkynNlnT3LOOnsv+S0hpcSDBw8ePPx90bT3BDx48ODBg3vxGHoPHjx4+JvjMfQePHjw8DfHY+g9ePDg4W+Ox9B78ODBw98cj6H34MGDh785HkPvwYMHD39zPIbegwcPHv7meAy9Bw8ePPzN0bX3BADCwsJkXFxce0/DgwcPHk4rdu3aVSSl7NTYcR3C0MfFxbFz5872noYHDx48nFYIITKacpzHdePBgwcPf3M8ht6DBw8e/uZ4DL0HDx48/M3xGHoPHjx4+JvjMfQePHjw8DfHY+g9ePDg4W/OGWXoVVVisSvtPY12o6DSwsL4HAoqLe09lb8tFrvCmdq1TUrJmqQCtqeVtPdUPJxEh8ijbwsKKizMem8jxSYbL80ewFVjYtt7Sm2KzaEy8+0NmO0K3notm588Gy+d1qXniM8sY192ObMGRRHsa3Dp2O5CSkl+hZVO/l5oNaJVYz23IIGvt2QwIDqAX+4e7/Lfb0fnnZUpfLzhCEjJW3OHMnNQlEvHr7TYWRifQ58If0bGhbh0bHdSbrYjBAQY9e02hzNmRb/mUAEVFjuKKpm34YhbzpFTZiartNotY7eWapuDsmob1TaF0mob5Wa7S8dPKzJxxbwtvPTHQa79dJtLx3YnN3+xg4mvreb8dzZgc6itGuvbbUeRQGqhicTcStdM8DgsdoXE3ArsSuvm6S72Z5djtilYHCpbjxS7fPzbvtrJi4uc11dCdrnLx3cH65MLGfWvlYx6aSWbU4vabR5njKEf2z0UnUaDQafhkmExzXrvobxKEnMrGjxmTVIBU99Yy7Q317Fkf25rpuoWgnwMtasgjRD8ujsbgF93ZfHCwgMtekClFlZx9htrOefNtSRklyMQWB0qOWVml87dXdgcKmsOFWJXJOnFJo6WmFo13rR+4XjpNIT4GugV7tfk95VX29mSWozZVr9b0WJXmP6fdVzywSaunLelQ7qHbpnYDQFICYv25SKlJK3IxPMLEvhjX06zx5NS8ujP8Qz/5wo+23iErFIzVoeKBkF+xenhfvx1dxY2h4rVobJgb/N/B67ijHHdxIb6svrhyaxIzOesnmENHutQVN5ZlUJWqZkRsUG89GciAP+6eBBzRtT9kFh+MB9rzYpw6YE8l29bXUHPcD92ZZQCUFJlY0d6CU//noDVobAtrZglD0xq1ngfrDlMWpHTOG5NLeKq0V3ZcqSIJ2f2c/nc3YFBp+H8gZEsO5hP7wg/YkN9WzXeR9eMYNmBPHRagY+hYbfN1iPFfLEpnen9w3ll6SFMVgddQ3xY8sBEhDjVhZRdZqagworVobIrowybonY411BkgBGDToPVoWKyOgC44bPtZJZU8+POTLqF+TIgOrDJ4x3Kr2RRfA4Wu8pLfybyw+1jeXHRQQbHBDGlT7i7PoZLmTuqC0sS8hDAnOHNW2C6kjPG0APc+90eEnKcW74VD02mc5B3ncf9vjeHTzYcwepQ2ZJahMXuNOAbDxedYuhLTDYCjDquGdOVRfE5qFJyw/g4t36OlvLwuX0oM9vRaQT3nN2TAzW/CynBrjR/hTisazCL9+cCguGxIfU+BF2Bxa7wwsID5FVYePGigXQN9XHJuO9fM5yyajuB3no0rfTRrzlUwIM/7UUIwW1ndeOhc/vUeZyiSm78fDsWu8qqpHyEENgcKofyKrErEoPur3lY7Ao2RSUu1JfR3ULYkFLEVaO7dDgjD9C9kx9PX9CPJfvzuHtqD4QQOFQVCQjA0cxrLCrAG4NOg0YIYoK9Gd0tlD/un+iWuQMsS8jlk41pXDqss8tieON7hLHnuekIBN6NPPzdyRll6JPyKqi2KfgYtGQUmwj39+KnnZkYtBrmDI+pvdG9dBpAoBGCuFBfhBAoquT2Sd1PGO/FRQf5aks6EQFGlvxjIvtfOBcpabXBcBchvgbev3p47c/juofy2Iw+7M0s4/5pvZo93rVjY+kT6Y9GwIhY9wbH5u/M5Lc92dgcKk/9tp9vbh3jknGFEC4LHCfVGGpFVdmbWQbA7qOlbDtSwkVDo2sXFgLQaTSAigCm9O7EhpQibpoQh0H3lzc1MbeCOR9uxq6o/GfuUL6+ZQyqKjvs9QVw/bg4rh8XV/vzZzeO4v01hxnXPZQhXYKaNVagj57l/5jM/uxyxvUIdfFMT8TmULn3+z3YFUl8ZjlT+0YQGWh0ydg+hvY3s+0/gzbkxdkD+ffiREbFhTA6LoT/rEjm041pIKDS4uDms7oBMGtwFOXVdrLLzdwxqTtBPnUbgp92ZuJQJaXVNvYeLWNS707UsevusAghuGlCt1aNMaqV2Q9l1TZu/WonhZVW3r1yWL3GIMTXC40Q6LUawvw6ZkbPFaO6sPxAHmVmO4/N6EtuuZmr/7cVhyL5cks6W5+cBjgXAj/dMY75uzI5p18EE+pxJa44mI/FrqBK+GZbBrOGRHdoI18XfSMDeO+q4Y0fWA+RgcZWG9x561P5ZEMas4dG89T5/ep0jWk1Am+9FkV1oNUIjPq/V/jyjDL0Fw/rzMXDOtf+XFhlxa5IhIDCSmvt60IIrh3X+NbtshExfLM1gyBvfbNXKy2lwmLnmv9tI6PYxOuXDea8gR0rFiClrPNGOvmYr7ZksDezjMhAI/syy7Apkpf+PMj8O8fX+Z7zB0WiSElhpZWrRndxx9RbTZifFwvuPav25+T8SpDgUCXl1SdmOfWPDuD56AENjndOvwg+WpeKXVG5enRXt8y5LuatT+XtlSmM6xHKx9eOQKftWEavKddYcn4lH6xJZXjXQF5ZkoQq4cstGVw/Lo4uIae6/bQawe/3TGBJQh6TenWqd3F3unJGGfqTefS8vpRW2zFoNdw5pUez3//CRQO49+yeBHrr0bfRzbDiQD6HCyox21VeXpLUoQz9b7uzePTnfUQFGvntngmE+XnVedy2tBJeWZKExa4QGWhEoxH4aDUMjqn/YSmE4KIh0e6aulvoHeHPQ+f2ZvmBfO5rgWusf3QAu56Zjk1RCfRuuxzsN5YlY1NUNh8uZn92OcO6BrfZuRuixGTj4vc3kV1m5tU5g7msgZjQzZ/vIKvMzJKEHEJ9vTDZHOi1zoyo+ujeyY97pvZ0x9TbnTPa0Hfy9+J/149s1Rj1GTNXk5RXwVO/7q+54Z1ZHeN6NJw91Na8u/owDlVSWGVldWIBc0fVvfLWaYQzQCfA36jjo2tHUGyyMqX36ZFJ0Rxun9SD2yc1fxFxDG+DFm/cH8RTVMmzvyewP7ucHuG+ZBRXo9dqiGtlJpIrWZWYT2GlBUWVvLc6pUFDr9UIBM4FwttXDKXMbGdkXDC+XmemyWvSpxZCBAGfAAMBCdwMHAJ+BOKAdGCulLJUOPdU7wDnA9XAjVLK3S6f+RnGk7/sZ09mGUa9hvvP7sWobiGM6CArrWPMGBjJ55vS0ArBiLi/5pZZUo1DlXQLcxqNkXEh/OvigcRnlXHbxO51bqUBSk02vticTrcwX2YPjW50u94S8iss3PH1Lix2hQ+uGU73Tk3Pf/87sSoxn9/3ZlNtU+ga7M0nN4ykd4R/h6pwHhkXgkY4/efnDYisfb3a5iAlv4q+Uf612Uhf3DyazzamMSoumAm96l8QLYzPIbWgiuvHxRLqpkXbG8sO8evuLG6cENeqh35raOrj7R1gqZTyMiGEAfABngJWSSlfEUI8ATwBPA7MBHrV/BsDfFjz1UMr6BLiQ2JeBQIY0Dmw1UFQd/DYeX24dFhnQnwNtTfNl5vT+defiQgBr1w6iEtqconnjIhpNB3zvu/3sPVIMXqthkAfPVPdkDv9yYYj7MsqQ0r4z4pk3ru65YHD05moQG9UKfHSaYgJ8WF8B9stAnQL82XD42dTXGWlZ01BWmGllZnvrMdkVejeyZc/7jsLIQTdwnz558UDGxxvY0oRj/+8D5virOT98Y5xLp9zbrmZeeuPYFNUXl16iGvGxLbLrqLRMwohAoBJwI0AUkobYBNCzAam1Bz2JbAWp6GfDXwlnaV7W4UQQUKIKCllxysX7SBY7Ap6raZBrZXXLhvMuD2hRAd5M7l3o72A2wUhBL0i/Gt/XpNUwIuLDnAsfXplYkGtoW8KlTWSFXottQU4rqZfVEDtKrB/dIBbztHeqKrEpqgY9fW7gAbFBPLlTaNJLqji4qEdNxYS4muo9bPbFZXz311PUZUNgIM5FZjtSpPTGatqrilFlbXfu5pAbz3eBi1ah8DfqGvwb+BOmvIb6Q4UAp8LIYYAu4AHgIhjxltKmSuEOLbc6gxkHvf+rJrXOoShX3OogLdXJDOtX0SLcsddzS+7snj8l30EeOtZeO8EYoLrdmMY9VquasPMC1ew52gpao2R12oEt05sXirnO1cO4+UlifQM92Omm4LOlw6PITLAiNWhMqVP6x+g5dV2HvslHrNN4bXLhrgsF7ullJhsXPDuBgoqrDw+s0+DroMx3UMZ0929+equpMJsp6TGyANcOrxzs3LWz+0fwa0Tu3Eov5LHZ/R1xxTxMehY+o+JbE8rYULPsFYL57WUpqSK6IDhwIdSymGACaebpj7q+iSnlMQJIW4XQuwUQuwsLCxs0mRdwT3f7iY+q5wP1x6urQxtT/634QgOVWKyOliVWOD288VnlvH2imRn6p+buXJ0V3qE+xER4MVvd49vdvZGXJgvH183kkfP6+vWG2R8zzCm9g2vjQFUWOwk5lagqs2vFp634QirEgvYeLiIl5ckunqqzWbT4SLKzXYUKZ01I27GZHXw0bpUftmV5XY9nlA/L26c0A1/o45bzurGm3OHNuv9Go3g4XP7MO+6kfRwY2wmKtCb2UM71yZuSCk5lFdJWbWtkXe6jqY8/rKALCnlMUnCn3Ea+vxjLhkhRBRQcNzxx6dbxACnqPlIKecB8wBGjhzZZgpNYX5e5JRVY7Gr3PrlTj67cRT9otp2y15tc/D+msPotRouHtaZt5Yno9OIegtnXEV5tZ0r523FYlf4dGMau5+b7ta00Oggb1Y+NNlt47uDEpONaW+uxWxXmNonnA+vHdGs90cFGNFrBTaHZGlCHm8sO8Qj59UtheBOViXmsyqpgBkDItFrNRh0kkuOqyFxF0//lsDi/bloNaDTCmYPde85n53Vn2dn9XfrOVzN8wsO8NOuTHQaDUv/MbHeXbwrafQul1LmAZlCiGNX6zTgILAQuKHmtRuABTXfLwSuF07GAuUdyT8//85xjO4WCgJyyy28vTLZZWMXVlr5c18uRVXWBo97c3ky/1ufxodrU7HaVdY9NoWtT02rDTC5C6uioKgSCVgczu9bgsWu8OKiAzwyP57iRj5rR0FK2SQZ4qTcCqwOFYtdZV1y83ea14ztypPn94MaJc8P16W6TBJaSsnaQwW1wnT1kVlSzT3f7ua7bUe57/s9bH5iKqsfnswTbSA2V2a24VBVVOl0rbSU1Un53PbVTlYn5btwdu7FrqhN2sUsP5iHxa6iSlkrleFumrqcuw/4VgixDxgK/Bt4BZguhEgBptf8DLAYOAIcBv4H3O3SGbeSiAAj14+LxUunwVuvZUSsa1IUrQ6FGW+v59Gf45n59oYGNcMdiopEIqXEoapEBXrj3wZNCcL9jbwyZxDje4Ty4TUj6g0MZZZU8+22DDJL6pYu/mpLOt9uO8rve7J58Y+Dbpyxa7A6FGa/v4nezyzhxUUNz3d4bDA9w/0QAu6c3L3BY+tCCMEVo7oQ4mvAx6Alwt8LXxeJWf1nZTJ3fbubaz7ZyvIDefUep0pZ6ytVVYmPQdcmq0aAf10yiHP6R3D5iC711lEoqmTB3mxWJebXaRgrLHbu/Ho3Kw7mc+fXu6m0uLZ3gjv4ccdR+j67lLEvr2q0g9t9Z/dCqxFEBhqZ2KttEiuaFLmQUu4F6qosmlbHsRK4p5XzciszBkbxU5A3ZpvC6G6uSVOssjiosNixK86Vo8nqqLeM+pHz+iAE6LUa7p7StpV4lw6P4dIGMl+sDoVZ723Ealcw6DRsf/qcUx4IRp22phgFDFoNKfmVxIX5tll1cHM5mFNBSn4V4HxIPXdh/Vt9o17LwnvPalKZfX146bQse3ASuzNKGRUX4jIJgf1ZzsYeWo0gMbeCc4/LJT+e2FBf3rhsCCsS87n5rG5uqT+oj85B3sy7ruEixDeWHeKLzekAvHzpoBNkSQC0QqDRAIoziJ9XbsHmUN2W5+4KPlyXiqJKys121iQVcMWo+hMnrhkby9Vjurbp3+XMLBODBsvtW0Konxd3Te7BDzsyuXpM1wa1MvyNel64qOEc3/bCYnc+pByqRJGSapuCUa9FSskvu7I4lF/JzRO61Yq5/bEvh0Xv5dA3KoDf7h7fphdvU+kV4U+Qjx7VJJlUT2pqSn4ld3yzC6Ney6c3jCQqsG4J66YS4mvgnP4RrRrjZB6b0Zf04moCvfVc3YiM7oVDo7mwg6ZJHimqwmJ3PrDSi/9q9nK4oIrvtmUwoWcY3902lj/35SIEzHpvIxrhFIIbFNN0Pfu25KLB0Xy8/ghajYYx3U7NXFJVyaM/72N9SiEPTe/d5hl0oiN0qhk5cqTcuXNne0/jb4fFrrAxpYjeEf4N6refLH375eZ0vt6SwdVjutYqeq5PLuSOr3dhcygM7RrML3eNJ7OkmmlvrsOmqGgE7HvhPPw6aIm52aaQXWame5hvnQqQd3+7m8X7c9EIuG1i9xo/u4fGSMgup6zazoSeofU+5KWUJ8h3ZxSbePDHvfgb9bxz5dDaRdGYf62koNKKl07D4gcm0r2TH3M+3MyujFK0GsHD5/Zu8x1wc8goNhHkY6hTlyg+s4wr523FbFfw0mk49NJMl5xTCLFLStmojkvH3Gt7AJxdhX7akdmk1nwFFRbu+Honj8yPry0uuuXLHdz/wx5mvLO+fn/75nR6Pr2YqW+srQ0a3jA+jpUPT6418kBt9yxVUhvU7BzkXasTfuGQ6FOMfHm1vcUBX1fjbdDSM9yvXpnfITGBeOu1eOk0DOzcMVeNrkZRJX/uy2V9E4POH69L5ar/bWV7WgngfPhf9tFmbvtqJ28sP1Tne3LLzYx9eRW9n1nC4v3O5LvYUF9+vXsCX948+oSdr01xNilBOBU/Ae6c3AO9VhBg1HHBSV3bLHbFbYV0LSE21Lde8bnoIG80GvAxaJvVZtJVdMzl19+I7WklvLjoAINjgvjnxQObnA9udShc8O4GLHan62TbU9Ma7Cr0zz8PsvJgPhqNIC7Uh3vP7sWBnL8araQVmerUlPnvmsOo0qn5sulwEefX0wLxnH7h3Ht2T5LyKnikpnOSRiP48ubR2BX1FP/8c78n8O22o3QN9eHP+8/qEM0XGuL2Sd0Z2DkQo17j9iYqrsRsU3hkfjw5ZWZemTOYPpH+jb+phuN95a9dNpgLG1AHTcgu5z8rk7HYVRJzdrL3+XM5kFOBQ3EmFOzOqDt7ZGlCHqUmOw5V8v6aVM4fVP85vrhpNB+tS2Vq33B611RYT+8fQeKLM5wiZcftGBKyy5n78RYciuSDa4a73E3majr5e7H0gUkcyClvswDs8XhW9E3g7ZXJjP33Kv67+nCz3/vgj3tJyKng973ZrEtuekFUtVWhyuLAYlepsjhqG0cXVVnZn1V+SjFPiK8BXY2MwjEhqhcuHECYn4EJPcPq7dAzY0AkRp3zfUMb0NQXQnDP1J68d9XwU3qr1hWE/XFnJoqU5FdY2J/V/oVpjSGEs46hPYx8Ul4F57y1jjkfbG52uuovu7NYmZjPnswynvl9f7Pem1JQidmuYFdU0gqdvnJFlcRnllFqOrGY59huTSsgoGbVevnIGPpFBdA5yJsnZtZdWTq2eyhajcBLp6l3EXGMIV2C+PDaEcwdeWK2jk6rOcUt9Oe+XKptzjaL32zNaPqHbke6hPgwY2BUx9S6OdMprrLy/prD2BXJ2yuTuXZsw4HW41l+II+8CgsCpx88IqDp5fDBvgYem9GH77YdrQ3uZpZUM/OdDSiqZNaQKF6/bEjt8U/O7EdsiC9+Xrpa+daTG63Uxf/NHsB142IJ9zcS6OO6FM/ZQ6P5bU82Ib4GBjTDFbL2UAEL9uZw5agup1U5fmt4ZUkShwuq0GkE32472mRpjnKznU9rehsbtIKu9aiA1seT5/cjv8JCgFHPdTWNdu7+dhfrk4sw6DSsfGgynfydmS5xYb58fuNodmWU1OoVhfl5sei+s+odH5xaQhsfn0q52e5SZdDzBkbyxeZ0FFUyd1TT9ZNKTDb+syKZMD8D90zt2eGaqrgLj6FvBD+jDn+jHrNdwdegbdbT+F+LE52iXBrBbZO6MyC6eb7fk7XME7LLUaXEbFdYd+hEv6pRrz3Bp95UThYicxWvzhnMw+f2IdjHcEIf1IYoNdm44+tdWB0qS/bnsvf5c9tNBKotGdQ5kG1HSpDIZrleliXkkVvhzNkO8tbz70sHNeu8PTr5sei+E5ttbzpcjNmuIAQcyqusNfQA43qEtqh3a6ifl8tTI4d2CWLHM+fgUNRmdYN6+rf9rDiYj04r6ORv5Ooxp5d+VEvxGPpG8NJpWfrARLamlTCue2izcsXHdguhsNKKlDBrcOtT3Sb27kRcqC+HC6p4aHrvVo/nToQQp+xg7IpKfoWFzkHedWZonPCSOOnnZvJHfA4frUvloiHRhPh5YdRruGBQVIdM/3zwnN4M6xpEgFHPyGbITw/oHICoaUIzfUBkgzGcpnL/tJ68vuwQfSL9GRnXsfodnExdGV4FlRZ8Dbp6F2TH//1bcykUVFp4dP4+tBrBzRPiSCmo4oLBUYT7t6+IXX140ivr4WhxNb/szmRMt1DGt1CDRlEl29NK6Bzk3WB649+JTYeLeOb3BPpHBfCfK4bWruatDoWZ72wgs6Saib068dmNo+p8/4aUQhbF5zB3ZJdmGb3jsSsq/Z5dikOVaGoK0zRC8Oysfo3mn7cViir5fvtRLHaFa8fGtnjnklFsIqfMwphuIadd4/CWYLI6uPe73WSWmnnz8iEn9Gr+bFMaLy9OxEunZcG9E+oUKiurtvHOqhQ6+Xlx+6TuLXbdPPnrfn7acbSmU5pAqxFEBRpZ9+jUln60FtHU9ErPir4e5s7bQkGFhY91R1jx4OR6uyA1hFYjWrTVbSvWHirgkfnxdAvz5fObRrskB/7xX/aRVWomv8LC6qR8ZtTIC6cXVZNTasauSFYnFaCoss4MpIm9OrU6K0ErBIHe+lo9e7uiohGC7LKGS9Pbki82p/P60iRUnJpLLRXmig31PSU43lGosjq46fPtpBWZeOPyIUxxQeOY3/dmszm1GKtD5dkFCSw8rhn7/J2Z2BWJQGVDcmGdhj7Ix8DzFzbclL0pRAcZMeg0qFLWphwXVnZc3aczztDHZ5aRX2FhWr+IBlMdTVZHrZZ6dU3Giys5ljbZnry46CBFVTZMVgdLE/Ia7MHZVHqF+1FcZUOV8gQD1L2TL70j/EnIKefCIdFulR3WaAQL7p3AsgP59I7w48O1qfgYtNzWTD38llBWbWNDShEjYoOJDqq/uraiRjpYlbhFrvbYw6299M/BmVqZkF2O2a7y4qKDLjH03cOcOkTeei19Toot3TyhG0/+uh8fg5Zp/dybbnn3lJ50DvJGIyC1wMSaQwU8dG7HdaeeUa6bLanF3PTFdjRCcOmwzrx0Sf3Bq21HivnvmsNM6xvOjRNcZyCklNz65U5WJRVwTr9w/nf9yHbzGz86P54/9+eiSskvd41nQHQg5dV2nvh1HzaHyitzBp8QjGsKFrvCsgN5xAR70y3Mr7YbEDg/e6XVQUAbCLi1B1JKJr2+huIqGzqNYOMTZ9f7WU1WB/+36CBmu4MXLhzg0mDlmkMF3PHVLrz0Gn69a7xbgu1N4UBOOXM+3IxGCC4Y/FeW2DdbM/hldxa3TezWYF59fezKKCGnzMywrsFEBhhPcL9U2xzotZoOq7vkajyumzpIKahESqi2KyTkVDR4bGu77Siq5Jnf97MjrYSnZ/Wv7XdaWGWtlb9de6iQYpOttiFBW/PKnMFcNDSazkHetalvH6w9zIqD+UgJry9L4rXjUjibglGvZWiXIGa9txGLXeHp8/vVPiiFEG1i5KWU/Lo7m3KznavHdG2znZNDlWSXmlEleOk0FFVa6/28vl46XrtscKvOtzGliBcWJTC0SzCvXDqo1uB9uiENm6JiV1QWxefw0Lltr4cPMCA6kD/vn0hOmbm2B21euYUXFx3Epqg88MNepvWLaHYQeURsCJ9s2MVDP8UTG+rsE3vsb9xWhXmH8ipZfiCPc/pHtHk/i5ZwZjz2arh4WGeGdw0mNtSnQQVDV7D1SDEL9uZwuNDEIz/F174e6utF7wh/vHQa+kb6E9KM1DBXo9UIJvbqdEJ+c7i/FzqtQK8TRDYj7/941icXYnOo2BXJd9uPumq6TWb+riye/n0/ry5N4p9tKKOs12p4dlZ/IgK8uGZMLN3C3Os7f3j+Xg4XmFi8P5cNKUW1r188rDNeOg1eeg2T3dBQvTn06OTHxF6dal1I3notWo1ApxH4GHToNM03QaoqWZKQh12RZJVWc6TQ1PibXIjFrnDpB5v4z8pk5ny4mWpbx5FhqI8zakUfYNTz/e1jWz3O0eJq3lxxiL6R/tw5uUedrpeoQCOqlBj1GmKPy7jR1viPj5ZU0zXEp8NlStw0oRuBPgbsisrlLfTZT+kTzhvLk1FUyQ3j4lw6v/qCuMdTarKhqhKHKimuart2beD8/d3USlefqko+WHuY1EITD5/bu14t+bhQXyrMdlQp6Rz8VzzgshExTOgZipdOe4LrrCMQ6KPnl7vGsz6lkBkDIlsUQ9AjH+glAAAgAElEQVRoBBcNiebP/bnEhvrSI9x1D9RjFecN3Zd2RcWmOJur2BUVu0NCx/o1n8IZ5aN3FRe+t5GE7HKMei3vXTWsXp2NAznlHMypYMbAyDZpLFIfUkrWJhdisjqYOTCqTQJ0NoeKxaG41FXz4qKDfLYpjRGxwfxw+9h6/bDVNgfPLzhAabWNf148sNWSw23N4v25PPxTPFaHwrAapdC6qLI6WLI/l76RAe0u35tVWs3GlCIm9u5E5waC0K5CSklZtZ1Ab73LFksJ2eVcOW8riir5+pbRDab3Ltqbw9db07l6TGyj1efuxOOjbwUVFjvl1fZ6UyoNWg3Hrq2Gqj4HRAfWVsPmlptZuDeHkXEhLutq1VQWxufwxC9OHZSDORU85qaO98dj0GmaXBHbFKSUfLHZ2dz6YE4Fh/Iq61WZ9DHoeP3y5sUW2hJVlaQXm4gO8q4zfmCoeYAJRO33deHnpePyGl0YVZUsiM+m2qZw+YguLv3dN4bFrnDBuxuxOpyZZNufOsft5xfiL00nV/HjjkyqatQwv9ic3qCh78h6/3XhMfQnkV5kYtZ7G7ErKndN6cE/zjk1ZeqDa4fzv/VH6BXhx8ReTSumuuLjreSUmdFpRYvz8ltKWqEJu6KiqJLDhVVtdl5XIoQznrAtrZggHz3dwnxJya/EoNN02Dzy+rjjm12sTy4kxNfAiocmn1K/MK1fOM/N6s+RoqoTJDAa4rttR3lp8UGQkFFczVNtqKdfbVOotjmwKxKHIjHblDZ90LiKc/pH8NPOTADOHxRJebWd1KIqBnUOPO2zeDyG/iS2pRXjUFWsDpXf92bXaegjAow808wClxKTDYcq0WsF5WY7dXfTdA83jI9jR0YJVRYHT7ZBg+jWsiwhl8UJeVw/Lu6E3c9nN44itbCKLsE+LNibzQuLDoCEj64bwZQ+4a1q/9eWHCsYK6u2k5JfybCuJ+7whBBc1UwNloIqC4oqUVRJXnnbFoaF+Bp49Lw+fL/9KNeNi3OpOJ47KKiw8NaKZGJCvLlrcs9aV+bk3p1Y9+hUFCnxNWiZ8sYaLHaVEbHBfHPrmNPm+qoLj6E/ial9w3lzeTJ2h407G1lN2RWVlxcnkllq5rlZ/RtcpX947XDeXpHC2f3C27yxRbCvgW9vbTwIXWmx42vQtWuAOKfMzP0/7MXqUFlxMJ+EF86rnY9WI2p1ylclFWCxqwhgTVIBLy9OIqWgkmdm9edmF9Y9uIPrxsby5eZ0eob70j+64dS89cmFzFt/hIuGRDG3gT6kt07szpFCE9VWhacvaPuH+ckCfHVhdShISbsXCj48P57Nh4vQ67R0CfZh9tC/fOyRgc5Ms10ZpVgdKma7wva0EuatT+WVJUn0iwpg/p3jOnx/hZM5vWbbBoT7G9n21DTsijxh+2lXVH7dnYWfl57zBkTw/MIDrEsupKDSit2hUmm288Md4+od1xWl/e7khQUH+GprOt3CfPnjvol4Gxq/GcuqbSiqdGmxj6aJolN3TenBtrRijDotPcL9mL8rC1XC+6sPd3hD/8JFA3jy/L4YTtJZ33O0lD1Hy7hwSDRJeRW8sjiRpLwqFCnZkV7CuB5h9S4mAox6/nv18Lb6CM3m+EYhH183gql9G0/7tCsqeeVOETxXLj40wqmYJzjxejuewTGBDOsSxPb0Eu47uyfvr0lFlZBWZGJbWkltXczpgsfQ14EQAoPuxAvglSVJfLstA4FgZ0YXftvjDHwJQKcVHX672hjf7ziKKp26K/uzyxndrWFBsc2pRdz0+Q4k8MHVruvwExlo5KNrR7D8YD5Xj+5a7w0+vGsw+54/D3AW4byx7BBGvYazm2BAOgInFwllFJu46n9bUVX4bvtRiqqslFU7WzsKnA+99l4Jt4Y/9uXUSol8tSW9UUNvV1RmvbuRtCITI2KD+e62MS5zm7w5dwjvrz5MlxDvU9oTHkOv1fDtbX/tglMLq1h2IB+9VsOARnZhHZEmGXohRDpQCSiAQ0o5UggRAvwIxAHpwFwpZalw/jXeAc4HqoEbpZS7XT/1tiW71IzNoaLVCOyKiiolBq2gS4gPlw7vzHUuzhdvay4YFMWifTkE+ejpF9V4yfyS/Xm1fWR/25Pl0lZuU/uGN2nFd4zIQCPrH5tKTpkFo17D1iPFjI47vdQcS0w2BAKbolBYaSUy0FhjGCVXjerKhUOimy1H0ZGY3t/ZKERVnZ2pGiO71ExasQmborL1SDEWu9qkXWZTCPPz4vmLmids9tbcoSTlVRLia+BQXiUaIdqtor0lNGdFP1VKWXTcz08Aq6SUrwghnqj5+XFgJtCr5t8Y4MOar22KQ1G56YsdbEkt5o7J3Xn0vLpTCnPKzOxIL2Fir04NFpc8M6sfFRZn3u5jM/oya3A0KfmVzB7W+bTUbjn20DoWiHpz7hAeOa8PoX6GJpWkzxkRw8+7slCl5Jqx7S/96+zAZeb8dzegEYK5I7rwwuzWqxQ2xOL9OTz4YzzRQd78fOe4Ol1YiipZlZhPJ3+vU4KuxzO0SxA3nxXHhpQiHj2vD/2jAvhjX67ThdDA+zoqUkqsDrV2FzIiNphtTzkbhTTF1dclxIchMYHsyihlxoBIlxn5lqLRCPpHBzDr3Q0cKTJh0GpY99jUepuBdzSaVDBVs6IfebyhF0IcAqZIKXOFEFHAWillHyHExzXff3/ycfWN74qCqbWHCnh7ZQrT+0dwz9SeJGSXc/lHWzDbFafC3L/PP2XrV2V1MP7lVdhVSbC3nk1PnH3aRtWbw7KEXO79fg/eei2/3zOhxS3ebA61pvq3bW5CKSUrDuZTaXEwe2j0KVri3207yv8tOoDVodInwp9lD05qdLz8CiuhfoZG0+eOib1Z7AqvzBlMRICRc95ax+GCKow6Dc9fNICrRp8aLH1+QQI/7cxCIvnk+lGc1cR03NOZSoudi/67iYxiE/ed3YsHW9gkR0qJyaa4RD67qRwtrmZtcgGTe3c6JW1XSkmPpxajSjDqNfx614RGg+kVFjtSxW2u3aYWTDU1OVQCy4UQu4QQt9e8FnHMeNd8PbbX7gxkHvferJrX3Mrd3+5mb2YZ761OITG3gthQH/y8dHjrtYyKC6nTgJdU2bA4VMw2hbwKCzZFddl8tqQW896qFLJKq102pqv4ZGMadkU6KysT8lo8jkGnaVO/8cL4HB74YS9P/57AK0uSTvn/CwZF0TvCj2AfPU81IfPkvu/3MPG11Ux/a11t8/X6mLfhCCsO5rMuubD23NP6huOt1yKEYHg9q+6EnArMdgVVOkX1XEWpycb7aw6z/EDL/37uYmdGKfkVFlQJn29Ka/E4Qog2NfIWu8Ks9zbwrz8Ta0X5Tp7Po+f1wd+oY3r/CPo20vZxe1oJo15ayah/r2R1Ur47p94oTf0tTpBS5gghwoEVQohT77K/qGtJfMq2oeaBcTtA166t79sY4mvArjjzhwO99fgb9ax6ZDJHCk31Bk+6hHhz0/g4FsbncNuk7i5pxQbOoqubvtiOzaHy085MNjx+tkvGrQurQ+GjtUdwqCp3T+nZpC3upcM6E59ZjlYjmNSBM4FOJqu0Goeq4lAkGSXOB+jO9BLu+34PkYFGPr9x1Ck9UBti8f5cVAn5FVaS8ytP6FZ0MhH+Xui1GiSyNgXviZl9uWhoNGF+XvU2fn/+wv488MNeIgOMXDq89Xr/x7jzm13syihFrxV8cdNotzZS35hSxNIDuVw+okuDv6NjDIkJwluvRVElFwyuO9jZEbHanemUdkU6ezPXPPzv/HoXB3Iq+OfFA7hrSk/umtKzSeP9sS+nNo71884szu7rXo38hmiSoZdS5tR8LRBC/AaMBvKFEFHHuW4Kag7PghPqgWKAnDrGnAfMA6frpuUfwcnPd45nUXwOnfwNXPz+JlQp+ermMQxt4MIUQvDk+f140sVVhMfKqFUJFRb3Ktt9tPYIH6w9jJSSapvSpE5FV42JZWrfCIx6TbMaK7sTu6I26j65dmwce46WUW6280zNiv2lPxPJLbdQbLLx257sZgmKzRkew6+7s+kS4t1oU+5rx8YS4K2n2uZgXXIhfZ5Zwo3j4xq9dgbHBLHmkSlNnlNTKas+VoCnocxsd/n4xyiqsnLLlzuwOlR+3Z3NvufPbbT9XoivgY2Pn01hpZUuIR1DZ0hVJRIa1HkK9NHz/IUD+HpLBteM7Uqwr4HlB/LYnl5CtU3h+QUHajumNYWLh3Xmp52ZqJJmF8C5mkYNvRDCF9BIKStrvj8XeBFYCNwAvFLzdUHNWxYC9wohfsAZhC1vyD/vKiIDjdw2qTtP/LKPgpqWXp9sOMJbVwx196lPYWDnQB6a3pt1hwq5f1ovt57LrqhI6byI7Q24nqSUFJtshPgY0GhE7aq0I/D8ggS+3JLB8K5B/HD7uHrL5wO99Xxyw4m9ZkfEBpOcX4kqJf2bqQv++uVDeOaC/vgbGy8S02gEFw/rzOGCKv5v0UGsDpWP1x/hkfP6tEt5/LtXDedffx6kf3QA093YTUk9Loan1lxn9VFldaARTq0hb4O2w/RJTsgu54p5W1BV+OqW0YxqQMPm2rGxXHtcckHPcD+kBB+DttnCccO7BrP3uXNRpWz3AqumnD0C+K3Gx60DvpNSLhVC7AB+EkLcAhwFLq85fjHO1MrDONMrb3L5rBtgYq8wft+bDcCk3u3nlqivUvBIYRVLD+QxuXenWsGz1nDP1J41202VR8+ru8GElJJbvtzJ+uRC+kcF8Ovd41vcFNnVSCn5emsGAIm5lRzKq2zWDXXD+FiGdQmiR7hfixpAHB8kk1Ly2tIkViYW8OD0XnV2P4oOMhLorafK6qBbmC+6dkrh7BPpz1e3nJrMZlec7kKDVsOc4TGtTjEN9zfy7lXDWBSfw3VjY+t9qK1LLuS2r3aiEfDNLWNa3NjdHfyw4ygmq9MN8+Xm9AYN/clEBBj56LrhOBTZooLHk2NYezPLeOq3/fTs5Mfrlw92mbu4MRo19FLKI8ApUoBSymJgWh2vS+Ael8yuieSWmymosDI4JpALBkfTJ9IfVVJbLt9RcCgqF7+/CZNN4b1Vh9n61LQT0rOklHy//ShZpWZum9i9Sep83gZto+4ai11lTVIBEkjKrySr1Eycm5tiNBUhBJN6d2JLqlOsrHunps/r+20ZvLDoIELA97e1vs9AYm4ln29Ox2JXefDH+FpDb3Oo7M8uo2cnfwJ99Kx4aDKH8ioZHBPY4bK03lqRXBsArbI6TnFlJeZW8POuLM7uG86Enk3LADpvQCTnDYhs8JifdhzFVuOPXlCj0tpROLd/JPN3ZgHUWyBVFyUmG+e8tQ6T1cGswVEu6UP7xC/7SMqrJK3Q2TDmkmGui9s0xGlfGXsor5KL398EwFWju/Lchf3pGd6xDPwxHKrEbFec4lNCYrUrcJyhX5KQxz//SMSuqCTlVfLZjaMaGK3pGPUaJvfpxMaUIvpE+BET3DH8psf49IZRpBVVERPs06wsngXxzmCXRsCGlKJW55uH+RkQCIw6DVFBf7m2rv10W23/gTWPTCHQW99o5XB7UVRpxe6QCAGFNS7MY6iqZO7HW6i0OPhmawbrH5tabxC5uVw+sgsrEwsQwEUdTL53Uu9ObHjMKVbWnN4ECdnlWOwKVofKsgP5vOmCucSF+pJebEIi620o4w5Oe0O/N7MUicRiV1mXXAC4t0VgazDqtbxz5VA+3ZjOZcM7E37STeZM56qJ+NsbTvdrDkIIPr9xFIVVVsJ8vTpcxahWIxp8OMdnlpFWZGLGwMgTHgR3TOrB7owyvA1aZrkguyM8wMjv90xgV0Yp5w74a/W2K6MURZVI6ZQqGBzTeOZJe/HojD6Ume146TTcMflU1+HxcZyGYjrNZUqfcHY+c06bp0Q2lZPvteMpr7azIjGfITGBJzRSHxEbTEywNyn5Vdw60TX6SW9fOZSF8TnEhvg0y4XUWk77DlOlJhtzP95CdpmZNy8fwsxmbM06Gg5F5e2VKRwtqeaJmX2JboNOPR2d/VnlXP7xZgSCCT1DTwnGOhQVjRDNfnhJKckqNdPJ36vRXcQ7K5N5f20q43uE8sn1IztMfKMlbD1SzKcb05g1KIrZ7dgZqSMx8+31pBc703VXPzL5hFW/lLI2u6m5lFXbsCkq4f7uS3w4YzpMBdc0b/g7oNNqeKSegOrxZJeZ+W5rBsNjg+v0G9ocKg/8sIeEnHJeuHAAYX5exIX5njbl2seTUWJCIDDbFVLraALdUqP70E/x/Lk/l2AfPcsfnNzg7+aBc3rzQB19CU5HxnYPZWwjOfeqKvl+x1FKTDZuntAN3zpW6Iv35fLvJYmMigvhH+f0wq5Ieoa3rMK6vTlaUo3ZruCt15JXbjnB0Ash0GubvwPefbSUq2tE6l6dM4hLXFhD0RJOe0N/uuBQVD5cl0pRlY1/TOvVqjZo13+6jbQiEwZd3WXY65ILWZdcSLVN4a5vd6EVGox6DWsemdJh8uabyvT+EUztG86hvAr+fckgl427NCEPm0Ol0uLgQE4543uc/tIE29NK+HHHUWYP7dyqjLNfdmfxzz8OoqiStCITb809NUX5qd/2U2a2U1iZyx/7ctAKwfMX9ueqMe2ve9RcXrtsMK8vO8SkXp0arLtpDmsSnf0SAH7dk93uhv703YN2QFRVcvtXO+n+5J8893vCCf/3084s3l99mG+3ZvD07/tbdR6TzVlS71zpnlqQFRfqgyol3nqts7WbXcHiUDlc0HHaCFrsCovicziYU9HgcV46LR9cM5xVD09xafXndeNi0QiIDvKu9+ZWVXlKGXx7s+ZQAf2eXcL4l1eRU2aufd1iV7j+0238sjub277aSanJ1uJzmKwOpHQKslXWU/DXI9yv5vpyVipbHCorEgvqPLa92HO0lCX7c3E0Eou4YHA0ax+dyosXD3RZFtWsIdH4eekwaDUN9kcw2xTawn1+Rq/oFVWSV2EhMsB4QsVcicnGH/tyGNS5ecqBR0uqWZdciCrh620ZPHVBP7dowfzvupG8syqZMd1D6tRY6RXhz+/3TOBwQRXJ+ZV8sCaVQdGBHSqIePe3u9mSWoxE8tvdE1qUA98anjq/Hw+e0xujXlPnzV1UZWXWuxsprLTy1AV9ueWs7i06T3GVFYNOg7/xxDTaFQfzKTPbuWRY52b5f99ZmYLZrmKvtPLHvpwm95RtDleN6Up6cTXFJivPXFB3csNXN49mVVIB/l5aHvt5P2a7wl1TXD+XlrL1SDE3fr4dgeCiIVG8elnbNovvE+nP3uemo0hZb678S38c5LNNafTo5MfCe89yq0LnGWvoVVVy6QebOJhbweCYIH6+c1ztDX/tJ9tILaxCCFjywCS6NTHnPDLQSJifFyUmGz3CffE6rsJz7sgYik3WWtdNaxgUE3hKUPJk+kYG0DfSaTwfmt6437+tSc6vxGxX8DFoySg2tbmhBxq8sTYdLqLcbEeRkk83pLXI0P++J5vHft6HViP46Y5xtYVgi/bl8vjP+5BIDmSX83+zBzZ5zPMGRJCU59wFjen21w7HqNfy9a1j+HFHJhcNiW6Va9BLp+WFRvTafb10XDTEmUa545n203Cpj9TCKqQEi0PhYK7rxOSag06radDAfrMtA1U6Y27xWWWNxk5aNRe3jdzBKayyciCnAocq2ZtZRmm1vVaPPrfcjNWh4q3XUlhpbbKhN+q1LH9wEocLqugb5X/CSlGn1XDf2e6VQ2grDuSU8+22o0zrG97iIpKXLx3E078l0D8qoF3FnupjVFwIBp0GRZVcMrxl2Sk/7czEpqgIBVYl5tca+pwyc604W2apuZFRTuSuKT2Z1i+CAKP+FBmLUXEhbZqy5y6sDoUP1qTiUFXundqrRSvd2UM7sywhj8xSMy+6uS9BS5kxIJLFCXkEGPWNyh23ltM+vbKlqKrkmk+2sS2tmIm9OvHFTaNqDfPGlCJeXpLIuB6hPH1+vw5X/dgUyqvtzP14C0dLqnltzmAudFERi5SSIf+3nAqLAy+dhpUPTT6hj6mU8pR+u6crJquDMrOdzi1Mcz2m+2/QafjlrvG1O6xKi51H5sdTWm3n9csGn6J7frrw/urDvLMqhdHdQvj8plEu0/x5e2UyH6xNBSm5flwcz5xU+W1zqOi14rS8L4+nOSm+9XHGpFe2FI1G8N1tY6iwOAgw6k64aM7qFcafvZoud9sRWZmYX5s29vryQy4z9OBU5TzG8euEcrOdi/67kcySah6f0bfOgp22oLDSyvKDeYyMDWlUlbIhfL10daYWNpXzBkYR/3wntBpxgp/W36jn4+savTc7PO+sSsGmqOw+Wsq+rHJGxLqmE5ZDkVAjoOZQTwykvrMymbdXpdA9zJeF957Vqr9PS5FSsvxgPnZF5fyBUS0uQBRC1Nvs3dWcsYYenL/ok/OnNx8u4vlFBxgaE8TLlw46bYtjjumGe+u1TOnjOnE3IQTf3DqGzzelMb1/xAkKhVtSiymstKJKmLf+SJsZ+gqLnR+2H6VriC8zBkYy58PN5FdY0GoEax+d4taClcY4WbXQZHXwjx/3kltm5vXLh7RLbMJVjIoLZk9mGV46DT2aoVHUGPdM7YnVoeBQJQ+fe2J86ZONaciaJvY70kuY0qdtmsGvPJhPamEVV47qysL4HP69OBGQpBWauM/NCrWu4Iw29HXx8Px4csstZJeamTkoskX+43KznY/XpRLu78X14+LaRXKgZ7gfax+dQl65hcHNlFdtjKFdgnjnymGnvD6saxB6rQYvXds2nHjg+z1sPFyETqPB12uEs1uYQ8Wo11BisrWroT+ZX3ZnsT65EKtD5dnfE/j5rvEtGuePfTnsPVrGDePj2mxVeDJf3DyafVll9Ojk59L6DG+DlqfryfaZMSCShfE5GPVaBnV27XVdH1uPFHPf93twqCrrkwvpFxWArUYePL341CK+jojH0J9EbKgPpdU2VClbLEHw1K/7WXYgD51W4GfUc9mIti2WcCgqG1KKiAn2blJHIFcREWBk0xNnU1RpJdbNWuSqKrnv+z2sTirAz6jDrkh0GkmJycZblw/hnVUpnDsggj4dTMG0a4gPQjh3Wj1aWEkan1nGI/PjsTlU1iYXsPKhKa6dZBNIqVFBndgrrE13va9dNpi7pvQgIsDodrfNuuRC7vtuNz4GHRJn7KnIZOPOKT1IzK3AXseOo6PiMfQn8ckNo1i8P5c+Ef61wbPmYrEfK4IQtdKtbcljP+9j6YE8VCn5+c7xDGyjlQ+An5euTUStjhRVsSox39nz164woWcovcL9uWBQFDqthllDOpaC4jGm9AnnsxtGkV9p4YI69O6bgk1REQhUCTZH2ydTJGSXc9lHm9EIwcyBUbw5t+1y1IUQLW5m31xeX5pEhcWB2a4wMjYYjUbw7Kz+hPl58a0LZLHbEo+hPwk/Lx1zR3Zp/MAGeHnOIF5dkkR4gJHLR7Z96fPerDKqbQreeg2H8irb1NC3FVGB3vgZdWhsCt3CfPn21tPnxhvfRB34+hgVF8LjM/qwI6OU+9shZTcprxIBVNsU9maWtvn524qJvTvV6CtJnpjZr013x67mjE2v/DuzIaWQR+bH0z3Mj09uGNkumQltQVm1jaS8SoZ2CXJLBbKHujFZHdzy5Q7Siky8cfmQFnVeOh2QUrIns4wwX68O0xbxZJqaXukx9B46HKUmG/9ZmUyIr4F7p/Y8bTOfPHRc5u/MZFtaCXdO7t5hGxU1BU8e/d+Q5PxKDuZUML1/hMtX6SarA2+9tkM0JXlmQQLLEvLQagRhfl4nNGv24D7MNoXlB/PoHeHv8rRPu6KiqLJD7Lz2ZZXx7IIELHaVrUeK2fj42e09Jbdzxhj6vHILAd66du/G3lIyik3M/q+zZeI3WzNanJZXF28sO8QHaw8TE+zDn/efdYIAV3tw7FkjgNOl+NFkdVBldbisNV97cNtXO9mV4ezY9sd9Z7lspXu4oIpLPtiExa7w7pXD2r05kEDUfIXT5PJqNWfEnvjtlclMfG01415eTXZZ87RFOgpZpWaEoKYBh2vlhr/ako4qnYqNOzPaP7j20uxBXD8ulvum9eKKVgbGj6Gqksd/jmfSa2tYmpDrkjGPkVFsYsy/VzHx1dV8tC7VpWO3JSkFTqE5jRBk1HRccgXLDuRhsjqwK5LPahqXtyeDYgJ5+ZJBXDGqC1/cPNpl425MKWLK62u459vd7ZJt1xBnhKH/eVcWdkVic6hsO1Lc3tM5hdxyM8/+nsDXW9Lr1aYe2z2UmQMj6Rriw6tzBrv0/BcOicag1eBr0DG0A0gZB/roee7CAdzTDP+8oko2pxaRVVq3gdqRXsKifbkcLanmsZ/3uXK6bDpcjENRsSmS+TszXTq2K5BS8sWmNJ5bkEB+haXe416dM5jYUB+m9QtvVeOSk5ncuxNeOi0GrYbLXfTgbi2XDI/hlTmD6dGMVM30IhPb00rqvUcf/2Uf6cXVrD5UwOqkjqXN32Q/hhBCC+wEsqWUs4QQ3YAfgBBgN3CdlNImhPACvgJGAMXAFVLKdJfPvBncPCGOfy1Ows9Lx1m9Ol4noXu+3c3ezDK8dFpign2Y2vfUsm6tRvBmHZ1+XMFLFw/k7qk9CfU1tIkP9fNNaWxJLeb+ab1clvr5yPy9LDuQj5Twx/1nnXIDRwd5I6WzUKmpaqRNZUqfTryxXIddtXPLWa5pIu1KViYW8OrSQ1gdCom5Fcy/s26335Q+4ax71PWSAgM7B7Lt6WlY7EqbVCmn5Ffy5vJkBncJ5K7JPVwifrYvq4y5H29BILhqdFeeu/DUyt3eEX6UmGxIKYkL61hZOs1xWD8AJALHojSvAv+RUv4ghPgIuAX4sOZrqZSypxDiyprjrnDhnJvNzWd158rRXfHSaU9oMOIKpJQUVloJ9jW0WL3veDL76aIAACAASURBVJEwRW37LCghRIsVGpvL3swyXl16CItdIT6rjG1PneOScbcdKampHdCSmFtxiqHvEuLDwnsnkJBTTpivF5d9uJmRccE8PqNvqw1BdJA325+ahk1R3RIDqrI6UFTZ4p6/6nEr0Ha4vAAIMOoJaKPYzx3f7OJIoYl1yYUM6hzokvTP+KzyWn37LUeK6jzmw2tHsOxAHjHB3sxbf4T8Cgv/vmRQh1AnbZJlEkLEABcAn9T8LICzgZ9rDvkSuLjm+9k1P1Pz/9NEB9AT9THoXG7kAR6ZH8+EV1cz7c11mKx1t11rjP9ePYzLR3bh4XN7M61f01ZUS/bncvYba3lh4YE2aUXmKox6DSDR1MgAuIqnzu9HgLeO/tEBTK1H6KpXhD+XDIvhsV/2sTOjlK+2ZLA51TWuPJ1W4xYjv/toKSNfWsGol1ay4mB+i8Y4t38ED03vzeUju/DeVadqFNVFcZWVq/+3ldn/3UjGaaLncgwfgxZnP2/psmts1qAoeob7Eeyj58mZ/eo8xqjXMntoZxKyK/hzXy6bDxfz9G8JdR7b1jT1ynwbeAw4FoYPBcqklMcsWxZwrDtDZyATQErpEEKU1xx/wmNQCHE7cDtA165dWzr/dmdhfI5TA6PKSlJeBSNim9/4ISb4L7+7ojr9qUWVVu6c0qPeVdzD8+Optinkllu4eFhnlzU1djd9IwP471XD2ZFe4tK0yVlDopssexDm50VRlRVVSkJ8DfxnRTLfbM3gshExPHl+3Tdxe7F4f25tk+kfd2QyvX/zRfaEENw26a8OWXszy/h1dxbnD4qqt6vR55vS2ZZWgqpKXl2SxAfXjmjZB2gHPrl+FF9uTmdA5wBGuqgRS7CvgT/vb5p0eSd/LzRCYNBpiAw0kpRXwZ1f78LHoOPTG0cSFdg2u+fjadTQCyFmAQVSyl1CiCnHXq7jUNmE//vrBSnnAfPAWTDVpNl2QOYMj2H+riwiA4z0j2q9v/mXXVm8viyppvtQNf+9enidx3UJ9iGjxLnSCvc3sCW1GJ1WnBYdhs7pH8E5/SNQVMnbK5PJKK7mkfP6tJn76IubRvHbnmz6RwcQHeTNf9ccRlGdGSG3nNWN8A6UInnh4Gi+3XoURUquGdP6BZHVoXDVvK2Y7Qo/7shk21PT6lSe7BHui0ErQKuhZ7g/OWVm9mWVM6FnaLun3zZGZKCRx2f2BWBnegmfbkxjxoBIZg9rWaew5jJzYCTgzGKbO7ILD/ywh/Ti/2fvvMOjKtM+fL9TMqmkEyCNEnrvTXq3995FsRfs7qqrq2tZXd39LNgrKoIoKIIgvUMCBAghkJDee5t+zvv9MSEmkJ5JMkHv6+IiTH0znHnOe57y+xnRCPhyV2r12tqTpuzoJwMXCyHOB9xx5OjfBvyEELqqXX0YkFX1+AwgHMgQQugAX6DI6St3EV69YhhPzh9AFw+9U1JDVkUFh++C4+d6WLZoAuvjchkR4cf6Y7m8tjYBcBRWr2hntcyWsuZINh9sPYXFrpBVYmLZoom17pdS8sb6BA6mlfDUggFOMzcP9DawcIpjh2tXVLr6GCg12fDQa/H1dK0gNjzcj4PPzUFRpVOG5KT8I2fv+Lnux106IhQ/TzdMVoUJvQKY9sYWFFUS5u/B+kemtXod7YGUkps/3YfRqrDpeB6jIv3PknQ+kFbMv39LYEKvAB6c1dcphVshBOfXmBUYGeHPthMFSKTTJcObSqNHjpTyaeBpgKod/WNSyhuEEMuBK3F03twCrKp6yuqqf++uun+T7ARJ5OiUImJSi7lkROhZXpyN0Roj5jO5Zmw42SUm8issPD6v/jO/n6cbV491tKq9vyUJs01BCEd3QEsCfYXFziPLDpFfbuGNq4a1y1i4W1XxWghRy0j9NDsSC/h0Zwomq8J9Sw+wvQ0mGHVaDb8+OIW9yUWM6elfywnKmZQabSyPSSeqq3ezzTKc2Qnlrtfy6a1jWbonlctHhVX7JJ+JEKK61nEsqwybomK2qSTlVyKlbFFAXLY/jY+3J3Pl6LB2M6VxNEgoCKhzI3bPVzHklls4lFbCxD5BjOvl/CviRVN7MyzUFw83LSMjnOPC1Vxas0V4EvhOCPEScBD4pOr2T4CvhBCJOHby17ZuiW1PamElN36yF7si+W5/Opsfm95ha9FrNTw+v3mXdvfPjOJwRgk6jaZ6p9pclu1PZ2tCPlZF5blVcXzjRBnW2PQSfj6cxflDuzOqxoE+b3AIz144kJRCI4um9ia5oBK7otIn2JunVx7m9/hc7IqKTiOcamxxJv5ebsyvutxuK+7+Oobo1CK0GsHSheNbVMtxFpOjgpjcDAXNgd19uGR4DzYez+OBmS3b9ZptCn/78Sh2VfLm+hMt2lDVh9Fq5+Ntp/B213PzxMjq2QshBMsWTeC7fenMGNCVLh56YlKLGNzDlwOpxTzxw2EqLHa0GoGk5V1NjSGEaLViaWtpVqCXUm4BtlT9fAo4a6xMSmkGrnLC2tqNUpMNgcCuqhRWWJr0nOSCSt7ZdJIR4X7cNLFn2y6wEfoEe7Px0emteo1wfw+0GoGHRuPUPnOzTeHaqpzw13tSif77nGq9eiEE1493FGQ3xudy39IDIOCuKb1ZHZuNyaag1wgWz+3Xaunojia/wlJljqIhv9za6OMVVfLelkSySsw8Mqdvh7pkCSF47crWac7rtRp8PfRUWOzotRq83Z3XofTSmnhWRGegcZQUuGXSH7MMA7p14R8XD8ZiV5jxxhZKjDbCAzyxKyoZxSbcdRrmDw7hunGRrfIXdnU6p/CLkxka6ss90/uw9UQ+j87p16Tn3PllNEl5Ffx6JIe+IT71di90FuYO7saSm0ZTUG7hIieadiiqrJ4NUFVQlLqzeNtPFmCuGhuPyypFo3G0yfUM9OLe6VFOW09H8fY1I/jnL8cY2L1LkzpnfjqYybubE7HZVbJLTXx+m/NG9TsCrUbw8wPnsel4HpOjgpxqTmO0KChSghAYrUqdj8krs1BQYcVqVzmZW86Cod3JLjWjSsmiaX2cVv9xVf4K9Dh2LA/O6suDjZj8Hs0sZW9yEQuGdEMrRLXgVlv053cE05w49n4aL4OOD24azdK9aVwzNrzeYueNEyL49Ug2VkXlwVn9+IeXG4czSpnaz/UmmVvCkFDfs4rNZ2K02vkhJoOwAE+0mirpLSHQdvwYilPo4efRJkqkz100CK0GfNz13Da57snkMH8P5g4K4be4HK4fF8HfLxzEpuN5hPt7MqhH5zVobyp/6dE3kbxyM9Ne34JdVQnyNvD9ool8sC2J4WF+2BSVdzYnsmBId/5+wUCnVO7/4s/H3V/FsDkhD40QLLlpFCdzK8gqMXHF6DCeXnkEKeG9G0Z1mBn4X7geTdWj/1OImoGj4PrUD4dZtj+tRc8vM9lRpcMguLDSSpi/By9dOpQrRoXx7Ko4skrMfL0n1enKks0hJrWI8S//zvy3t5FXXr94lbMoM9vYeiKfUpOtzd/L1VFUyftbknh+1dEm13nOJKvUhMWuApL8cisLp/TmuYsG883eNI5mlhKXVco7mxOdu/BmYLEr3PLpPka8uJ4fYjLa/P2klMSkFnM8p6zN3+tc508T6Bd+Ec2y/en8Y/Ux9qc0v60/qqs3D83uy7AwX965bmT1rl0ICPXzwEOvRa/VEORtcPbSm8zrvyWQW24hMa+ClQcy2/S97IrKgre3c8/XMcx/exu2Bnr+TVal1TIN721OJOqZX7lqyS4s9rrzsB3JTwcz+d/GEyzdm9ZidczXrxzG2J7+XDisBxfXqJMM7N4Fg06LQadlYAcWDPecKmJ/ShElRhsvrTnW5u/30fZT3PjxXi59dyebjtcv/2C1qw0ef00hpaCScS//zpDnf2Nf8rk39vOnydHLGj8VVlj4cncKE3oH0i+k6V+ce6dHnVUYFEKw6r7JbD2Rz+hI/2a1AUop+d/Gk2xOyGfxnH6tloYd3yuAw+mljsGMNjYELzfbySkzo6gO+ecSo41gn7NPcg9+e5CfY7MY29Ofb++a2OJ6xv9tSsSuSuKyyjiYVuKSxW9Z9UeVkp9jHfODFwzt3mTXrgHdutSpLHnD+AjCAzyRUja7jnI0s5R/rI5jYHcfnr9ocKtsGfsEO7qxPN207SK5sedUUZU+PhxILWbmgLOL2HtPFXLLZ/sQCL69a0KL17UiJoP8cgsSeHdzIuN6de7i95n8aQL9xzeP4f2tSQwP8+X51XEUG23oNIIdT86sd2ikqfh7uXFpC8arj2aW8f7WU5htCvcuPcDRF+ZV32dXVL7bn46iSq4bF4GbToOUkqT8CgK9DHUOaT0yux+T+wTh5+nm9FaxXYkFPLvqKENCfXnjquH4e7lx66SeLNufzhWjQusM8mabwuqqgBebUUpqYSW9m6H/XZOJfQLZnVSIQadp1sm5vbh0ZCi5ZWaySk0EeRmqd/VZJaZWDwcJIVpcKH9k2SFO5lUQl1XGxD5BtSY2D6WXsDUhnwuGOQS7AIoqrRRVWugT7H1WrSnM35MNi6eRlFfh9BNtpcXOg98eJKPExBtXDmdomC8Pz+5LXFYpXgYd142vu4j79d7Uai2g5dHpLQ70k/oE8vH2UwAt0hNydf40gb5nkBevXTEMRZU8tyoOuyoROg2lJlurA31L8fPUAxK9VhDkXXsNH+9I5u0NJ5BAfrmFx+b159W1x/lidwpajeCXB6ac1e8uhGB8M76AP8dmsT+liNsm96p+LaPVzqH0EgZ3963VIfPED4fJKDaRXWpm0/E85g3uxrMXDuLZC8/W5T6NQadhYu9AYtKKCfP3IMy/5UXED28aTVxWGZGBnm06PNVStBrBvTMcV3vP/nQUa1V6Ka3IeU5NLaGbrzuphUYkkq41TsbFlVau/XA3VrvKJztOcfC5uaQUVnLx/+1AUSW3n9eLJ+oY3Av182iyJlFGsZGPtyczNNS31rR2XFYpOo2m1mbkp0OZ7Ex0tNg+u+ooP903mWFhfo3KWF8yPJTf4nIRwIIhLbconBQVxIbF0zDbFPq64EaitfxpAv1ptBrBW1eP4J0tiVw0rIfTTSiaQ3iAJ9/cOYEDqcVn9a4XV1qxV/WfF1U6BmzWHs3BbFPx0GuISS1u8tr3pxTx8fZTzB/cjctGOb5wRzNLeXxFLBabypaEfLY+Ph27onLJOzvJLDHhbdCx7YkZ1eP3fYK9KKywokpJeBMDthCCrxeOJ73ISA8/D9zqkDloKjqthuE1dmt55WaiU4qZ2DvQqRIUzuCBWVGkFFaiSslDjbTstjXv3jCKH2Iy6BPsXUvJ0WxXUKu0bkw2BUWVRKcUoUiJ2a6y9mhOnYG+Liotdl5dexxVSp5cMKBad37hF9GcyC3HoNMSEejJiHA/Vh7I5PnVDunet64eUe0f2zPQC6qkq/t2bfpV3+xBIex8ciYa4dAwag01u5lUVbLtZD7+nm61jrvOyjkT6HclFpBTZubCYT0aDSgXjejBRSOcNxTUGkZF+NeSBTjNfTOjyC2zYFdVHpvXH4AHZkbx1MojBPkYmNHfcSkvpaSgwkqgl1uduWApJbdUCTttSchndGQAEYGeKKpE4MgpW+wK417eSFGlBVU6blNUSW6Zudo0YcmNY1h7NJuort7N6jvWagQ9nXwyNdsU5r+1HbNdwddDz44nZ7b5LENumZmN8XlM6B3QaPqpq487X90xvk3X01S61NNb3t3Xg5cuHcKPBzK5c2ov3HQaZg0M4f82JZJdauaBmX/UosrNNjRC1Cuq9s6mRJbtT0MCeq3gHxcPAcCuSk7X4JdsTWJjfB4BnnrMNhUB7D5VWB3oJ0cF8dUd48kqMdVKLzWFutKGreX13xKqvJQlS24c3Wx9Ilej0wf6wgoLr687zo+HstAKwe6kQv59VevGtV2BLu563r62tnXgVWPCuWJUWHVAl1Jy2+f72XGygEHdu7Dy3kl1FttqCjvpHI4MDA/349kLB7HnVBFhAR58sj0ZRYJ/1Rdx/pAQImrscDzctFw+yjVUMUuMNsotNmyKxGJXMdkUp05a1kRKyZrD2Ty18gh2RUWrEex6apbLqVy2hKvHhNeSlgjyNrDjyZmoqqw+xrYk5HHXlzFoBHy9cHyd+u4GvcaRz5e1Bdg+uGk072xKZGhoF178JR6ACqudAC833PUabpnUs9bruJLE9uGMEoxWBZ1GcDyn/K9A39Hc9vl+jmaWVsutJhd0Ljec5lJz126yKWxNyEcCx3PLySg2nbV7FkLw/aKJfB+dzvT+wfSokV+9fnwk14+P5GRuOZ/vTMGg03Dn1N6NSg6kFxkpNdmc5vfaXLr5unP75F6sPJDJLZN6tlmQB1h3NIfHlsdWyzMYquo650Kgr4+ax9j30enVctmrDmXVGejvnR6FQadBUWUtUb0+wd68dY1js7LpeB77U4oJ9jGw4ZFpeLjVr8hptikcySxlQDefDtO+f3rBQO775gCBXm5c1Ulkvxui0wf6okorqgSNgIgAT/556ZCOXlK74aHXMq1/MDtOFjAgxIcw/7qLZP27+TRYNO0b4sOup2ZSZrITEdhw/j0mtYgbPt6LQHD/zCjum9ExOjRPnz+wTjeovHIz13+0l8IKC+/eMIpJfVonoVBYaa1uzfXQa7hnep9GP6NziavHhLMxPg8BXFJPutNNp+GeRjYHX9w+nuSCCsL8PRuUXZZScsk7O0kvNuLroWfzY9PbxbD+TIaG+bLtiRl13vfa2ni+2J3KvMEh/OfqEZ1iEr7TB/p3rh/FK7/GMzLCnyfn9+8UH/qZxGeXcSyrjLmDQ5q1gxFC8NmtYxvM0TcVP0+3JnWzRKcUY1ckdlVlU3xehwX6+lh9KIvUwkpsiuSN3xJYeW/rAv2Vo8M4kllKVomJly4d4hJGz82l0mLnt7gc+oX4NPsqbHr/rkT/fXaDOfqmoNWIJnkcmGwKJ/PKUaUjx59XZnGpE6vZprBk2ymkhDVHcnh4trFTHBOdPtCPCPdrVCzKlUkpqOTy93YBkm/2pfHDPWcPzDSEEKJNilH1ccmIUJbuTaPYaGXx3KYpfbYnI8L90GoEOo2G8/q2XhDNXa+t9vPtrNz5ZTQH0ooBWH3/ec2eQ2jP9Imnm45bJvZk6b405g0OITyg/f1VG8Kg0xAV7E1miQkvg44QF7KdbIhOH+ibyq9HsjmWVcbNkyKxKZJKi90lBm+ySkwIAUar2inqC9183eu9pHUFxvQMYO1DUyk2WhnZjm1x6UVGvtuXxpheAUzsHcjxnHL6hXjj6dbxX7FT+ZWYbSqebloyio0ucdw3xPMXD+b5iwd39DLqRAjBqvsncyithME9fDskrdQSOv4obAf2JRex+PtD2OySdXE5ZBQ7hlgen9efO85rmSOTsxjfO5ALh3Vnf0oxf7/g7JxzQ1jtKu9sOkm5xc7Ds/u12iEnq8TETZ/spcJi56Obx3RKjW6zTSGtyEj/EJ92TePd8PFeMoqN6HecoruvB7llFoJ9DPy+eFqr5gecwb+vGsbzq+IYHu7L1L7Nm7DdmVjAygMZXDE6rNX1DoAXVsexIiaDq8eGN1g3cmVSCoy46TR08eg84bPzrLQVVFrtCCFQpEpRpcN8QJWwPi63wwO9ViN4vYXuPS/+EsfSvWkIHNozb7SyrfTbfWkkF1SiSnhrwwk+64RmF7d8to8jGaVohGDTY9NqOTNZ7SobjuUSHuDh9JOY0Wqv7vxKKzKiSsguNVFQYanV6dQRTOkbzKYW2GNmV534VQk/H87m4LNzWpWnL6iw8NWeVOyq5ItdKdw3I6rDptJbyqbjudy79AACwUOz+3L3GfIWRzNLSSmsZM6gkDbzH24J57x6ZUGFhTGR/twzrQ9zBoXw32tG0LWLO55u2kaNRlyBz3cmc9H/bWfVwdpqlFJKvtuXjqyabqy02Fv9XqMi/HHTafDQa5nQx/VEw5rCkYxSjFYFVUpSCmrLDzyxIpbF3x/i8vd2sfVEvlPez2xTyCk18/EtY5k1oCtPzh/IVWPC0WoE8wZ3o7uTfFHbiuSCSq79YDcPfXcQ0xnuTB9uO1V98lIUSWsvkHw99AT7GPB009K1i4EuTrQTbC8OppVgrZrd2JdcWOu+IxmlXPH+Th5ZdohbPt3XQSusm873STeDb/em8vzqY+i0gh/vnVwd2Pc8PauDV9Y0ckrN/OvX41gVlUeXxzJvSLdaOUFvg5YSkx2tgEfn9G/1+80Y0JWf7ptMpUVBK+CtDQnMG9ydL3Ylsye5iL+dP5C5g9vWRLu1/O38gbz+WwJje/ozKqL2rv1QekmV3js8t+ooWx9vXa2hsMLCvLe3UWqycdOEnnxy69jq+zpLAffvPx1hT3IRBp2GkeF+3FpjijbAyw29RqBIycXDe7S63qDXalj38FQOpZfQL8Sbj3ckE+jlRkgXA8+vPsbQUF/evHp41YCfa3LduAjWHs2hwuxIl9bkVEEFVsUxDbz3VBGJeeVN6jRqD87pQL8sOgOroqJKwZaEvE5n/utp0KLTCqR0tLbV/AIIIVhxz2R+PJjJlL5BRIW0TBXyTAZ060Kp0caEVzZitil8sO0UQghMVoUnfjjs8oH+hgmR3FCPXd2NEyJ5eU08EsdOvLUcSHNMT9oUyY8HM3juos6Xc+7h64FBp0EjBN3OuPq4e3ofvAw6VCm5eWJPp7yfr4eeaf2CeWTZQX45nINOIzDoNJSYbOSWmdmakM9sF1aP7OHnwe+Lp9V537zB3dBrNFgVFTedhrwyy1+Bvj24bVJPHlsRi7te2ymlR7u46/nx3slsP5nP3EHdztJzierqzePzWr+TPxOL4hC5kjjkkvVaLR56TYcKwNVk8/E8lu5N46oxYcxrxonn9sm9SC8yEpNWzLMXtD4oj+sZgJ+nHotN5aY28EJtD/556RBGRPgR5G1g7hnfEb1Ww+3n1e3B2lpKjDYUVUUjNAR6u2GxO9JtrmCTWFRp5ZVf4/E0aHl6wcAmd9a467V8fvtY/vVrPGN7BriUZ0KjnrFCCHdgG2DAcWJYIaV8XgjRC/gOCAAOADdJKa1CCAPwJTAaKASukVKmNPQebekZa7Ta0Wk0Hd750BpKTQ7t/NYUwprLjwcyWHEgg9sm9SI8wJO4rFLmDGreQFdbUGmxM/KfG7DaVdy0Gvb/bXaHyhEoqsRotXf459IabIpKsdFKsLeh3TqVskpMvPBzHF193Fk8ty9bEwqI6urdYbIaNXlk2SF+js1CIwQPz+nbqCRIR9JUz9imRA4LMFNKWSGE0AM7hBBrgcXAW1LK74QQS4A7gPer/i6WUkYJIa4FXgOuafFv0koayysmF1Ty8HcH8fXQ87/rRrqc1vm6o9k8+O0htBrBd3dNaDfJ1MtGhVVLGgMuk/bSagTaqmCk0Tj+dPR6GgryUkr+sTqOHYkFPLVgAHMGuVbqq8JiZ8Hb28guNXPl6DBebafaQg8/Dz646Y/41BLjnrbCy02LRghElWzyuUCjXxPp4LTjtb7qjwRmAiuqbv8CuLTq50uq/k3V/bOEC+sSvLzmGIczStmVVMiXu1I7ejln8e0+h6iUyaaw7mhOq1+v0mLnzfUJfLA1CXsrfTY7Ane9lu/umsDC83qxdOEEl99Jx6QW8310Bkn5lSz+Prajl3MWcZmlFFZ5H/x40Dk+wxuO5fLC6jiS8isaf7AL8swFA7l/ZhSPz+vfaVNyZ9KkXIAQQgvEAFHAu0ASUCKlPN3TlwGcPiWHAukAUkq7EKIUCAQKznjNu4C7ACIiIlr3W9SBqjrawRo7x0R19WZnoqNNqmewa+Sga3LD+Ah2JRWg12qardNdFy//Gs/y6HRUVbL6UBavXDG00w1GDQ/3a/GVzepDmTzz41H6BHux9M4JrVK+VFTZqA7+6RF5d72myYYt7cmQUF+CfQxkFJu40gkqjYl5FTzw7QHMNpVv96Xx8Jy+LJrap1NpUHm66Vrcel1UaeW6D/eQVWrif9eOZMYA15A3btJRLqVUgBFCCD/gR6CuEc7Tyf66/kfPKgRIKT8EPgRHjr5Jq20i+1OKuPmTfei0gmV3TWzQKOPxeQMY3MMXH3ddh2lOq6rkzfUJxGaU8tSCAbXylHMHd+Pgc3PRaYRTxq0tNgVVlSgS4rLLuOXTfRx8bm6rX7ez8Nq6BCosdk7mVbD5eN5Zzl7gMGJZeySHMH+POmV5rXaV6z7aTUxqCQun9OLvDRR2wwM8+eGeSRzJLGH+4NafqFtKTGoRb6w/wXlRQdw7/Y/A62XQsXHxNMrNdqc4ddnVP64SzXaV//6eSJ9gn07ZDNESfj2STUphJRa7yuvrjtcb6A+mFZNcUMn5Q7u3i4xCs7YzUsoSIcQWYALgJ4TQVe3qw4CsqodlAOFAhhBCB/gCRc5bcr1rY82RbIqNNnaczMdkU8AGjy+PRZGSJ+cPqPND12pEnV/29mTryXw+25WC0apw/zcH2HJGf7cz9dafvXAQZpvCurhcFFXWaVRyLjOpTyBrjmQDMLieDcBjy2P5/VgeEsmXt49nXC9HsE/Kr+D3Y7l09/XgWFY5AJ9uT2ZPUiEDu3fhlcuH1vl5DurRpVmuXG3Boq9iKKiwciithAm9Axkd+YermU6rcZod44BuXXjh4iG8ujaeUpMNcLhO/VkYEe5XnduvT1QvNr2E6z7ag8BxYvj4lrF1Ps6ZNBpBhBDBgK0qyHsAs3EUWDcDV+LovLkFWFX1lNVV/95ddf8m2VhrjxNYHZvFUz8cQZWSMZH+GHQaVCk5mV+B1a7y4HcHOfKPedWPN9sUjmWX0T/Ep127WerCz0OPKiU6jcC/jYvBfp5uvHvDaDYcy2X7yfxzJgcJsOpQJidyy7l1Ui+CfQykFxlZ9FUM4HA7Cg/w5LUrhnHN2HBC/T3o7lu3NEFiXiUmm4K7XkNqYSXjegVgSakfvgAAIABJREFUtatc+u5OTFYFvdZRgJU47BiPZpWRlF/JrIFdmV/DoDoxrxy9VuMSMra+HnqKK21IJL5trNFyzdhwpvcP5oOtp+gX4s20fs3T13FVUgoq+W5/GuN7BzKjf1eklLzw8zHWHc3h3hl9uHliT4aE+rLhkWnklVvOGtg7TVqREYHAZFM4ld8+QoZN+R/vDnxRlafXAN9LKX8RQhwDvhNCvAQcBD6pevwnwFdCiEQcO/lr22DdZ5FfbkFRVWyKxKDXsvHRaeSVWbjh470YdJpao+iq6jA3SCsyEujtxqZHpzer/VJK6dSc48gIf967YRTx2eVcOza88Sc4gTmDQpp8OZ1ZYuJ/G08S1dWbhef16tB8a7nZRnRKMUPDfAmqYQa9K7GAp344jNUu2XOqiB/umcQ7mxOJzy5DCHhvSxKvXD4UjUbUmY6pyb8uG8JTPxyhZ5Bn9dWeTVExWRXsVbWflfdMotKq8NKaY+xPLkIia504lken8+xPDhPs928c3axcrbOPL4ClCyfww4EMRoT7tcsQT0gX9yYPkEkp+WRHMifzKnhwVl9CO1gb6EBaMVohzqoDXf/RHrJLzXy+M4VfH5qCKiXf7kvDYlf5x+o4bhgfiVYjCA/wbHAeYO7gEH6L60pCTjn/unxoW/86QBMCvZTyMDCyjttPAWepXkkpzcBVTlldM7h+fARHqzoIXrh4MGH+noT5e7L87okcSi+pVcg01jA3yCuzkFduJqwJhTKLXeG6D/dwKL2Eh2b15aHZLddjl1JSYfmj/3rmgBBmDnDNPOYD3xzgUHoJBr2WyADPDpuOPe0+lFNmxqDTsOPJmdVXY0arAjiE64xWR4/AkB5dWF2V/xwS2vTUycgIf357ZGqt27wMOt64ajif70rh2rHhhFV9kZfcOJrVsVn0CfauFRg2xudV2w/uSCxocqBfHp3O0yuPEBHoyY/3TG7VjIDJqqDTCvRaDd183V3OJOY0v8fn8eb6E1jsCidyy/nx3skdtpZv9qbyz1/ikUheuWxorRZjk01xFBsFmG0qoX4euOk0aDWCrj6GJhvUG3Ra3rl+VNv8AvVwzkzGerrpePvas85HDAn1PWsIw9ug47pxESzbn87cwSGE+nmgqpJ/rY1nX3IRz5w/sM6pttj0Uo7nOE4Q729JanGgV1TJNR/s5kBaMfMGd+P9G0e36HXaErui8uPBTDzddGhO7y4lf/zcAVgVleTCSqR0fIb55ZbqQD9rYFfuntab+OxyHp/vmBa+cUIkvYK8EcKRm6+LUpMNm6LWujqoj0tHhp7V7+1VdSydyaJpvdl1qgCDVst14xxXaftTivjnL8cYHenPsxcMqtMR7L8bT2JXJdklZjYn5LW4v3z1oUweXR6Lh17LqvvPc5mp5prEppdwIK2YLjXktTvy+ALYn1KMyaYggJi04lqB/tNbx/Le5iSm9guqrrmsfWgKB9JKmFaP/LOiSrJKTPTw82jyiaAtOGcCfXN5+bKhvHzZH5dNu08V8M3eNIxWhQe/Pci+v80+6zn9Qrxx12uREiZFtXy8Ob3IyOEqQ/N1R3MwWZUGzZI7gn//lsAXu1MQCB6Z05eB3bsQ1dWLWQNb35kkpSQht5wgb0OTAuxpDDotj8zuyyc7UlgwpBuRNSzmhBBnnXiFEA26TB3OKOGaD/agqJLXrqi9e2stIyP8Ofz8vFq3PfjtQbJLzSTmVTCjf1em1pG7nj0whO/2p6HRwMh6crxN4dOdKdgUiZQK6+NyWHSGnG5Hk15k5NoP96BISaivO08vGMDJvAqnXXUUVFgoqLA025fgvhl9iEktRiNg4RkS5iMj/PnoltpDqKczB3WhqpKrluziaGYpA7p14cf7JndYsP/TBvozCfY2oEqJm05DSJe6g4+fpxtbHp9OWqGRgd1b3kUR6u9BryAvkvMrGNMzAHe963W+ZJSYsNpVNEJQabG3yHT9aGYpX+9JZdbA2vWAV9ce54vdKWiEYPX95xHVtemCbA/O6seDs5xjYbgpPg9z1eX48pgMpwb6uujm605hpRVVynrtH5+/aBDXjA2nq4+BwGacBM/k6jFhxGWVotdqmNbf9YqhxUYr4GhVza+wcvOkns1+DbNN4d3NiSiq5P6ZUdVT8KfyK7jw/3agSsmN4yP5ezMMTqK6+jjNQa3EZCM2oxRFlRzLLqOgwtJh1oN/Bfoq+ob48PUd4zmaWcolI+q/XO7irm+1Hodeq2HNA+eRXWom1M/DJYdJnjl/IMWVVrzdddzeAnMWKSXXf7SHMrOdHw9m8vviadUFqg3HcjHbVNz1Gg6kFjcr0DuTBUO78/GOZCx2hdtqyPO2FZ/dOpafDmYyqIdvvRsFIUSrNhGnuX58JLMHheCh17rk9PDQUF/uOK8XW07k8ejclgnzvb8liQ+rjLotdrXasepAWglSSsw2lQ3xuc0K9M7E31PPlL5BbDuRz/jegXRtR2/nM/kr0NdgTM+ARjsynIVOq3EJpb76CPXz4Js7J7TqNWo21doVyU8HM/Fw0/LgrCgeX3GYkC7uTkkFtZT+3Xw48OwcVCnbZWjFz9Otlt57W1PTXcvVEELw2Lz+PNYK9VVVOrTfJRJVSuKySjmQVsLE3gF083UnvcjEQx1oLiSE4LNbx1JhseNt0HXohu6vQN8Ctp/M53BGKVeNDqNrPZdiRzJKeXxFLOEBnvzv2pEYrXbKzHaXLIq1BUIIvl44ns93pTBnUFdWHEjn0x0pALxw8SBOvLTAJa5kXFHVNL/cwvfR6Qzu0aXeaW2bovLY8liOZZXxz0uHMCbSn8T8CiIDvFyu3tNW3DcjCqtdxa5Krh0XzsX/twNVQpi/B5sfm9EmbarNRYiGRe/ai3M60B/NLMXDTUufYOelBuKzy7jzy2hsiuTn2CzWPTy1zsf97acjHM8pJ6WwkiVbk/ho+ykUVfLQbNeWPW0qhzNKWB6dwfwh3ZgcVXfBc3i4H29dMwKANUdysNgVNEKQVmTq8C+gMyiosJCUV8GoSH+nuiLd9vk+jmeXo9MKVtw9qc5U4cb4XNYfy3UYwqw4THdfd2IzSgj0MrDx0WntcoXSlpisCu9vTUSn0bBoWu86/Vfd9VqePt+hxnI4owQQWOwK2aVmoHGdqz8T52yg/3j7Kd5YnwDARzePYUo97U/NpcxkQyBQVJUSo63ex0UFe3MytxwJlBit2BWJVVH5fn86w0L9mBwV2GkPRLuicu2HezBaFb6PTmfXUzMbLRw+NX+Aox3STcvCKe2Xvmgr8sstzHpzC3ZVMiYygC/vcJ6ReonRhl2V6LWaeo+xMH9PpJS46zX0CvRk60mHZmBBhZmle9O4bGRopzPersmbGxL4clcKQgikhIdmN5yCGRrqyy2TItmSkM+jc51TrD+XOGcD/baT+ZhtKhoB0SnFTgv043oFcPe03uxLLjorv6iqkt/ictBrNbxy+VCm9gumh58H4QEerD2aQ0GFhcwSE3d+Gc39M6NcdoClMSSO/uDTKE1QuAgP8OT7RRPbcFVNx6aovPTLMU4VVPL8RYNbVAxOzKvArkqMVoXoVOdKOb13wyheW3uc0ZH+TD6jjTcxr5yY1GJHG+ZdE0nKq+D8od15+ddjfL0nDVXCm+sT+HBbEjufnNlptYysdtUxnCQd/1+NIYTgqQUDeWpBXXqL7c/WE/m8uymRBUO7tUuhvzEadZhqD9rCYSomtYiFX0Tj7a7nm4Xj26Xw+e7mRN7ZlAjA3y8cyA3j/9CRkVLy+roEPtiWhCph7qAQPry5UWOYFmG02skpNdMryKvNrhr2nCrkq90pXDy8B/OGdJwqI8DeU4UcSi/hspGh9dZMavLjwQyeWXkUk01heJgvq+4/r9nvabWr3Pb5Pg6klvD4/P7c3g5f5vxyC9P+vRlVlYT4up9lbp5TambK65uwKQ7dpJi/z2kT9y0pJamFRoJ8DE4V3KtJudnGv39LQK/V8Ojcfq02Jm8NxZVWVsRk0K+bT5N0e6SUDHh2HRa7ikGn4deHpjg1fVwTZzpMdUpGRwa0u/xuUl4FFruCQJwlViSE4JZJPdl2Mh+jVWFxG11eFlVamfOfrVRY7Fw8vAf/vmp4m7zPhN6BLuGJmZRfwS2f7sOuSpbHZNRr3CylJC6rDH8vt2rhOL1WNGtgqyZuOg1LF7auK6m5FFZaUKXEbFfJKjGdVWzs5uvOwim9WR6dzg3jI9vMYvH51XEs25+Ou17L+kemtklvuI+7nhcvaf7sRltw51fRxKaXVLm8TWREPV4I+eUWMoqNDAv1pYuHnqIKC0KAVweepE7T8Ss4h1g8tx8phZW46RwFpDPp5uvOmgenOP19S4xWYlKLGR3pz5HMUkw2BYtdZd3RnDYL9C1lx8kC7v/2ACFd3Plm4fhWDQWBI58thMCuqhRVWOt93H83nmTJ1iQAlt01kbeuGU5akbFO+QJXpX+ID7dO6sn6Y7k8PKtvnVdrT84fwJPzBzj1faWU7E0uwtugY0ioL78eycZiV9FqBAfTimspdnY0JqvCTZ/sJSG3nBcvGcJlTrAoLCi3YFMcNZPCCkudj8koNjLv7W2oKswf0o2V90xidWwWE3oH0s2349tc/wr0TmB3UiHFRivzBndjZTsLMtkUlXlvb6PcbMfHXcdvD0+lh58HSfkV3OGCRc/X1h2nxGjDaFH4OTar1X3loyL8WDStNzsTC3isgcGbTcfzMNschuLRqcXccZ7rfTb1kVdmZtvJAib2CeyQPPR7W5J4Z1MiEsm714/irqm9eXXtcYK8DUzsU7/EREew9UQex7LLMFoVXvk13imB/v+uG8VLa44xLMyXGfW0ux7NLENKh/DZjpMFvHXNCJeqwf0V6FvJhmO5PPjtQQBixhdXT+e1lpUHMvho+ymuHB3GHQ1Mppab7RRWODw/rXYVVcKGR6ZiVdQ6W9I6mslRgSTmVSCRDGuhHaCiOoavNBq4ZHgoD8/ux8ONCMwtntOP+5YeIMjHwEXDXGcH2hh2ReX8/22n0qLgptOw5+lZTumTzyk18+jyQxi0Wt64eniDHTrRKUWYbAoaAYczSnlkTj9undQLvVa4XOfY6aliTzct43u3fPgxLquU3UmFLBjanaFhvixrpJFgSt8g+gR7cyK3vM3Ssq3hr0DfSk7lV2Cv0sE/nlPmlNc02xy90XZV8traBM4f2r1Ok4zsUhMVZjt3nNeLZfvTuWZsePUX1hWDPDhSC3MGhRDoZaBnC4fHlmxN4p1NJ5EI8sst3DW1ccGu6f27Evfi/Ba9X0disasUG20oqsSuqpSZbU4J9P/+7Ti7kwrRCMGSrUk8c/7ZVwkWu8Lx7HLumxHFidwKfNz/UOp0xUEzgMhAL35fPI20IiNjarhoNYeCCgtXvr8bu6ry4bZT7H1mVqMnNC+Djp8faH5Rv734K9C3kmvHRrD9ZAEFFRaeu3CwU15Tr9Xg466j0uJwM6rLAetAWjHXf7QHJDw6rx+Hnnde4flkbjm3f74fjUbw+W3jnDrNK4RgdGTrZCaySkxY7RIhJJklZietzDXxMuj42wUD+WxnMleNDnda4TPc37N6MxBWh9GHlJLL3t1FckElQT5ubH6seeY8DaGqksXfH2LT8TzumxHldGXNHn4e9GiFeUm52Y4qJTZFUmy0IiW42IVLsznnAr2UkoeXHeKX2GwuHxXa5sVIX089Xy8c79TX1Gocqo6/x+cypW8QXeoYod57qgi7IrGrkt+O5nLnFOd9Wd7bkkR6sQkBfLL9FC9d1j4uOE3l4dn9yCoxIwQ8OLP+POjG+Fy+2p3KNWPDWTDUeemaXUkFLPwiGh93HcsXTSIisG1bd2+f3Mvp7ZsPzOpLRKAnbjoNF9Tx2VRaFY7nlKFKyC21kFtmdlqLckJuOevicjDbVF5bd5y7pvZ2qRRQryAvHpnTjzWHs7l/Rp86fQMACiss/POXeLwNWv52wSCXlp445wJ9frmFX49ko0jJyoOZPHP+QKcZH7eU4korvxzOYkioLyMjmnY5GR7g2eCgxUXDu/PFrmRKTTYecLJw07ie/qw96jDQbi+Rt+YQ7GPgs9saNlQ2Wu3c8/UBrIrKrqRCJvYJxM9Jfrzvbk7EaFUw2xR+PJjRKqcxZyClZGN8HsVGK5eMCG3SzlurEVzegCyzt0HHNWMjWLY/jZkDggnzd569Xw8/D9x1WjRC0DOw7WY9WsPd0/pwdyNXGi+tieeXw1lohKOj7v6ZHSeg1hjnXKAP8HIj1M+D3DILof4etdxrOoqbPtnLybwKhIA1DzpneCLM35M9z5xtjuIMrhsfycAevmgEDAtruflFR6IRAp1WYFUcQc2Zhg9zBoYQk1IMApeYJVhzJJvHl8cicYjpvdgC74C6eOXyobzSBp6mvh56NiyeRlxWKeN6ud5Goqn4uDvc1zSCNhsccxauvboWoNNqWPvQVBJyyxnQzadD7btOk11qxmJX8dBryS+3tNmUnDOpbyiks+Cu1/L9oomsOZzN3MEhTlUQvHVyLyZHBeHhpm2S13Bbk1Viwq5K7IokrdjY0ctpEsE+hnqVOTsLTy8YSDdfd7zctNw4oWdHL6dBzlkJBFdix8kCXlkbz/hegTx74UCXvFT9i85LudnGY8tjKaq08vqVw/80Uth/0XQJhL8CvQthsSsYLUqH1xT+bBRVWnlm5RGEgH9dNvSc/fyllBRWWvHz0HdasbPOyuc7k/nlcDb3TO/DrIEhjT+hiTQ10Df6vy2ECBdCbBZCxAsh4oQQD1XdHiCE2CCEOFn1t3/V7UII8T8hRKIQ4rAQYlTrf51zn6wSE+P/tZGxL//Oh9uSOno57YqUkpUHMvhiVwpmm9Lu7//27yf4PT6XDcdy+e/Gk+3+/u3F4ysOM+FfG5nz1jZM1vb/nDuSE7nlvLs5kYSc8nZ/79TCSl5Ze5zo1GLu+fpALeXX9qIpp3U78KiUciAwAbhPCDEIeArYKKXsC2ys+jfAAqBv1Z+7gPedvupzkB2JBVhsCnZV8tnOFF78OY7tJ/M7ellNIj67jOSCysYfWA/LYzL4249H+Nev8by8Jt6JK2sawd4GdFpH8bY+0+5zgZ8OZmJXJdmlJl5ac4x3Np3skBNrcymutBKdUtQkueK6MNsULntvJ//ZkMBl7+1s95Ocp5ujaKsVoqqA265vDzShGCulzAayq34uF0LEA6HAJcD0qod9AWwBnqy6/UvpyAntEUL4CSG6V71Op0NW+VLW10vrLM6LCsKg12K1qxQbrXy6M4Wle9PY8vh0YlKKWReXw22TezG6hdN+bcXXe1J5ac0xAJbcOLpFBbbCCgt2FRRVJb8e0ai25J7pfQjyMSCAK0fX33LYVqiqbPPjC+DSkaH8dDATd52W5TEZCMBoVbhpYiT/WX+CiABP7psR1S5raSrFlVZmvLEFq6IyKsK/RTMrVkXFaldRVIc2lNWutmvPe7CPge/umsCOxAIuGtajQ2p0zeq6EUL0BEYCe4GQ08FbSpkthDj9DQ8F0ms8LaPqtlqBXghxF44dPxERrqkgeDK3nKuW7MZiV/nstrFt2krXw8+Dvc/MotJsZ/Jrm6tvTys08ujyWCx2lc3H8zj6wjyXKuZuSXCIhQkcGvUtCfQ3T+zJydwKSkw2nr/IOVpBzUGn1XDduAhUVVJmtuHroW+Xz1hKyd1fx/BbXC6XjOjBf68d2abv9+8rh/HUggF8sDWJL3aloOIQ4Vq87BB7k4sw6LREBnlx8fAebbqO5pCUX4FVUTFaFfantMzgpYu7nn9fOZyv96Ryw/iINpNvbojh4X4MD/ejwmLHalfbXUKiyYFeCOEN/AA8LKUsa+CLUNcdZyWlpJQfAh+Coxjb1HW0BUcyStmbXMj5Q7vXGp1eEZNBiclh5fbR9lNt3jNt0GkxeGv58o5xfLz9FAuGdCesxjSiK7SKnsm9M6KITi3GQ6/l2rEtO2F7GXT8p8pbtqOwKSqXv7eTY1nlzB/ajXevd15pqdJiZ0VMBuEBHswc8EchLqfMzKbjeQD8EpvNixcPadMgJIRDf/+h2f0w2VSklCye0497lx6oPrHpXewYGx7ux6gIf/anFPFwI3aCDXHpyFAudYKSZWtYHp3O0yuP4GXQsfr+yUQGtl93VJMCvRBCjyPIL5VSrqy6Ofd0SkYI0R3Iq7o9Awiv8fQwIMtZC3Y2eWVmrv7AIWD08fZk9jwzq/q+af2D+XxXCgAL2lFze2zPAMbWmEhdctNoNh7L5brxES61mwcYFeHPoXY2eGkLUgoqOZFbgSIlaw5n8/Y1qtMMvx/5/hBbE/LRCPjo5rGc19ch7RvsbSAiwJPMEhO9g7zxcW+fsRZvg46XagxVvXXNCN7fkkhkgBfzh3RrlzU0Fb1W43SJkY7i810p2FWJyWpnY3wet7ejVHajR5ZwRJZPgHgp5X9q3LUauAV4tervVTVuv18I8R0wHih15fx8mdmGrCVg9Idrz6Q+QWx9fAZWu9rmeiYNMaN/13p1sNuT5dHpvLQmnmFhvnx8y5hqUaziSitv/X6CIG837p0e1Slb9yIDvYgM9CS5oJIpfYOdFuQBckpOD8xpyC37Q4RNp9Ww5sEpnMqvJKqrd4flxoO8DTzrJEG+1pBXZuamT/ZRZLTy/g2jaslvLI9OZ19KEYum9mmRx68rcO3YcF785RhuOi3T+jvHw7qpNNpHL4Q4D9gOHAFOl72fwZGn/x6IANKAq6SURVUnhneA+YARuE1K2WCTfEf30S/ZmsTaozk8ODOqxT2um4/n8dnOZK4cHcbFIzr2ErEujueUce2He1AUyVcLx7do8nXEi+spMdrwdNPy3g2jqvPx9y09wG9xOei0gmcvHFTLK7cpGK12h/ZJB6cN7IqjGNyti7tTr5wScsp5btVRegV58eIlQ1qUny2utPLCz8cw6DU8e+Eglxu5V1XJoq9j2Bify/XjI3jp0uZLJ7y/JYk31ydgVyXjewVUa8DHppdwzYe7MdtUwv092P7kzGa9rk1RUVSJu77jRccKKyx4uGmd5oHrNM9YKeUO6s67A8w684aqbpv7Gl2hC9EUAaOGMNsUFn0Vg1VR2XOqiIl9glyuTW/pnjRKjI56wyc7TvF/1zU/Bz0q3J89yYUIoG+Izx93nD46JIh6D5W6eemXY3y6M5newd78fP95tbohDqYVczijlIuG92jQGMNZ6LSaOnX/W0v/bj6NGlc0xmvrjvPL4SyEgK4+Bh5twE2rI0grMrLtRD6qdBxrf79gULMD6/BwX3RagV6rYWKNepgQjuNKQLNPwPHZZVy5ZBc2u+SDm0fXujIuM9tYdTCTfiE+jG8nzaLWWme2FNfaFnRStBqBXucQ0NJowM0FUxfT+wezPDodCcwe0LKrliU3jWZfchG9g71qFa1fvnQIXX0MBHq5cfWY5rUnfr03FVU6BsZiM0qqC97JBZVc99EepIRv96Wx7uGpLVozOHxEv9ydgr+nG1eODqvzysFsU0jMq8CmqDz5w2G6+7rzzvWjnKqR0xp83PVoNY5g1165/ObQzdedYB8DhRVWorp6YWjBVcukPkH8fP95lJhstUxDhoX58fKlQ9iXUsSdU+t3W6uLn2OzqLQ4+uY/35lSK9Df+UU0h9JLEAJW3D2JIaG+zV7zabaeyOdQWjFXjQmvVwv/VH4FBp2Gf/+WQGxGCS9cPISp/donheN6R0wnRK/VsOLuSfwcm8XsQSHt3r4lpeS5VUf5OTab2yb3rFM2d9bAEDYsnoaiyhY7O7npNNWFxJr4ebrx/EUty/EuGNKdNYez6eKuZ1CPLtW3F1RYEAjMdqVWXrslPL86jp8OZqDRCISAq8aE17rfpqgs+O92ckpNgMBkU0gtNPJDTEarPW2dxaNz+xHs7YabTsONE5qXGnMGMalF3Lf0IEHebnxx+7izdqbuei3rH5lKYl4F/bv5tDj1VetKsQaXjw7j8hbMOMwaGMKnO5NRJVwxqnZKNavEhMWu4qnXklNqbnGgP5FbzqKvorHaVVbHZrHx0elnPebzncm8svY4qpRohMBiV3l8RSx720iB9kz+CvROYmD3LtV+lQ1RYbHz6q/x2FTJM+cPxNcJMsoZxSaW7c/Aqqj8d+NJ7prap86BEGcZRziT/1w9nMVz+hHsY6h1qT8m0p+bJkayK6mAp+a3zgy7xOTw1NUJQWlVu2xN8sstZBQbsSmOepWHXoMEeruQyqi7XstdTUwv/nwoi1WxWdw2uSeTo5xj3v3q2uPklJkprLSw8kBmnTtrTzedy8laj470Z+/Ts7Eq6lnp1LevHckLP8cxLNSXGQNa3uxQbrYjEKgSysz2Oh+z9mgOFrtj3kSrAQ+9tl2Lyn8F+nbm3U2JfB+djirBXafhhUtarx0e5G3A212H2aYQ5G1o0WVzRyGEqPMEJISo08e0Jbx48RA0QhDg5Vbnbri7rzuzBnTlt7hcLh3Zg1kDQwjp4l6rxbWzkFNq5tEVsVjtKttP5nP0hXlO6SAa0zOAo1llSCkZHNr4hsaVqO8Ke3SkP6vvb73P66gIPx6cFcXupEIemVO3Cc29M6I4lB5NF3c9r14+lHKLnbmDnSdu1hh/Bfp2xsNNixACrXA41TvrNTc8MpVD6SWM7RXQYPeKlJI31iew9kgO98+MatBlqDOwP6WIfclFXDy8R71XLN183Vly4+h6X0MIwZKbxtRqre2s6LR/lMP1Wg0aJ/0+T8zrz5SoIAK83RjQreFAfzSzlCdWHCY8wIO3rxnp0hZ7jVFqsvHdvjR6Bnkxb3DdMwZCCO6ZHsU90+u3tZzWL5jj/5xf/fj25i+Z4nbGalf5bGcydlXljvN610pXrDqUyctr4hkd6c//XTfSKf3o6UVGCiutDA/zRQhBYl4FF/xvOxa7ilYjOPnSgg5va2yI7FITn2xPZlCPLmc4P3+JAAAgAElEQVSdlDKKjcz+z1ZsdpWuXdzZ/fRZTWB/SvacKuT3+FwuHxl2Vt3jjs/3U2y08e71oxga1vLi42nMNoXY9BIGdOtSvXO++J0dHM4oxV2v4fmLBnPdONeUOAHHxuebvWmkFRlZNK3PWd1dN3+yl92nCtFpNHx8yxinpcKchdPaK/+iZSiqrFOywE2nqdf1/rlVcZSabGw9kc/e5KJWH1RHMkq5+oPdANwyKZKnFgwkwMsNnUYgdBoCvQ0u726/6KsYjmaWYtBp6e7rwcQ+f7TBne6mUCR15t5bw+pDmTy98gi9g7355s7xLtN9cxpFlWhE3bvDCb0D65TrWLY/nbisMuyq5LV18Xy9cEKr13H1B7tJzKvA003Llsdn4G3Q0SfYi5O5FYAk0gXrQjVZdzSHl9bEY1NUEnLK+fz2cbXuL6y0YlMkOo3Dt8BZFFVaufbD3WSXmvnvtSNqSWO0BZ0nmdtJsCkqVy3ZRZ9nfuUfq+Oa9dyB3X2q0zmRTpjEPZhejColJpvC1hMOyeMALzdWP3AeL1wymJ/um4wQAqtddXqgdBYWu8rpi07rGTK1/bv58Njc/ozvFcBHNze6qWkWr61LoNKqkJRXweYE15KLXnUwk/5/X8vEVzaR14yOpEE9uqDTCjzctAx3glWkokqOZJRitCpUWOxkFpsAePWKYfzr8iF8fts4JlVtVoorrR2iw94Yp48pVUos9rNlkN++ZgRT+gZx3bhwzh/qPBmUX49kk1ZopNxs5/V1CU573fr4a0fvZBJyyjmSWQrAF7tSeP6iQU3OyX1+2zg2J+TRxV1HkBMGKy4Y2p0vd6eSW2rmiXkDqm/vE+xd7VubU2rm/P9tp8xk44n5/blrassHx9qC928YxVu/n2BoqC9T62jtXDilNwunNK+3euuJfBLzKrhydFi9XU+TogL5JTYbBAzp4VrFx3c2J2JXHZId64/lNrndckb/rny/aCJphUbG9Gy93LVWI7h/ZhQfbTvFtH7B9K3qIjHotFw28o8029MrD/N9dAaRgZ6seWCKS+XsLxzWg+SCSlILjTw+7+whtL4hPnx1R/O0dnLLzKw6lMnoSH9GR9Zd0B8R7ocQAg+9ts6WZWfzV47eyRitdma9uZVio5UxkQHNFmS6d+kBNsbn4u/pxobFU9s8ZbAiJoNnfzqKyaYQHuDB9ieaN17uLOKzy1h5IJPZA7u26ZRiTGoRN3y8F1WFMT39+ebOutMXqio5mF5MDz+PNpmWbQ1v/36C97ckodUIVt8/maiudfee18XeU4Xc8uk+VODNK4dz0Yi2lyTu+7dfsSkSTzctX90xrt7g15aYbQqf7UxBq4FbJ/VqU5ngGW9sIb3IiE4rWP/wtHp1stKLjORXWBhZFfRbwp8uR+8qHROebjo2PTqdtCJjo32yhRWWKjEwA/fPcIiB/X4sF6uiUma2kZBTXkvYqSFUVfLQsoNsPp7P3dP6cP/M+jsATj9+96lCuvsaMOg12FW1w4pmiiq5asluKix2vtydwq6nZrbZqHh+udWRrlKUBtMeGo2oFZBOb4hc4Rh7eHY/Lh7eAz9Pt0alIb7bl0Z0ajF3T3OIgf0en4e5KkXxU2xmswL9thP5PPTdQXr4ebB04Xj8PBt+79TCSlIKjVw4rAe/HM4iyNvQpFmTtuC/v5/g050pAFhsKg/MarnkcWM4jHQkeq2GEpOVCOoO9OEBnu0223JOBPr3NifyxvoEhoT68v2iiR0uXuThpqV/t8Z3Wc/8eISN8XnotIKQLu5cNy6CmyZG8umOZCIDPZs1qXcir5wNx3Ix21Te3JDAvdP7NNhN8881x1i2Px1VSj67dSx9Q3wI8jZQbrbhbdDVG9BiUov478aTTO/X1Wkyq6qU1TZxEqoHl9qCOYNCuGZMOMeyy3juwqaZnKQUVHLlkl1UWhSX6bxoyjDXgbRiXvj5GCabwv7kIrY+MYPLRobyzb407IrKbZOa9//3yq/xFBttmKwKvxzObjBllJRfwYX/24EQMK1fEDufnIm/lxuqlJhtSr3fUaPVzos/H6PCYuf5iwY7TTOq0qqgqBIhHK5abcn7N47mP+tPMK1fMENbIavgTM6NQL8lCVVCYl4FManFLvFFbAo1e5xPx+RnLxzE4/P6Y9BpyCu3cNeX0eg0Gt64eniDu7cefh546LVohKBXkFejLZP7U4owWhUMOg0n8yqY2CeIx5fH8sOBDAZ278KP906u8/L2ji+iKTHa2JdcxLheAa3SBzmNXqvh01vH8umOZC4Z0YNuvu6tfs360GoE/7i4eXINqw5lUlRpRZXw3pbETnV8yf9v77zjoyqz//9+Zia9FxJII/RepYt0FRGwi35dlbKWVVHX3l1dy7ruWtb2W3XFuqCIqKsIIiJNaighEBIS0knvyWQyM/c+vz9mEgNMkkkySWbivF+vvGbm5s7ck8m95z7Pec75HKRVDMyybXhUIIlPX4QqLSPON7acZNOxAlbOHdRsnngDUwaEkVmqRyIZ3Upq5snC6kanejinkohAbxKyyrnhfYt+0YfLJp2RQdXAql2ZfHUwz5pVJPjX9Y7punX/RUMwmFR0WsGdrcx2O8r5A8Od7hzpEY5+xuBwfj5RhJdOw1A7RtLOwotXjiIq2JteAd5cfd5v+isNo51//pjCzrQShBC8vTWNJ1oYgQZ6e/DTfTNJzq+2q6/s4wuGc8+aQ/QO8mbxmCiklHyZkIvEIr6UWlht04n7e+mosmbo+DlQKtcZL44Gpg4I551t6UgJ81txhs7E2NhgXrh8FAeyy7mlyYK1ViPQIjhZWM1bW9MwmFVWrj5Eyl/ntxiaemrhcOaP6E1koHerekmzhkQwNjaYEwXVPHmp5bxdl5CLwWSZua3el23T0Qc2NM/WCofIgzQQ5OPB368e7bDPczV6hKN/8/rxJBdUERPi2+6TY1daCfesOUR0sA8fL5/cJcJkwb6eLTZ8iAnxbWzuER3S+oJgmL8X0wfZN9WdOiCMfY+fKah04fBIfkkpJjLQu9n1hdW3TGHtgRwm9QujXwsXu6JK3t1+iqIqAyvnDkIrBIl5FYyLC3E6LfXWmNQvlK0PzKLOqLRb/0ZvNLPsw/2cLKzhxStHtTp6dhQtiYEF+Vp643pqNYT7eba6/iCEsHuh3NtDe85C98LRfVh3MBeAK5pp6/d/k/ui1WioqTdx09T4Fo+RkFXO5/uzWTg6igsGhXMwu5wgH482LU7/XuiRWTeqKrn9swR+Ti7ixil9edqOqfolr28nOb8ab52GJxe1vXmGozErKiZF8kNSPlqNYNHoqE6vYJVSkldRR0SAd4ezEr44kMNT3yRhViSzhvQiMbeSmnozIb4ePDx/KLOGRhDoZEVIbWFrShF3fnaQMD9P1t4+rdVw0/+OnOahdYnUGRViQnzY2cbmGY5GWvPG04tr2JdRxiUj+3RqyKyBCr0lBNbR/gJGs8qYZzZRZ1Lx0mlYOi2ej3dnoUqVO2YNYt7wCEZEOUd8vDOxN+umRxZMZZbWsi2lGLMq+fDXTOrNrS++TIwPteT3Chx+guxOL2XNvmz0RtvKdmdzoqCKsc9uZswzPxLm78VlY6O7RKZACEFMiK9DUs8aBhASMJhVKvQm9EaFvAoDD687yhJrxa6r8trmVPRGhYIqA98ltt4SeVifAJAWfaPxcR3PYW9KcXU9n+zJ4vjpKrv2l1KydNV+hj25kdd+OsnSafFd4uQBuzKF7KXpEHV/Zhl1JgWjWfLm1pNc9c6vJOZWOOQ4PQHXmkPbSVSwD6F+nlToTQzo5WdXI5C/LBrBxdb4oyPlQ/dnlrHsw30A/JRcyPs3T7S53660Ep7+NolR0UFEBHhTU2+5KazamcHMLmpO4EiuGh9DUVU9hdUG7p07iH9uTmX9odOYFZU6k8Kp4truNrFDzBsWSUphNYBdKpcDIwLYeO8FZJfpz+ie5Aiu+X+/kl9pQCMEWx+YZdNp19abWbn6EPkVdTxyyVB2pZUggZ9PFFGuN3VJBy9H4qnT8MmKyfx3bzaLx0Th763jT58mUFlnskoWWHSdnE02ubvokY7e20PL5vtmklpYzYioQLtynzUa0SmLgacr6hDWZhY5ZXXN7vfg2iOcrjRwusLAyjkD8dZpUGk+luksSCl5bP1RfjxWyO2zBjQu+um0mjNylV+8cjTPXz6Kx9YfZVtqMfc1I+faQHmtkXe2pRMV5M1NU+OdTnht5dxBzB0WSbCvR7Mdhc7G0oC8fU1fWqKgqqH5uJbS2nqbjv6rg7nsSiuh3qzy2k+pDI4MIK24hmG9Awh24KJnZ7D3VCn3fn6Y6GAf/rN0YuM63MT40DNusgeeuJDd6aU8vC6RAb38uGRky5IFXx3M5WheJSum9yMmxLk1eTpKj3T0YMkOcfQUuT1cMrIP21KKOVlUw/NXnKs9b1ZUdFoN/Xr5Ua43okrJ7KERLJkYh0lRiQzsmil1e0krqmH9wTwMZpUXNySz/Px+NsXcwHIz/dtV9mU+PLD2CNtSi/HQCkL8PLmsCxuuSylZtSuThOxy7pk7iMHNdD0a7iTSCK9fN45XN6cyd1gEw88qSDIrFpXS+HA/NMLS8GJQZADPXzGK3PI6YkN8nO4mejZ//e44+ZUGymqNfHvkNDe2kL8/dUAY2x+a3epn7s8s47H1SRjNCntOlfLDPe1vVdkeThRU8caWNCb2C2FpG+sZ2kOPdfTOgqdOwytLxp6z3aSoXP/uHg5klXPT1L68d9MEfjhawODIgFb1vp2JyCBvPD00aDSCPkHeNp28lJJNxwoQQnDR8Ei7ZlgmRUWVEhCdWkBli/2Z5by8KYU6k0JSXiXbHmzdcXQnF4/obTOL5+tDeTyw9gihfp78b+V0Plw2iYIqAwtG9cFDq2kxa8qZGBcXzKmSWlQpGd7H9k03raiG/ZllzBsWaVeRlcna7UlKy8JuV3PLRwfIKa/j5xNFjIoO6nRZCLej7yZSC6s5dtoifvbJ7iyeWTyCq9rRE7O7CfT2YPOfZ3I4p4JpNvKiAd7bcYpXN58E4OH5Q+zqw/ryNWP4x6YUooN9ujx85aG1FBppBJ2qidLZvP2LRfysss7E5jaInzkbf1k8srHrly0JhbJaI4vf3IkqJW/+nMauR1rPaJo6IIyH5g/hcE4Fd3eiHEJzeOo0aARIpEM6gLVGq45eCPEBsBAoklKOtG4LBT4H4oFM4FopZbmwDNVeBxYAemCplPJg55ju2vQL9yPEzxNZY2RifGiLo9wqg4n3t58i3N+LP0zp63RT7chA7xbzwtOLa6k3KwjgVEnzi7B1RoXj+ZUM6xNIZKA3L18zphOsbZ1xcSG8fPVoDudUsuz8+G6xwREsGh3Fm1vT0GkEU/q3PGLcmJTPwexybpwS73S9hbUawawhzfd0LautR1UlBrNKYZUBVZXNXiMpBdV4e2joG+bHsm5s/P7hskl8+Gsm4+KCu2TBuNU8eiHEDKAG+LiJo/87UCal/JsQ4hEgREr5sBBiAbASi6OfDLwupWxVvrEz1SsVVbIrrYQ+Qd7NdphvjeOnq1j24T48tBo+Xj7JYU2jDSaFnDI9/Xv5NxvXBli5+iAbkwrQagTPXT6Kq11s5J9fWcfdqw+hEYI3rh9HhI11B0WVXPjqNgoqDYT7e7Hl/plnjHScRbTOFqeKa8gq03PBwPB2dQVTVMkdnyWw82QJd81puSVdW8ksqSXIx4OQFrJqkvIqufr//YrRrNIv3I8t989y2PG7Aikl//wxlR+S8rlrzqBmZ4Cf7sniue+Pg4R3b5rAjCbZbM4kWtcWHJZHL6XcDpSdtfky4CPr84+Ay5ts/1ha2AMECyEcp9bfDp76JonbP01g0Zs7OZRd3q7PeGdbGoVV9eSV1/HR7kyH2eZtXRhrycmDZaSrqhIk1Jk6V5DpbD7YmcEf3t/L3lOl7f6MPkE+rL19Gp/fNtWmkweoqjORVapHb1TIr6w7o5vPu9vTGfDYBua/tp3aevtqEbqK1MJqLv3XTu787CB//uJwuz4jOb+K7akl1BoV/vFjqkPti7fOHFvCYFIQCFRJo0RBV3GysJplq/bxtx+S292YRAjBAxcPYcv9s1oM8/18ogiDSaXerLI7/bfzOadMz6QXtjDkyY1sPVHULhucnfYGhyKllPkA1seGeVU0kNNkv1zrtnMQQtwqhDgghDhQXOyYDj6qKsku1Z+xuHIwuxy9UUFKSM6vbtfnTusfhreHBi8PDZP7db2W9gtXjGLRmGhumhbPkgmxrb/BQSTnV/H3TSfYmVbCLR93br+AED9Prp0Qg4dWsHhMFBFNFtTe3moRrcsu07M3o/03HEdQWlNPaU194+uUAss5pTcqHMpuX4FObIgvXjoNvp5aRneD2uGE+FAeuHgI80f0dninrta4Z81htqYU89GvWWw+XtCpx7pz9gACfXREBnpz7cTfrqPvEvMprzViNKu8uTWtU23oLhy9GGtraGrzNi2lfBd4FyyhG0ccfNmH+9l9qpToYB9+uOcCvD20PHnpcO79/DCxIb5cOrrtkwuDSWF4VBCfrpiMv7euWzJiIgK9ee26czN3Ohs/T8vpoRG0qk9TWWfiw12ZRIf4cNX46HZNgV+8cjQvXnlu+uXcYRF8fzQfnVYwshvL2n9JKeK2TxIAy9R/5uBezBsWybi4YE4W1vCXRfbJHp9NaW09H6+YRI3BzHg7BOk6gxXT+7HCQbLTbSHIxwOddUbbmiTGxqR8jp+u4g9T+jY7M2yJ8/qGkvj0xedsnzYgjNe1Aq1GsGCU64jWtYX2OvpCIUQfKWW+NTTTMN/JBZoOOWOA1uvDHYCiysa+qPmVdWSV6hnSO4BpA8PPEe+yFyklV7y9i8wSPeH+nmfELqsNJm76YB9ZpXr+ec0YZg9tfrHIERRVGThRUE2fIG/+szODMbHBnd4oJC7Mlw+WTmTfqbJWM4Ie/PIIW08UodNo8PPUcokD+2u+fPUYbpnRnz5BPg5VNGwr3yXmN/YV/d+R08wc3Asfz3PFu9rCuoRcHl9/FIB3bjzvDJ32/+w8xes/nWT6oHDeuH58qyG+jqCokr2nSokK9mHjsQLyyuu4e+4gh+nBN8fbN4zns71ZDOjl39hf1hYJWeX8+fMjGM0qv6QW8+1d0x1mw5jYYLY/OJuaerPD1t+cjfY6+m+Bm4G/WR+/abL9LiHEGiyLsZUNIZ7ORqsRXDU+mvWH8hjaO5D+vTqeI1xrVEgpqEaVUFhVT2GVoTEjYWNSASfyq6kzKTz3/fFOdfQlNfXMfWUbiiqRUmIwqXxz+DTxYX42pV4dybQB4Uwb0HrFcLXBjKJKtBpJtYPj6BqNcIragusmxjbq2lw30TEhtJ+SCxs7Pu1ILWZ2k+ySv/1wApMi2XqimGOnKzs1O+OhLxP5ISkfk6KiEQKzIskp0/Ph8kmddkywhOzumtN6emPD2owiJTUGx6/TRAR607lDte7FnvTK1cAsIFwIkQs8jcXBfyGEWAFkA9dYd9+AJeMmDUt65bJOsLlZ/nntWJ69bCS+nlqHrJ77e+lYMjGOL/bnMGdYBDFNpIIbhM98PbUtap3syygjtbCay8ZGtbv/a1ZpLYoq0RsVm7ExZ+Dlq0fz/PfJxIT4dijvvVJvAkG3jtybY0L8b1N/R+XX3zKjPztOluCp05wzQxsRFURqYTU6jSC2mRL9sloj3yeeZnRMMGNi238jaGhE46EV1kK1ZmKu3cQFg8K5Y9YAjuRW8ICNJt72YlJUiqvr6RPk7XIZNh2hR8oUdxWZJbWcrqhjSv8wm3m7DWlrUlqq+9bcOrVdxzErKnf89yC700tZfn4/CqoMjI4J6nYp5eZQVUlqUXWbQy3bUou55eMDCGDV0oktTuXt5c2f0/jiQA5Lz49neTfmTbcHg0lhb0YZw3oHNBuTvuT1HZwqrkEI2HjPjFYbgjTHj8cKeGhdIv3D/Zg5uBfFNfXcM3dwp4du2ktRtYHaeqVN1b0Gk8KCf+0gp0zP7CERvOuAhefUwmruWXOIMD8v3vq/8V3Sx6Ipv7vm4N1BfLhfixdWgVVRUG9SyCtvXtCsNXRaDe/e2LXZEB3h/rVH+CEpHy+dls33zSAiwL6Fs/UH8xozpj7andlhR19UZeD1LamYFMnz3ydz7YRYl2p64u2hbVW5tKCyrlHQrLimvt2O/qIRvbnIRbpnHc6p4Lp3dyMlPHzJULtv4KeKLQMzkyL58XghdUYzPp4dOx/++t1xkvOr8dDWsGZ/NrfNHNChz+ssXLe+uwUcrV0hpeTOzw4y+PEf+Ot3x+1+3+yhEVw+NppR0UG8akPvpqfSkK9sUlSO5dmnkQ6wZGIsWuvEaOuJYrYkF7bpuCcKqrjjswQ+2JkBQIC3B76eOnw8tAT7euB9VrglMbeCn08UWmoU2oBZUdv8ntbYnlrMyKc3MfPlrRRWGex+3+vXjWNEVCA3TIljQjdl7HQ1v6aXYDJbGqdsSLR/CXBghD99rWtsWo1g6ar9bTquSVH52w/J/PnzwxRZ/0eDIwPw8dCi1YhzZhcVeiMbjuZTUGn//7OzcJ3hjZ2sXH2Q/x3JZ+bgXqxaOtEhcgFZpXp+Si7EqKh8sCuDBy8e0mwX+6ZoNYIXrhzV4eO7GnfMGsBLG08QF+rLpDbUHUwdEMasoRFsSS7CpKjsyyhj7rBIu9/fIBS19UQxo2KCmBgfyvd3T2d3eikzBvc6o2r117QSln+0H40QLJkYy9OLRpBXUccT648S4uvJc1eMxNfGaG93eilLV1mqpL+4barDFCxf3ZxKTb2ZerPCt4dPc8uM/q2/CZgxuNcZFZ6/BxaNjuKDnRlUGczcOdv+KmJPnYbnrxjFjf/ZR51J4VBO2+oevjiQw4e7MjEqKlV1Jv6zdCKPLRjG+LgQQvw8zkhakFKy8I2dlNUa8dBq2PXIHPw8tbz200l2p5fywMVD2nRtdJQe5eirDSa+t97hd6eXkldR16xuh6JK1h7IQZVw7YSYFkvXewd5E+LrSaXBRN9QS3GLsyOlJKOklvAAry5v2XfbTIsufXtusvfMHURiTiXenpo2r0F4e2gbhaIa/kcxIb5cM+Hcc+BEQTWqCgZFITHXIi73l2+PsS21GJ1GMKxPoE1nu2pXBvVmS3Xllwk5PBXVfJvKxNwKdpws4dJRfVoNqcweGkFyQTUgOS/eNUbm5bVGqg1m4sK6VhsnNtSX/Y/PQ0rafI6NjQ1mav8w9mSU8udWeiKcjbfO0oFOI4SlGx2WwZyt+hyjonK6og5VgpdOUlZjJKXGwLvbT1FnUrjjswQOPHFhm47fEXqUo/f30jE6Jpjk/CpiQ31bbI/27vZ0Xt9iUVQsqjZw77zBGEwKd3x6kOP5VTx/xcjG0aSlkckMUgqqGRkd5BKr9c/87zir92Xj5aFh070z6BNkX3MMR9HemdTomGD2P9G+uodVyyby0a+ZjIsLaTUV8arxMWxIyqewysATlw4DoFeAFx5ai6pgmL9t2YDFY6Ia6zXmDW9+tlFWa2TJv/dgVBTe23GKg09ciEYjWH8ojxc3JDO5fyivXju2cYCxcs5A5gyNIMjHw+lExWyRUlDNFW/vQlEl9104uMtj00II2nMZ6rQaPlhmu8tba1wxLpqaejPF1fWtzri8dFoeuWQo7+3IYNHoKGJDfTAqChJL96uu7ujVoxy9EIIvb59KZmktsaG+jaJYn+7OZH9WOXfNHtgobFZSU49ZkUjrc7BUPu4+VUqdSeHJb5LOCBsEeHswwY6WcV2FlLLFEc2Go5biHq1GcDCrgktHd62j7w5iQnx5/FL7qlODfD348vZpZ2x7auFwhkQGEOzrweIxUTbft3BMFOfFh6DTaBozUtKKqnnj5zTO6xvCTVPjAdAbzahSoqiWHHBVSjQInvomiWqDmS3JRRzIKmeKta2gEIKR3SB/0BItqUD+ml6CWZEYFUtNh7MuQjoSjUZw87R4u/e/dcYAbp3x2/cyMCKAVUsncSS3giu7WHq7Rzl6sNyxB0b8plKZkFXO8xtOWGJy2RWN3WdWzhlEfmU9qpTcPXcQ/ztyGoNVMMzXU+t0F11TCioNXP7WLkpq6nltyVgW2nBKt8/sz3PfJxPu78X0TmiR6AiO5FTw8qYUJsWHsnLuwG6fKXl7aO26kM+eHf3xowNklur58Vghw/oEMjE+lJgQX55cOJyvD+Vx28wBpBRWcyK/moER/o36OHFOPHJ/6pskPt6dxbQBYXy8fNI5oc2LR/Tmra1pVOhN3DHLOZ28waTw7HfHKa6u5y+LRxBtZ8vHzmTqgLBOL3K0RY9z9Gej0/zWREKn/c2RBPt68vYN4wF46usk1ibkIpE8cekwIgK8W9S/7m42HSugTG/ErEre+iXNpqNfPr0/N06NR6cRDnGgeqOZ0hojMSE+DnPIt3+aQH6lgYSscib1D20c3dpiS3IhOWV6rpkQi5+TpUg2hHuAM2QK/jClL3+Y0pe0ohoWvrEDAQyPCuKVa8cyrE+A3b1muxpFlXy8OwuwiAKmF9cypPeZEt9RwT7sf3weiirbJc18NlJKcsrq6BXg1Rj/7iif789hXUIuJkXFrKisWtZ8lW9eRR0bEvOZ0j+MUTHOO8hrL851xbSD7xJPcyK/ipumxdvM1x4TG8zfrxpNQlY5y5sRbUotskgZeGo11Jul0+cTT+4fik4j0Og0LGihAbKHVkOF3sitnyRQWlPP69eNa9dMpajKwEWvbUdvVLhhUhxPL25+AbItBPl4UFRdj0S2uGC8PbWYO/97CCklv54q7dKaguxSPav3ZzMpPrRZmYsPlk7k/R2nGBcXbLNPcV5FnaWewqiQXaZn/kjnPr+0GsHkfqEcya0g1M+z2ZmHEAKdVvDu9nRW7crkyvHRPHjx0HYd85F1iXx9+DQB3jo2/8BUixoAABPRSURBVHlmq9LK9hDs62EZ4GlEi58npeTKt3dRWmPJkNn24Kx2iaY5My7t6PeeKuXBtYkYzSq70kpZf+f5NvdbPDaaxS00l3560Qju++IwkQHeXDvB+Zt6DO0dyI6HZlNRZ2JAKyJMXxzI4VB2eWPR0Opb2ybApaqS/+7LxmBSMJpV/pd42mGO/uPlk/jiQA4jo4NaTFMsrq4HLHnThV2ck3zDf/aSV65n1a4Mvls5/YywYAOxob48c9m5jd8bmD4wnAWj+nAwu5ynFznmu+tsPvvjZE4W1RAf5tfiCFtvNPPSxhQUVfLe9gxumNy3zTOV7FI93x6xrikZFRLzKlstFLOHxWOiUFRJaY2RG6a0LABYrjdhtmo1VRnMRHS/tJJDcWlHrzcpICxCR7XG9gsdDesT2OVd4DtKmL8XYf6tl6c3NDbRaTTtyvl+fkMyn+3Not6kohE4VMo2ItDbLkGrRWOi2J9ZRkZJLSum92Pcsz9iUiQfr5hkcwTtSOqMZlRp0d+uM7avEE+rEfyjm9oithedVmOzP+vZeOm0hPt7Um0w46HVENxGCYBTxTVc+q+dmBTLd9s70JvzHFT4JYTgyvGtD9yEELxzw3je+DmN+SMieXnTCTYfL2TJxDhe7CF1MC6tdSOtzYCPnq7koYuH2BxtOZKMkloeXZdIRKA3L1012mGxxM4mIaucslojc4dGtDntcdEbOzmaV4mnVvDwJUNZMd2+Qp7O4plvj7Hq10wAFozqzds3nNepxzucU8GbP59k+sBwu5qadwRVlbzwQzIHMst5bMGwLi2o6QglNfXsSithUr/QNqfxbkzK574vjqA3KkQGerHn0bnduiifU6Zn7ivbMJotA5ujf7nY6daEmvK70LoRQrCyCzu4P/H1UfZklCGwdF/65q7zbVZPNkd6cQ3fHMrjgsG9WlS87ChpRdUE+Xg2pv91ZIT06IKh3L36EH2CvLlyXPeHtWYM6cV/92UDcGEbqmbby9jYYN6/uX15121l96lSPt2dhcGscv17e/hk+aQ26f2YFJX/7s1GUSV/mNLXYQqbZ1Nea6Sw2sCQyACEEIT7e3FZC6HRlpg5OILRMUGkFFTz1MLh3Z55FRHoRWSAFyU1Rvr38sPXRQZzreHSI/qu5qEvj7D2QC4S8NAKnr1spN3NP6SUjP/rZir0Jrx0GrY/NLtTFnz+teUkb29NQwjBV3dMs2v67WrklOkxq7JV5cITBVUYzWqn6rg7kpSCaha+sQOTYrkmY0N82PHwHLvf/8aWk42t8G6fOaDNlZ/2kFuuZ/5rOzCrKlefF8Nzl/eM0EZT9EYzaUU1DOkdgJeueUdfqTdxNK+SsXHB3SaW57Dm4L936s1KY4f4Zy8bydjYYDy1GpsiRi0hpaWvqMSi891ZTZg3JhVgMKsoUrIv4+ye7j2D2FDfVr/7jUkFXP7WLpb8ew+f7snqIsvajtma+gcwpHcAz18+Cp1G4O2haSzus5fKOhOKKlFUSYXe2Pob2sGRnEpUa/Obn463TXTOVfD1tFTYt+TkDSaFC1/dxq2fHGDRGzsdLnLnaFw6dNPZPLIukTX7czivbwif3zoFbw8tX9w+lY1JBUQF+zSGRKSU/JRchN5oZuHoKJst3zQawfs3T+Df205x6ajenaYPcvfcgdy9+jBhfp5On8bXmezPLKPepCKBXWklXDQ8kl4BXt0eGmjKwexybnhvLwCf/nEy5/UN4dqJsQyPCiS9uIaLm6T5ZpXWsv1kCbMG92pWImHl3EGU1RpRpeyU0TzA9EHhRAX7kFFSy0o7FtJ7KiU19VToTRgVlazSWvIr6wjz97JL7LA7cIdumkFRJQMe2wCAt4eGr+88v9l2dl8m5PLk10kALDs/nusnxeHlobFbh93RSCmdyqF1B5kltdz4wV6MJhUfTy255XXMHhrBew5oNuEoHlx7hLUJuQBcNT6af15rW8q6zqgw6YWfMFp157c+MIuSmnoG9PJ3iDpre/i9n2NSSh5Zl8h3ifmMiwthb0YpXjot3951fpf2nXWHbjqIViO4YGA4XjqLw44Paz5UkF1ai0lRMZgUdp4sZt4r25jx963dFjrprAtQSsmne7J4YUMypVZ9IGclPtyPHQ/N4ZM/Tia/0oBZlWw+XtiYxucMLBjdBy+dBi+dxqYCYgN6oxmDSaHerFJtMDHvlW0senMnd60+1IXWnklnnWPJ+VU8/W1So3CcsyKE4KWrx3Ds2fmU642YFInRrPBLinPa7Q7dtMCHyyeRWVpLdLBPi1Oy5dP7cSS3Er3RjEBQb1YRWCo6m0uRk1Lya3opfl46xnag12dXsulYAc9/n4xRUTmRX8XHKya36f17T5Vy26cJBPl4sPqWKV0iAdAv3I8BvfxJKazmouGRjUJ3zsDsIRHseNiivdTS7C/M34tHLxnK6n05zBgUzur9ORhMKltPFLX4+Tlleo7nV3HBoPA2ZYd1F1JKlvx7N1UGM2v25fDLg7PalK5pMCncvGofiTmVPLpgaKPAXGdz45S+PPlNEl4eWuY0Uz3d3Tj/f78b0WpEq5WnYNHN+Wi5RUdj58kSVny0H28PLZePs62ACPD2L+m8+XMaIHntunFnxGOdhbyKOp76OonwAC+eWTyCemvnLiktqoVNOVlYzaHsCi4cHtlsufmrP52kQm+ius7M+kN5bWoa0V48tBq+Wzmdcr2xy6Vh7cHe8N7y6f1ZPr0/BpPCnowyjp+u4o8XNJ/XX1hlYP7r25EShvYO4Ks7bFeNdydSSt7YksaeDEsjjnGxwY0ZRwDmJs8NJoUNR/PpG+bXbLrwvowyjuZWUmdS+MemlC5z9NdNiuOSUX3w9tC0uIDbnfQoR6+qkm+O5KE3KlxzXmy78ohzyvQE+3oQ0M5mHdMHhXP82floRMvT24NZ5dSZFLQCjuVVOqWjf/LrJH5JKUKn1TC0dwA3TY0no6SWrFI9D148pHG/wioDi9/chUTy7+3pjIkJJqWwmucuH8m4JpWrMweHcySnAons9IrWpmg0wq4qYntIKahma0oRFw6PtGsQcDZVBhOVelO7Nee9PbR8f/cFKKq0uejfQHaZvjHTq0Et09nYn1nOO9vSqTMp/OmTBPY+Po9PVkzig50ZzB/Z+4zv6J41h9ieWowE7p03iPUHTzNzSC8evWRo43U2pHcAWiHw9dR2ebFZkE/XNvdpKy7t6IuqDXy4K5MhvQO4bGw0q/dl89fvj4O0tP97bMGwNn3ePzal8O6OU3jpNGy4+4J2X4wtXYANPHDxENKKa/D30nHDlLZ1Uuoqwvw80Wksyowhvp5oNYJ7552bzVFUZYnXG0wq2WV6TlcYqDMpPLD2CFvun9W4359mDWT6wF74e+voE+TN8lX7SS2q5qWrRnO+E0opSylZl5BLZqme5dP74aXTcMXbuzCaVd7amkbCExe2aTCRUVLLwjcs5f4rZw/sULFfa+fY+LgQ5g2LZHd6KQ/NH9Livt1FoI8OieWGFWydbU2ID7XZ9yG9uJY6k2Ux+tXNJ6k3W861haP7NNZJRAZ6s+WBmWSW6BkfF8xXB3P5+6YULhgYzktXje62hWtnoFMcvRBiPvA6oAXel1L+rTOO86dPD3I4uwJPnaCXvxdF1YbGPOL2NOT95nAeRrOKVlhaEa5LyKWkpp77Lhri8Gn/sD6BbHtwtkM/06yo3PZpAntPlXHfhYNY3kG5gmcvG8mQ3gGE+Xty2djmw1AjowP5v8lxbD1RxBXjonnrlzS8PTT0DT13AbtBAvabw3mNTV4eX3+UXxz8XTiCLclFPPnNMUyKypHcCl5bMtYieatK6owKJkVtk6Pfc6oURVExmlXWH8pjQnwon+/P5vJx0Q6XxdZqBP+6fpxDPxNgU1I+D61LpF+4P5+smNTumS9YxPnevfE8juZVcc15LVddv3TVKB77KomBEf4kF1SRV14HyHNmahEB3o3hsMfXJ1FnUvguMZ/rJ8d16SzS2XC4oxdCaIG3gAuBXGC/EOJbKeVxRx5HSkl2mR5FSlRpkYBdcUF/0opq0RuVNo/mAW6Z0Z9nvj1OkI8nZXoj72xLx6xKyvSmRu16Z+ZIbiW700vRGxVe2pjSIUdvVlRu+fgAu9JLWDatH1e0IH8ghODJhcN5cqGlu9Pk/mGcKq5hcQs3hwG9/JFIfD21DI9yTv3v1MJq6s0KqgR9vZkwfy+eu3wkq/flsGxafJs1UOYMjeCVH1Mx6Y0snx7P0lX7qDer/JBUwN7H5hLs63xrCGfzwoYTVNaZSSmo5qfkwhbPi9b44Wg+96w5TK8Ar1Yd/Xl9Q9n0Z4vwYGlNPT8kFTAuLrjFZiIDevmRXlyLEBDjpNr/XUVnjOgnAWlSylMAQog1wGWAQx393owyqupMAHhqBXOHRSCE4K0OOOSbpsazZGIsnloNq/flIIRFtVDrIjO++DBfdBpLjHJkB51nWnENB7LKkBI+2JXBE5cOs3vqO6lfaKsx0pHRQay/43yySmuZM7TzNWvaw2d7s1Cl5f9/41RLeG3JxDiWTLRP9uJsIgO92fvYXEyqipTw3PfJjb8TuMZJNqV/KMU19UgJIzp4jr2+5SRGRaWkpp6NxwrsXjwN8/fiD3aEO9fcNpVfUooYFR3U4/Tl20pnOPpoIKfJ61zgnDw8IcStwK0AcXFtv3D8vXQIYbkIo0J8HZbX27Bqfu2EGCrrjJTWGF2mAjDM34st988itbCaCfEdm6bGhfoS4utJhd7IqJjgTolvDusT6NRaPIE+HuRXGvDQaRymjKrRCLw0lnPs0xWTWZuQy2Vjoghqo7xvd/HilaO5YnwM0cE+HW5iPn9kbzJLaxGIThH58/fSsXB087PK3xMOr4wVQlwDXCyl/KP19Y3AJCnlyube097K2J9PFHI0t5IlE+PoHfT7vmN3BrX1ZjJKLG3knCn/vKsorDKwZl82I6ODzmgU78ZxnCysJtj3N6VVN22jO2WKc4HYJq9jgNOdcBzmDI102ml/T8DPS+fUTdI7m8hAb+6xkWXkxnG0VbjNTfvojGHafmCQEKKfEMITuA74thOO48aNGzdu7MDhI3oppVkIcRewCUt65QdSymOOPo4bN27cuLGPTsmjl1JuADZ0xme7cePGjZu28ftbYXPjxo2b3xluR+/GjRs3PRy3o3fjxo2bHo7b0btx48ZND8cpWgkKIYqB9nZwDgdKHGhOV+O2v/twZdvBte13ZdvBeezvK6Xs1dpOTuHoO4IQ4oA9lWHOitv+7sOVbQfXtt+VbQfXs98dunHjxo2bHo7b0btx48ZND6cnOPp3u9uADuK2v/twZdvBte13ZdvBxex3+Ri9Gzdu3LhpmZ4wonfjxo0bNy3g0o5eCDFfCJEihEgTQjzS3fbYQgjxgRCiSAiR1GRbqBBisxDipPUxxLpdCCH+Zf17EoUQ3dq/UAgRK4TYKoRIFkIcE0Lc42L2ewsh9gkhjljtf8a6vZ8QYq/V/s+tKqsIIbysr9Osv4/vTvutNmmFEIeEEN9ZX7uS7ZlCiKNCiMNCiAPWba5y7gQLIb4UQpywnv9TXcV2W7iso2/Sm/YSYDhwvRBiePdaZZMPgflnbXsE2CKlHARssb4Gy98yyPpzK/BOF9nYHGbgfinlMGAKcKf1O3YV++uBOVLKMcBYYL4QYgrwEvCq1f5yYIV1/xVAuZRyIPCqdb/u5h4guclrV7IdYLaUcmyTVERXOXdeBzZKKYcCY7D8D1zF9nORUrrkDzAV2NTk9aPAo91tVzO2xgNJTV6nAH2sz/sAKdbn/waut7WfM/wA32Bp+u5y9gO+wEEsbS1LAN3Z5xEWae2p1uc6636iG22OweJQ5gDfYWlh7BK2W+3IBMLP2ub05w4QCGSc/f25gu3N/bjsiB7bvWmju8mWthIppcwHsD5GWLc77d9kDQWMA/biQvZbQx+HgSJgM5AOVEgpzdZdmtrYaL/195VAWNdafAavAQ8BqvV1GK5jO4AEfhRCJFh7RINrnDv9gWJglTVs9r4Qwg/XsN0mruzobXWrdvUUIqf8m4QQ/sA64F4pZVVLu9rY1q32SykVKeVYLKPjScAwW7tZH53GfiHEQqBISpnQdLONXZ3O9iacL6UcjyW0cacQYkYL+zqT/TpgPPCOlHIcUMtvYRpbOJPtNnFlR99lvWk7gUIhRB8A62ORdbvT/U1CCA8sTv4zKeVX1s0uY38DUsoK4Bcsaw3BQoiGpjtNbWy03/r7IKCsay1t5HxgsRAiE1iDJXzzGq5hOwBSytPWxyJgPZYbrSucO7lArpRyr/X1l1gcvyvYbhNXdvSu3Jv2W+Bm6/ObscS+G7bfZF3FnwJUNkwVuwMhhAD+AyRLKV9p8itXsb+XECLY+twHmIdlUW0rcLV1t7Ptb/i7rgZ+ltaga1cjpXxUShkjpYzHcm7/LKW8ARewHUAI4SeECGh4DlwEJOEC546UsgDIEUIMsW6aCxzHBWxvlu5eJOjgoskCIBVL3PXx7ranGRtXA/mACcudfwWW2OkW4KT1MdS6r8CSSZQOHAUmdLPt07FMQROBw9afBS5k/2jgkNX+JOAp6/b+wD4gDVgLeFm3e1tfp1l/37+7zx+rXbOA71zJdqudR6w/xxquTxc6d8YCB6znztdAiKvYbuvHXRnrxo0bNz0cVw7duHHjxo0bO3A7ejdu3Ljp4bgdvRs3btz0cNyO3o0bN256OG5H78aNGzc9HLejd+PGjZsejtvRu3Hjxk0Px+3o3bhx46aH8/8BRrFkySOYaXsAAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def fastexp(x,n,m):\n", " z = 1\n", " while n!=0:\n", " if n%2==1:\n", " z = (z*x)%m\n", " x = (x*x)%m\n", " n = n//2\n", " return z\n", "\n", "import matplotlib.pyplot as plt\n", "x = range(0,640)\n", "y = [fastexp(7,i,641) for i in x]\n", "s = [5 for i in x]\n", "\n", "plt.scatter(x,y,s)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "no solution\n" ] } ], "source": [ "def DLPslowsolver(A,g,p):\n", " #Finds a such that g^a = A mod p.\n", " result = 1\n", " for a in range(p):\n", " result = (result*g)%p\n", " if result == A:\n", " return a\n", " print(\"no solution\")\n", " return None\n", "\n", "DLPslowsolver(15,8,100000001)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Easy case of DLP,\n", "\n", "For the additive group $G = (\\mathbb{Z}/m\\mathbb{Z}, +)$ the question is to find the a such that \n", "$$ \\underbrace{g + g + \\cdots + g}_{a \\text{ times}} = A$$ i.e. $ag \\equiv A\\pmod m$. Firstly, if $g$ and $m$ contain any common divisors, we can cancel them out, so let's assume they are relatively prime. Then if $g^{-1}$ is the multiplicative inverse of $g$ modulo $m$, we get that $$a \\equiv Ag^{-1} \\pmod m.$$\n", "\n", "Efficiently finding the multiplicative inverse is done via Bezout's lemma." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Bezout's Lemma\n", "\n", "Given two integers $n$ and $m$ and $d = \\operatorname{gcd}(n,m)$ there existstwo integers $u$ and $v$ such that $$nu + mv = d.$$\n", "\n", " Proof: Consider the set $L = \\{an + bm >0: a,b\\in \\mathbb{Z}\\}$ and consider $\\min(L)= d = nu + mv$. If $e$ is any common divisor of $n$ and $m$, it divides any integer linear combination, and so any element in $L$, in particular $e | d$. Now we show that $d$ is a common divisor of $n$ and $m$. If we had $$n = dq + r$$ with $0\\leq r prime order $g$.\n", "Also choses a private key $a$. \n", "Alice computes $A = g^a \\pmod{p}$, publishes $A$.\n", "\n", "Bob has a message $m$ which is recorded as a number less than p and greater than 2.\n", "Bob choses an ephemeral key $k$ to be used only once and computes $c_1 = g^k\\pmod p$ and $c_2 = mA^k \\pmod p$, then sends $c = (c_1,c_2)$. This is his ciphertext, which he sends to Alice.\n", "\n", "Then Alice, who doesn't know the ephemeral key $k$ can get rid of the $A^k$ factor next to the message by computing $x \\equiv c_1^a \\pmod p$ which is equivalent to $A^k$ and then computes $x^{-1} c_2 \\equiv m \\pmod p$." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import random\n", "\n", "def ElGamalKeyGenerator(a,g,p):\n", " A = fastexp(g,a,p)\n", " return A\n", "\n", "def ElGamalEncryptor(A,g,p,m):\n", " #encrypts a message using the ElGamal encryption technique\n", " k = random.randint(p//2,p-2)\n", " c1 = fastexp(g,k,p)\n", " c2 = (m*fastexp(A,k,p))%p\n", " return (c1,c2)\n", "\n", "def ElGamalDecryptor(c, a, p):\n", " #The ciphertext should be in the form (c1,c2)\n", " (c1,c2) = c\n", " x = fastexp(c1,a,p)\n", " m = (c2*inverse(x,p))%p\n", " return m" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "p is Prime: True\n", "message is: 7955827\n", "ciphered is: (392864368, 363130765)\n" ] } ], "source": [ "from sympy import isprime, factorint\n", "p = 1234567891\n", "g = 2\n", "k = random.randint(p//4, 3*p//4)\n", "print(\"p is Prime:\", isprime(p))\n", "\n", "A = ElGamalKeyGenerator(k,g,p)\n", "\n", "plaintext = \"yes\"\n", "m = int.from_bytes(plaintext.encode(), 'big')\n", "print(\"message is:\", m)\n", "c = ElGamalEncryptor(A,g,p,m)\n", "print(\"ciphered is:\", c)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "decryption gives 11362729\n" ] } ], "source": [ "m = ElGamalDecryptor(c,a,p)\n", "print(\"decryption gives\", m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ElGamal is as Difficult as the DHP\n", "\n", "Let us have access to a Diffie-Helman oracle, meaning that there is a function (whose inner workings we do not know), such that $$\\operatorname{DHO}(g,p,A= g^a,B=g^b) = g^{ab} \\pmod p.$$\n", "\n", "With access to such an oracle we can crack the ElGamal problem, if we intercept $c = (c_1,c_2)$ and also the integers $A, g,p$ which were public information to begin with. Note that $c_1 \\equiv g^k \\pmod p$ and $A \\equiv g^a \\pmod p$ so that we get,\n", "$$\\operatorname{DHO}(g,p, c_1 = g^k, A = g^a) = g^{ak} \\equiv A^k \\pmod{p}$$\n", "And so we can then find the multiplicative inverse of $A^k$, multiply it by $c_2$ in order to obtain $m$. \n", "\n", "Conversely now assume that we have an ElGamal Oracle, such that $$\\operatorname{EGO}(g,p,A = g^a,c = (c_1 = g^k, c_2 = mA^k)) \\equiv (c_1^a)^{-1} c_2 \\equiv m \\pmod p,$$ i.e. somehow the oracle decrypts the ciphertext efficiently. Now we want to solve the DHP, and so given $A = g^a$ and $B = g^b$, we input $$\\operatorname{EGO}(g,p, A = g^a, c = (B = g^b, 1)) = g^{-ab}\\pmod p.$$ Taking the inverse modulo $p$ of the output gives us the solution to the Diffie Helman Problem.\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Baby-Step Giant Step\n", "\n", "There is a method to solve the Discrete Logarithm Problem for any group $G$ in $O(\\sqrt{N} \\log(N) )$ many steps, where $N = |G|$. We are trying to solve the problem $$g^x \\equiv h \\text{ in } G.$$\n", "\n", "Let $n = \\lfloor\\sqrt{N}\\rfloor + 1$. Note that $n > \\sqrt{N}$. Make two lists, both of length about $n$.\n", "- $e, g, g^2, \\ldots, g^{n-1}$\n", "- $h, h*g^{-n}, h*g^{-2n}, h*g^{-3n}, \\ldots , h*g^{-n^2}$.\n", "Find a match between these two lists (which exists). Then we have $$g^i = h*g^{-jn}$$ for some $0\\leq i < n$ and $0\\leq j \\leq n$. This means that $$h \\equiv g^{i + nj} \\text{ in } G.$$\n", "\n", "If three is a solution to $g^x \\equiv h$, then there is a match between these sets. To see this, first divide $x$ by $n$ with remainder. Since $x < N$, we have that $x = nq + r$ with $q \\leq N/n < n$, and $0\\leq i < n$. In that case $h = g^{q n + j}$, or in other words $$h*g^{-qn} = g^r$$\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Solves g^x = h in Z/mZ\n", "from math import sqrt \n", "from math import floor\n", "from sympy.ntheory.factor_ import totient as phi\n", "\n", "def BabyStepGiantStep(g,h,m,N =None):\n", " #solves the Discrete logarithm problem if g has order \n", " #$N$ in the group Z/mZ\n", " if N == None:\n", " N = phi(m)\n", " n = floor(sqrt(N)) + 1\n", " G = fastexp(g,n,m)\n", " L1 = [fastexp(g,i,m) for i in range(n)]\n", " L2 = [(h*inverse(fastexp(G,j,m),m))%m for j in range(n)]\n", " common = set(L1) & set(L2)\n", " if common==set():\n", " print(\"There is no solution\")\n", " return None\n", " else:\n", " c = common.pop()\n", " i = L1.index(c)\n", " j = L2.index(c)\n", " return (i + n*j)%N\n", "\n", "BabyStepGiantStep(16,fastexp(17,4,101),101,N= 25)\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "95" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fastexp(16,5,101)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "30" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "BabyStepGiantStep(2,17,101)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "17" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fastexp(2,30,101)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "100" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fastexp(17,25,101)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pohlig-Helman\n", "\n", "There is a way to attack the Discrete Logarithm Problem. This depends on whether $p-1$ has a lot of small prime factors. The method requires the so-called Chinese Remainder Theorem.\n", "\n", "### Chinese Remainder Theorem\n", "Let $m = m_1m_2$ with $\\operatorname{gcd}(m_1,m_2) = 1$. Then there is an isomorphism of rings:\n", "$$ \\begin{align*}\\mathbb{Z}/m_1m_2 \\mathbb{Z} &\\longrightarrow (\\mathbb{Z}/m_1\\mathbb{Z} ) \\times (\\mathbb{Z}/m_2\\mathbb{Z})\\\\\n", "x \\pmod {m_1m_2} &\\longmapsto (x \\pmod {m_1}, x\\pmod {m_2})\\end{align*}$$\n", "which does also translate to an isomorphism of their group of invertible elements:\n", "$$ (\\mathbb{Z}/m_1m_2 \\mathbb{Z})^* \\longrightarrow (\\mathbb{Z}/m_1\\mathbb{Z} )^* \\times (\\mathbb{Z}/m_2\\mathbb{Z})^*$$\n", "\n", "The inverse of the above map is given as, \n", "$$ \\begin{align*}(\\mathbb{Z}/m_1\\mathbb{Z} ) \\times (\\mathbb{Z}/m_2\\mathbb{Z}) &\\longrightarrow \\mathbb{Z}/m_1m_2 \\mathbb{Z}\\\\\n", "(x_1 \\pmod {m_1}, x_2\\pmod {m_2}) &\\longmapsto x_2 m_1\\overline{m_1} + x_1 m_2 \\overline{m_2} \\end{align*}$$\n", "where $\\overline{m_1}$ is an integer such that $m_1\\overline{m_1} \\equiv 1 \\pmod {m_2}$ and $\\overline{m_2}$ is such that $m_2 \\overline{m_2} \\equiv 1 \\pmod{m_1}$.\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX8AAAD8CAYAAACfF6SlAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzt3Xd4HNXZ9/HvvbuqVi+23GWDMdgUA6YYiDHN9JJAKKEmPHEAE0oIAR4S6pNAqAkQWiimV4MBF9zANPfeuyVbxZIsq/fdPe8fWudVhIQka6Qjje7PdenS7pQ9P82Obo1m58wRYwxKKaV6Fo/tAEoppTqfFn+llOqBtPgrpVQPpMVfKaV6IC3+SinVA2nxV0qpHkiLv1JK9UBa/JVSqgfS4q+UUj2Qz3aApqSkpJj09HTbMZRSqttYtmzZHmNMamuX75LFPz09naVLl9qOoZRS3YaIZLZleT3to5RSPZAWf6WU6oG0+CulVA+kxV8ppXogLf5KKdUDtVj8RWSgiHwtIhtEZJ2I3BqaniQis0VkS+h7YjPrXxtaZouIXOv0D6CUUqrtWnPk7wfuMMYcAhwPTBSREcDdwFxjzDBgbuj5fxGRJOB+4DjgWOD+5v5IuE1BcQn/98m7LFi/3nYURy3YuIYnZrzNnpIS21Ec9eHiL3hn4ae2YziqrKqC1xe8xMJti2xHcdTG3DV8sPRpCsrybEdx1PytXzBn/esEA4FOaa/F4m+MyTXGLA89LgM2AP2BC4E3Qou9AVzUxOpnArONMXuNMUXAbOAsJ4J3ddd+/RCLkhbwt7wXWLl1m+04jli2dSNvljzGtuSZ/HHBXbbjOObvs/7BzuhnyY15gQen/9V2HMe8uuqXxKe8QG7wd675A5BdtJPK6gs4JOVpVmWfbjuOY2aseZ5RUX9iTPxjfLHqd53SZpvO+YtIOnAksAjoY4zJhfo/EEDvJlbpD+xq8DwrNK2p154gIktFZGlBQUFbYnVJ3sRaPD4DAou2bbQdxxHLdm4AAZ8vSFRihe04jtkT3IzXG8TnDVIe7o4/1ABpCflE+vwYYH3eMttxHLGtYD3hHj9RPj8De+2lzu+3HckRtXUr8UmQKG+AvlFbO6XNVhd/EYkBJgO3GWNKW7taE9OaHDHeGPOyMWa0MWZ0amqreyh3WQN3DSNQ48Hk9uKaU86wHccRV514NpV5CdTWeInLPtp2HMdcmP4bSsp7UVoRzem9r7MdxzF78y+lrCaCrL1pXHzkVbbjOOLEA85gRf5ISusi+H7X+YT5uuRNCtps5IBbyKiKZ3dNNNXe33dKm2JMk7X4vxcSCQOmAjONMU+Fpm0CxhljckWkLzDPGDO80XpXhJb5Xej5S6Hl3vup9kaPHm309g5KKdV6IrLMGDO6tcu35mofAV4FNuwr/CGfA/uu3rkW+KyJ1WcC40UkMfRB7/jQNKWUUha15rTPicDVwKkisjL0dQ7wKHCGiGwBzgg9R0RGi8grAMaYvcDDwJLQ10OhaUoppSxq1WmfzqanfZRSqm0cP+2jlFLKfbT4K6VUD6TFv5GMvDxueusZnp/xhe0ojpq2fD53TH6chZvW2o7iqOe/fp2/fvk4pVXu6Xewt7yIp+c9wJsLX7cdxVHLMubz2oLbWLzjO9tRHDVr3atMWX43RZV7bEdpEy3+jdz03ePsGriFGVGzeOurObbjOGJHXg5T616gatAqXi98nFp/ne1IjvjHnJcoT/mAsP5zeeibO2zHccyrK3/DoP6f0Sv5Gd5e9EbLK3QDZVUliLmSY/tNJkyupqjSHdd9zFk/iRMTnmB8nyms3f4r23HaRIt/Y7389T1zgW2FOZbDOCN77x7EY/B6Db5wP9W1tbYjOWJvbR4i4PMG8Ua5515DMdHFhHvr7+9SWNWmkfm6rLKacqK8dUR4A0R4/BRXuKP4V9TUvz+R3iC9I4stp2kbLf6NXOg5g7q94Xh3xfOn8y+1HccRJx1yON6Mg6kojiJh1xjionvZjuSIG8fcSP7uNAr2JnBa0s224zgmPfwudhWlsC1vKNcee6vtOI7ol9CfBVmXk1mezMLsSxiSeqDtSI447ZDbWVh4ABvKkikw99qO0yZ6qadSSrmAXuqplFKqRVr8lVKqB9Lir5RSPZAWf6WU6oG0+CulVA/kjpEQgM1Z2fxl9uskeeN47sqJeL1e25Ec8f4Pc5iVO4fjk45nwqlNjZTZPT0y82kK/Tu5euQNHJE+vOUVuoHdJflMWvYAXmK45aSHiQiPsB3JEd9vmc2mPS8RH3Eqlxx1k+04jvli5WMQXMmQPrdxaP9jbcfpdK458r/tu2cpH5LHzoFbuecjd3SLL6+q5KuwN4kcmsWy2MlsydnV8krdwCvfvg/9ZtE7fT3vZt1nO45jJq28lYMGzmfowNk8+/2DtuM4JszzO07oP5+Dkh5hxU53jAX8w5bPOSX1Vcb3XUxUTeeMmdvVuKb4G28QCQ0aWRNwRw9WfyCIyP/vh1Fd547bMlT5KwEQAW+oJ6sbeDy1eMQgGIJU247jmHBPAE/od6u6rspuGIfUBiow1I8zG+Fxzz7YFq0Zyes1EckXkbUNpn3QYGCXDBFZ2cy6GSKyJrRch/ba+suh1yG7YonJTOWRi3/TkU11moSYGEYUnUtZdiIDck/msMFDbUdyxE0nX0vJziPZndOP0+Pcc0+ei4Y9xqac4WzKHsWE4++3Hccx2eV/Y3n+QSzLvYYxB4yzHccRpxx8BbN3n838wqHs9D9iO44VLfbwFZGxQDnwpjHm0CbmPwmUGGMeamJeBjDaGNOm291pD1+llGqbtvbwbfEDX2PMtyKS3kxjAlwKnNraBpVSStnX3nP+PwPyjDFbmplvgFkiskxEJrSzLaWUUg5p76WeVwDv/cT8E40xOSLSG5gtIhuNMd82tWDoj8MEgEGDBrUzllJKqZ+y30f+IuIDfgF80Nwyxpic0Pd84FOg2YtpjTEvG2NGG2NGp6am7m8spZRSrdCe0z6nAxuNMVlNzRSRXiISu+8xMB5w1xiCSinVTbXmUs/3gAXAcBHJEpHrQ7Mup9EpHxHpJyLTQ0/7AN+LyCpgMTDNGPOlc9G7ttfnTeXKL27mto+fsB3FUX+e/hB//OoaPlg01XYUx+wuzuORb37Fo99exo4Cd4ycBfDVxqm8u/xkXv7htwQC7rmWffKy/+X7dSczc92rtqM4prCklIsmPcC5b/8vyzY39xGqs3Qwlw5y/YLrCAsPEPALZ5nrufj4k21HarePl8xgS+QzhPmCVFaHc9+R7hjk/m9f/Y7hg5YAhs3ZI7nn5LdtR3LEV5sPoXdkKbVBH5nF9/PzUd2//8uqrPkMkWuI8ASpDnqJ7rOeMF+Y7Vjt9ptJT5E7OAMRMDm9mPGrtvc90MFcuoiA38O+v6uxUVF2wzgkLiIWBIIG/AF33DsJwEMUQSMYI5iAO94rgBp/GMYIAkSHxduO44hIXwwGIWigJuDFI+4oYdHeCDACBnz+zvndcseW64Kujr+ZwI7BHFJ0NuOPcMdNo8YffhJxBZdRsONQxsf+xXYcx/z+xL+xY9fpbNt1ChOPf9J2HMcMjHuDBdknsz7/Zs4cebHtOI4YnnY4i4rvYWbuCWQGn3PNDRyfunwCg7OGkpjRjxfPuq1T2tTTPkop5QJ62kcppVSLtPgrpVQPpMVfKaV6IC3+SinVA2nxV0qpHsg1Y/g65eW5U/ieaZiSWF46929ER0TajuSIP029h7CULUQUHsd9595pO44jcovyeGvDBKIiKjg48h7OGHma7UiOmL1+CrXmAYqqkjhvxMckRCfZjuSIyUtv57DEeawuOolLRj9rO44jCktKueqLR/HH1nJFr/H85vTxtiO1mh75NzLf9wXRCdVE9C/kH7N+6oal3cf8TStIGLyK+LgKwgd/TUllme1Ijnhz+dMMTsmiX3wha8rdcxuN6uCDDIkrYETKNj5Z+bjtOI7ILd7FmX0/Z3B0CWf1nUFm4TbbkRzx8BfvEexXiS+xjvcqZtmO0yZa/Bvxl0cS8AuC4YAkd9xaekByGsGgB3/AQ3VtGNHh7ujFmhQxCINQF/RSVZliO45j9lalUB2o/6c8IepAy2mcER+VQGUwjOqgl6qgl4Qod/w3c2BSPwCCfvCVh1tO0zbayauRnMI9/HPeOxySfCDXjTvXSoaO8PW6RXyT+TUXHXIho4YcYjuOY95Y8DrFNXn8z5hb6BURbTuOI0oqS/hk1eMkRh3ARaN+bTuOY9blLGFj7kcMS/sFh/c/3nYcxzw37XM2FWXzwPlXkhwfZy1HWzt5afFXSikX0B6+SimlWqTFXymleiAt/kop1QO1ZiSv10QkX0TWNpj2gIhki8jK0Nc5zax7lohsEpGtInK3k8GVUkrtv9Yc+U8Czmpi+tPGmFGhr+mNZ4qIF/gXcDYwArhCREa0J6xSSilntNjD1xjzrYik78drHwtsNcZsBxCR94ELgfX78Voten72JyyOmoa/Kox7ht/FyEFDOqKZTnfH1DuJG7iRopyBPDn+WVcMXpFXks97m64mObaYioIruWHsLbYjOeLLdZ8QGX4P1f5w0mImMWrg0bYjOeLjpTcyts9cVhcN5uQR010xbGJRWTmXTX8YSa7hoNyDePbqm2xH6nTtOed/s4isDp0WSmxifn9gV4PnWaFpHeKH4GzCI/1ExlXz4qKPOqqZTpVXXEjSkHWEhwVIGZDJwq2rbUdyxIcrJtEnvpBe4bX4Ej+0HccxhTVPkxxZQVqvYhbu/KftOI45s99MYn11HJW0gwXbp9mO44gX50xDUmrwhBs2p3XOgOldzf4W/xeAA4BRQC7Q1Nh30sS0ZjsViMgEEVkqIksLCgraHCiiJJmAXzAGjkg+uM3rd0VJMfGUV0RR5/dSUxfGwX3d8d/MiN7HIECN30fB3g47Huh0ZVWHUR3w4Q96iQ8/xnYcx2wtT6Yy4KPOeDkw9UjbcRwxdtihAATrBPZEWE5jR6s6eYVO+0w1xhza2nkiMgZ4wBhzZuj5PQDGmBaHpd+fTl6BQIB/f/0FgxL7cM7RY9q0bleWXZjPZ6tncsbwsQzrN9h2HMcs2LqYbXs28sujLiMi3B2/fIFAgOnrPiQ2IoFxw8+2HccxRRWFLNj+EQennczQVPf0Dv9h7Trmb9vAhNPOJj6ml+047dYhPXwbF3gR6WuMyQ09vh04zhhzeaN1fMBm4DQgG1gC/MoYs66l9rSHr1JKtU1bi3+LH/iKyHvAOCBFRLKA+4FxIjKK+tM4GcDvQsv2A14xxpxjjPGLyM3ATMALvNaawq+UUqrj6b19lFLKBfTePkoppVqkxV8ppXogLf4dqLSqgkAgYDuGowKBAGVVFbZjOK6mroaq2mrbMRxXUVPmyn2wpNx9+2Ctv47yqspOa0/H8O0gt0+9ndQhmyguieWew/9NYoy9QR6csqdsL+9v/SW9Y4vZnHksfz7tBduRHPHluikkRP0BjwTJKXmIi0ZdYzuSIz5cMoGz+89kS3UcCckzSIsfYDtSu5VVVvLz6Q/gSaklPCOeqdc9aDuSI6YtW8BHNa/g8QY5ZM/p3HnulR3eph75d5CkwVsQgZiYSj5fNcd2HEd8uW46CdHliED6gGW24zhmZ+kbRPnqiPAGKKp9y3Ycx5zYZx4egeTwShbtcEdP6qlLFiGJdYhAbXoJtXV1tiM5Ysq22XjDAni8huUs6JQ2tfh3kMLcPvgDHurqvJxykDs6nZ10wMnU+n3UBTzszHNHb2OAhLCzqA14qQ168QbH247jmGWFh1AT9FIX9DCy35m24zji1MOOwFR7MAEwuZGEh3X/+wwBnNTnGIIBIRgQ+lcN65Q29VLPDlLn9zNvw2KOGHQIveObuvVR95RfsocNuZs4adjxrrjJ3D4bc9cTCAYY2f8w21EcEwgEWJX1AwOSDqJ3bJrtOI4pLCll/ob1nH7UUUSFd69B03/Khl2ZFFeUMebgH91IoVV0DF+llOqB9Dp/pZRSLdLir5RSPZAWf6WU6oG0+CulVA+kxb+RQCDA9xuXs7uo7QPKdGVlVRV8u2k+NbU1tqM4amfhTtZkrbQdw3Hrc5ayuyTLdgxHVVZXM33xEsoqO68Xa2fIzM/ju/Xdb5Q9Lf6N3DH9TubWPsDzGb9l6TZ33IG6rKqCNzadz05u55nlF7umu//s9VPJKh1Hhf8iXvzuDttxHPPhkgmkmV/iKRvHksyvbcdxRG1dHedNu4+nyt7lwi/vp6q21nYkR8xZtZT7t93D62VPM+GDh23HaRMt/o1E983A5w3i8QSZs2We7TiOWJa5koSoCsK8QQYm51FWXW47kiO27p2GTwKEe4IkxX9nO45jRiQuIsITxEuQjIKptuM4YnN2Dp7EOsQLngQ/q7fvsB3JEV9u+QERg8drqEzd1fIKXYgW/0aCuUcQNFBTG8bFh59nO44jxgwdTW5RCsbA1pwDSOgVbzuSI47seyVVgXDqgh6qKi+2HccxG4rPwx8UKgNhHNr/attxHHHIwAFIbhTGALsjGT3sQNuRHHH5qLMI1HkxQUgrHGE7Tpu02MlLRF4DzgPyGwzj+DhwPlALbAN+bYwpbmLdDKAMCAD+1nZAsN3Jq6ishJioaMJ87ug6DqE7IVaVkRSTYDuKo2pqa6gJ1BAX1f1vnNdQeXUpEb4oV+2DAPnFJfROcMfBxz61/joqq2pIiI2xmqMjOnlNAs5qNG02cKgx5nDqx+m95yfWP8UYM6otoWxLjI133S+d1+t1XeEHiAiPcF3hB4iJjHPdPgi4rvADhPvCrBf+/dFi8TfGfAvsbTRtljHGH3q6EOj+94pVSqkexIlz/r8BZjQzzwCzRGSZiEz4qRcRkQkislRElhYUuOsyS6WU6mraVfxF5F7AD7zTzCInGmOOAs4GJorI2OZeyxjzsjFmtDFmdGpqantiKaWUasF+F38RuZb6D4KvNM18amyMyQl9zwc+BY7d3/aUUko5Z7+Kv4icBdwFXGCMabK7noj0EpHYfY+B8cDa/Q3akkAgwBvfT2HO2oUd1YQVu4sLmDT/DTIKutc1xC1ZnrmYT1a84boex19t/JAF22bajuGo/OISHp8ymVXbttuO4qjFmzfw3MzJlFdV2Y5iRYvFX0TeAxYAw0UkS0SuB54DYoHZIrJSRF4MLdtPRKaHVu0DfC8iq4DFwDRjzJcd8lMAf5h2N1tjJvFt4FHenv95RzXTqer8fiZnXIYn6UVm5/2KveU/upq2W/puy1yqg5eTFv8gbyz/he04jvlgyU2M7HUXB0TcwBern7UdxzGXz/krX/b6gT9sfY7Nu7Jtx3HE/I3reG7PEyyOm8b1M++2HceKFgdwN8Zc0cTkV5tZNgc4J/R4O3BEu9K1gSTkEOYLEggIawtXAxd0VtMdpqiimKReZXgEPBJkS942jos52nasdtuyZz4Hp0Gkz8+gxAzbcRyTGrWGKG+AgIGqmsW24zjGk1SHeCDoFxZu3shBA/vbjtRuC7avhgSD12cIT62wHccK1/TwHRG4gOqaMMrKo7lmVFN/r7qf3vEpbMk8ihq/jx05wxidPsp2JEecM2IC2WUplNeFk1d0je04zvH9nsLaKHKq4xjR7xbbaRzTZ0c/gnWCNzeSX/7sZ7bjOOI3PzufmsJe+Os89M5xz9CdbaHDOCqllAvoMI5KKaVapMVfKaV6IC3+SinVA2nxV0qpHkiLv1JK9UBa/DvI9rydPDH3r8xcM9d2FEfN3TCdl364l52FO21HcUwgEGDKyqf4ZPnfqfPX2Y7jmJ15+Ux84wUmzZljO4qjZixbxB0fPcOaHe7qcfz8V+/wyIznqaqp7pT2tPh3kM+z/4eUAdPIDfsLy3Z0v8Gdm7IsczHhkbcwst/7LM51T8/cj5f9ieOSn2FM6otMXjHRdhzHXDvvKTb028KbZgaTv//BdhxHrN+ZyTvVr5DXfzV/zXjMdhzHPPbli+xO+ojKvrO4e+a9ndKmFv8OEh9dQbi3fqD0jL3uGK90V/FWACK8AVKiSi2ncY7Xk0GYBAn3+In2uec/GmL9iA+MgQ15WbbTOGJbXjbiCfXMjaqjts4d/6kV1OYgHoPPGyQYVdQpbWrx7yCVuy9nT3ksmdmHcNEod4wFfO7IS1mTewQ5FQnsLLjBdhzHHDHwQdaX9mVTaR+G9H7IdhzHnFl9HIESLxHZvbjj/J/bjuOIc446Dk9Gf6pLw+mbdTThYe4Y7ezG435HUX4SxUWxnNf7+k5pU3v4KqWUC2gPX6WUUi3S4q+UUj2QFn+llOqBWlX8ReQ1EckXkbUNpiWJyGwR2RL6ntjMuteGltkSGvpRKaWUZa098p8EnNVo2t3AXGPMMGBu6Pl/EZEk4H7gOOrH772/uT8SSimlOk+rir8x5ltgb6PJFwJvhB6/AVzUxKpnArONMXuNMUXAbH78R6RLWZe9mQdm3cpz856zHcVRn618j2e/u5avN86yHcUxgUCAD5b8L+8vvp780t224zhm865sLv3337ntzX8TCARsx3HMe9/P5dr3HuCtb921D/51+r+4/bN72ZzTvfqItOecfx9jTC5A6HvvJpbpDzQceTwrNK3Lmpp1O+mDFxOV9h7vL/7YdhxHbMvfRmLcXzhm4LcY3+9dM2j6pysfZmzau5zabw6Lt19tO45jbvjmX+QPyWdl2iYe/Ph923EcUVBSzDTPe5ihu5jp+5CcwkLbkRzx/Lx3qeo3h5gh63h2/f2247RJR3/gK01Ma7JjgYhMEJGlIrK0oKCgg2M1LzysFo8YMFBW444B0ytrKxABEQj3+gkYv+1IjvAHSxHAK0EivVW24zgmGBb8z29OaU2l3TAOqa6t/c8+KAKVnXT/mo5WVlMGgEcMnrDu9XvVnuKfJyJ9AULf85tYJgsY2OD5ACCnqRczxrxsjBltjBmdmprajljtMyLsHjLz+pOVNZrfnPBrazmcdNiAw9mQfRUb9gwms+CPREf0sh3JEeceej/f5x3F4j3D6Jv8jO04jrl76C/xZkcSn5nA3y51x380A1N7MyzvRKp2xzB09xgO7NelTwC02h9Ov56yncPYk5vKhcm/tx2nTVrdw1dE0oGpxphDQ88fBwqNMY+KyN1AkjHmT43WSQKWAUeFJi0HjjbGNP784L9oD1+llGqbDunhKyLvAQuA4SKSJSLXA48CZ4jIFuCM0HNEZLSIvAIQKvIPA0tCXw+1VPiVUkp1PL23j1JKuYDe20cppVSLtPgrpVQPpMVfKaV6IJ/tAE5ZkbmOz7b/DeoSuWvcE0SFR9qO5IgPl75CSfADwgJnct2YP9qO44hAIMAHS28kJmI7/RL+wuj0k21HcsTaHZnc8fVrRAR8vH7pLSTHx9uO5IhX507jy+KvGBI4gMcuvcl2HMfc/fmjlIRlcHbvK7jgaHfsg23hmiP/aVl/Jr3fNgYOWsFz3z1tO44jSqtK6Zv0KIf32coBaS+yZfcm25Ec8cWa5xjbbxZjUjcSqLnVdhzH3D7vFWoGlVOaXswtH/7bdhzHzI34jMgBJWQPWMHM5Utsx3HEWz98jgxcQnL/PObVvWA7jhWuKf7BgBcT6hYZJuGW0zhD8BA09T+TMeDzuWPIOp8nCsEQNEJd0Gs7jmO8xvOf/uthHtf8U40JCvsuCowKd8fvVqSv/syAAYJB15TBNnHNT33V8KfI3Hkk+TtP5/cn32Y7jiNio2KoqHyMJbuOoaD4LwxJGWo7kiPOO3wC3+2+mnm7x5CaMMl2HMe8fO5EkjNSGJjZj+evdM8Yx5dFXI3Zkcaovacy9tAjbMdxxC+PG0/c7vGUZBzAxUl32o5jhV7nr5RSLqDX+SullGqRFn+llOqBtPgrpVQPpMVfKaV6IC3+SinVA7nnYuQu5q3F/yIsahL5xSOYeMJreL3d/3r2QCDAh8t/RXrcRvKrJ3DhERNtR3LE6m07uPWHVzBewyOjrmbMyENsR3LE8zOnMDc4l/CSON64+AHCw9zRT+T2KX8hkLyDvuUncc/Z7rikNrtwN6+svZWw8GrGJt/LSQcd2+Ft6pF/B+mX/AyD4go5rP8CZq7/3HYcR8zd9AEnpi3kwNg9HJr4hO04jrl37tsE+9Zgetdy/0J3jJkLMC98JpFJ1ZiBBTw76xPbcRwxc/V8ItPXE59QQVm/WdT562xHcsSry55mQFoWfZML+CrvsU5pU4t/Bymu7kVtwAMY+sQNbHH57qB3TDqCoSbopbA6xnYcxyR74iAoEIT4QLTtOI4JVIYRDAgCpCf2tR3HEQMS+oCBQECoqQ7DI+4oYbG+NIJBD/6gB39NYqe0ud9bTkSGi8jKBl+lInJbo2XGiUhJg2Xua3/k7uHw5PdYm30h1ZWPc/TgVve76NJGDTqBzeVP8m3OL0hNnGw7jmNe/fXNHJM/giN3D+fN6263Hccxj466i5Sdh3BK5flcfMJY23EcMXLQARwXmEhw5zFckfyAK06nAtxy8i3U5v2K4qxzuetn/+yUNh3p4SsiXiAbOM4Yk9lg+jjgj8aY89ryetrDVyml2sZWD9/TgG0NC79SSqmuy6nifznwXjPzxojIKhGZISIjHWpPKaVUO7S7+ItIOHAB8FETs5cDg40xRwDPAlN+4nUmiMhSEVlaUFDQ3lhKKaV+ghNH/mcDy40xeY1nGGNKjTHlocfTgTARSWnqRYwxLxtjRhtjRqempjoQSymlVHOcKP5X0MwpHxFJExEJPT421F6hA20qpZRqh3b18BWRaOAM4HcNpt0AYIx5EbgEuFFE/EAVcLnpigMINPD6/KdJTX6N3WUpXHzwZBJjkmxHardAIMDkFT/nyNS1LM47hSuPfdV2JEes3raDictexkQG+ZV3HDede7btSI54ZsYnfB85m0BFGE8ecw/pfdxxjf7vp9xNRP/tVGWn86+LOqcjU0fLKtzNpE03EBtTRkzptVx/0jW2I7Vau478jTGVxphkY0xJg2kvhgo/xpjnjDEjjTFHGGOON8bMb2/gjpaYOIn4iCoGJ+YyebU7iuSq7AWckLaShLAaTu//JWVVJS2v1A38/atPIcGPp1eQ90u/sx3HMd/IV4RNnil+AAAWLUlEQVRF+wlLrOYf85r6KK372Zq7k5j0LURE+IlL38aazK22Izni3RWvk5K4l9jIGgojm7vmpWtyR/c4B+WU9KPa70OAYclH247jiIGJw6gO+KgM+MitjiM63B29c0clp4MB44eEMnf8TAC+4jgC/vqeuUekDrMdxxH9k3pTUx1GXZ2Hmhofg3u747+ZYYmHIwi1fi+lJX1sx2kTHcaxkYqaCj5Z+QZDkw/nxANPspKhI2zN38Cq7OmcOOQy0hIG2I7jmLe/mkfW3j3c+fOfu6a3Z3VtLc/N+oQDUwdw0XEu2gdzd/LZqrmcd+gpDB+QbjuOY2av/ZaMom1cfdyviAyPsJajrZ28tPgrpZQL6Bi+SimlWqTFXymleiAt/kop1QNp8VdKqR7IVcW/zu8nEAjYjuG4Or/fdoQOUVvnjlGYGqqtq3PlPljrkhGzGnPr71ZruGYM39fmP0l62kuU10YyKOoNRg0+0nYkR3y07GxO6rOK5YVDGT9yHmG+7v+Wbczcxf8sfw6JCXLIznRevt4dYwH/c/pk5sfNIhgQro2+lvOOGWM7kiNunPIn4oZsp2RPHE+c8BwxUd1/tLO84kJe23INyXGl5GScyANnPmo7UqdzzZF/eK+PCfMEiQmv5tuMN23HcURBWR4n9lmFCByWlMnaXHdc/vrCvC+R6CDigfUpO23Hccy8mu/x+Aze8CAfbJ5lO45jYodsRwRiEsuZtsodPamnrP6MuF4VeASS+y+2HccK1xT/PcVHUxvwEjQehiefZjuOI5KiU9ha1pvqgJf86hgO6n2o7UiOOHfEaDCC8UN8nnt65qbXDCUYEExAOD7lCNtxHFOSl4jf76GuzsdJw9zxH/XPhp5EMOihLuAhL989nR7bwlWdvL7f8i0pMX04uO/wDkhlR0VNOUsz53H4gBNIjO7+N5nbZ33GTjbsyuKiE45zTc9cgDkrlxEfFcMxw92zD1bX1jJj9Q8cP/Qw+iY1eUf2bmnnnhzW52zktBFjXXE6VXv4KqVUD6Q9fJVSSrVIi79SSvVAWvyVUqoHcmIA9wwRWSMiK0XkRyfqpd4zIrJVRFaLyFHtbVMppVT7OHXkf4oxZlQzHzacDQwLfU0AXnCozS4tEAiwLns5FTXltqM4am9ZOT+sWe+6XqxbsnPYvGuX7RiOW7p1PUVl7hi5bZ+K6koWb1/lun0wpziHLXmdN8JZZ1zfdCHwZmjs3oUikiAifY0xuZ3QtjWfrjybY3qvZ3NWNP1Sv6FPXPcfuWh7Ti5XL/knRAaJXtiL2b+933YkRzwz41O+i63vlHXk8pP43wuvtJzIGTdOuZOYwRnU7fUxoe/fGDFwiO1I7VZcXsrLmy4jrlcFU7/rx0Pj3rcdyRHT13yBN/ouvBJk7ndXccPP/tzhbTpx5G+AWSKyTEQmNDG/P9DwkCorNO2/iMgEEVkqIksLCgociGXX6N4bCPMEiQurZlmmO3p7Tl64EMKDiBcqB1bYjuOY74uW4fEaPF7D0upVtuM4JrL/Lrxeg9cbYNrar23HccT3WxcRG1WFz2MY2DfbNffm2VQ0lXCPnzBPEF/03E5p04nif6Ix5ijqT+9MFJGxjeZLE+v8qHOBMeZlY8xoY8zo1NRUB2LZtWD3UQSMUFAdy/FDz7MdxxFXnDQWqjyYIMRnxtmO45gze59A0C8EA8LYmGNtx3GMP/sAgkGoq/Xxi1Fn2o7jiLHDT6CoPJaggcysIa7onAVweOrF1ATCqAt6kOrzO6VNRzt5icgDQLkx5okG014C5hlj3gs93wSM+6nTPm7p5JVbnEVKTJprdlCov2tlVsEehvbr/qexGtpbWkogGCQ1IcF2FEft3JNH77hEIsPDbUdxTJ3fT25xPoNS+tmO4qiyqgqq/VWkxu5fL+pO7eQlIr1EJHbfY2A8sLbRYp8D14Su+jkeKHH7+f59+iYMcFXhBwgPC3Nd4QdIiotzXeEHGJTSx1WFHyDM53Nd4QeIjeq134V/f7S3MvUBPhWRfa/1rjHmSxG5AcAY8yIwHTgH2ApUAr9uZ5tKKaXaqV3F3xizHfjR7QtDRX/fYwO444btSinlEtrDVymleiAt/kop1QNp8W+kzu/ny7XvsjF3je0ojtqek8s/Pvuc/GJ39facu2oFb82b46renoFAgHd/mM4PG93T5wBgd1EBby/4iJyiPNtRHLUicyWfrfq42+2Dej//Rj5cejZH916HAYqD7zA6/WdWcjgpv7iEi755BMINlHn57uKHXTGAyr9nT2NW5FQAYjIH8vpV/2s5kTNu/PQuogZlAHCi/7dcfNzpdgM5oLq2hn+s+Tm9Iqupqolg4ojJ9Irs/mMBz14/E3/EHwDYkD2KP4x9x1oWvZ9/Ow1P3EqU148A2/a4Y7zSJRs2Q4RBfEBCgOJyd/TOXZS3FsTg8RmK4vJtx3FO0m58viBgWJK70nYaR+zam0tcdCXhvgAxUVVsz3fHfZQ27fkeMER4/aQldd59eZygxb+RdYVXUBXwkVWRxLiD3HFV6lnHHkVEdiQmAAnb40iOd0fv3N+OvgB/ZRiBWg8ne0+0HccxB1afSl2dh+qKSK4b/UvbcRwxLC2dXVkH4g94yMoayoj+B9qO5IjzRlzPnso4qvw+qkousx2nTfS0j1JKuYCe9lFKKdUiLf5KKdUDafFXSqkeSIu/Ukr1QFr8lVKqB3JN8a+qreb9pY8wY629ThYdYfmmrdz8+r/5dlXjO2V3b+98M4d7PnyFvSWltqM4ptZfx2MzJvHSV5NtR3HUjrxdPD7nKb7ZuMh2FEd9tXEOL373CLtLXNRHpA1cU/w/XXUJR/V+ngPj7mbKyhdbXqEbqKqt5eaNr7A8bSt3Z71NVn6h7UiOePebuXwin7A5bTm/nvWw7TiOue3zB8npPZMN8R/z12kv247jmHd23URY3+msCNzL+uxttuM4Yv7WH6gJu5XBfd9m6jZ39KVoK9cU/5TonFDPXENpzXrbcRxRUlYBkaGeuV7D9t3uGANnXX4GAB6fgbhqu2EcVBtViNcbxOMJklOTZTuOY+J7VRDuCyBi2Ja/w3YcR2Ts3YgxEOHzkxpTZDuOFa4p/h7vn9lZkcjG4gGccfDdtuM4Ii05kaEZaZhyD70zEhl7+KG2Iznij2ddhn93DLVlPk4NnGI7jmN+kXYV5SXRlBXGcuPo62zHcUzFzrMoqYgid9dBnHO4O96vi0ddxZb8YRRUxlK453rbcazY7x6+IjIQeBNIA4LAy8aYfzZaZhzwGbDvcOETY8xDLb229vBVSqm2aWsP3/aM5OUH7jDGLA+N47tMRGYbYxqfc/nOGHNeO9pRSinlsP0+7WOMyTXGLA89LgM2AP2dCqaUUqrjOHLOX0TSgSOBpq4FGyMiq0RkhoiM/InXmCAiS0VkaUFBgROxlFJKNaPdxV9EYoDJwG3GmMYXbS8HBhtjjgCeBaY09zrGmJeNMaONMaNTU1PbG0sppdRPaFfxF5Ew6gv/O8aYTxrPN8aUGmPKQ4+nA2EiktKeNpVSSrXffhd/ERHgVWCDMeapZpZJCy2HiBwbas8dPZVa8O2qdVzy4hM89elntqM46pnpn3LdW48yf707+lIAVNfWcveUp7nz08cpr6q0Hccx63Zt5i9f3sNL37xhO4qjpqz4mCfnTWTBtgW2ozgmEAjw9qK/MGnhzRRV7u2UNttz5H8icDVwqoisDH2dIyI3iMgNoWUuAdaKyCrgGeBy0xVHj+kAf9r2Dlnpe/gwYgGzlqywHccR05cs5uuYOZQO2cmjO1+yHccxd33xOJUDllAzaDl/nP4323Ec83HOn+g9eBHVqW/y2fKZtuM4Yl32enyxDzBy4Nfk1N3U7QZNb867S+9jdNokxvSbwrR1V3dKm/t9qacx5ntAWljmOeC5/W2jWws3iAdMEHYXuaMHYV7pXggD8YBEuOOXDqCKcqI8QQDqvO458o8Ir8XrMQT8HvZU7rEdxxElVcUI4PUYIn11BI3BazuUAwKmEI8YvBIgylfWKW26podvV3NJ7XFIno/BmalcM/5U23Eccc24M4jPHEhtXhTja8bbjuOYe076PWXZqZTmpPCHo2+2HccxB/pvIic/lfydh3HdmMttx3HECQeewOasc9he2JfCPb8nzNeerkpdxwWH/ZWl+YeyqvAADkr9R6e0qWP4KqWUC+gYvkoppVqkxV8ppXogLf5KKdUDafFXSqkeSIu/Ukr1QO64TspBs5as4JHlXzDAJDDptxPxet1wFTH836dvs7R6HWclncANZ55vO44jKmuquXPqI1R7yvnD6ImMHDjUdiRHrMhYx3ub/0F4IJX7z3jINZczvrd4Erl1n5HqO4+rj3PHACqBQIA3F08k3LeTw/s+zGEDjrYdqdX0yL+R+7Z9TOXgKjYPzOWxT5q9D123snzrFpalLMA7uISZUV9SWe2OoRP/b8aLeAdvJmZwNk+ufsJ2HMd8vOtB+g/YRvLAJTw77wXbcRyRX7aHmKQnGdlvE4nJT5NVlGM7kiM+WvEkx/ebxvFpK8gqnmA7Tpto8W/MhL4Aj/xkB+Zuw+Pat7nB+2Pc8V4BYAQJ/Wwi7nvvDOKa3y3Bs++dwpju9V51r7Sd4JHhlxGXGc2h2QO465Jf2I7jiFEHHsDxe8didiRyXu15REdG2o7kiPvOuRHJHEllxiDuOvIu23Ecc3n6w2TvGkbxrhO4ZdwNLa/QDfSOTaGq+B7WZB1KRdGd9EvoazuSIy458nYW5Pyc+bnHMCTlVdtx2kR7+CqllAtoD1+llFIt0uKvlFI9kBZ/pZTqgdo7jONZIrJJRLaKyN1NzI8QkQ9C8xeFBnpXSillWXuGcfQC/wLOBkYAV4jIiEaLXQ8UGWMOBJ4G/r6/7SmllHJOe7oOHgtsNcZsBxCR94ELgYaDu14IPBB6/DHwnIhIRwzl+MX8xTyy5Qsiqn18fPntJMfHOd2EFXd/8AprIteTXjaYf111q+04jqiurWXi1HsJ9irhrNhfctkJZ9iO5Igl21czedejBOrCufXIvzMguY/tSI6YtOAFaiM+oLTkCP54yj9tx3FEIBDgzSVX0idmC0FzK+cddo3tSJ2uPad9+gO7GjzPCk1rchljjB8oAZLb0WazHtnyBYE+fioHVHPn+291RBOdrqC4hI39VhCeUkPWoM0s2bTJdiRHPDX7LSIH5hDXu4zZde/ajuOYjzKeoE/vfNL6ZfP8oqdtx3FMcurzDE7MZ/jAr/hqw1zbcRwxbe2bHNv3Bw5OyKFP9IO241jRnuLfVBe9xkf0rVmmfkGRCSKyVESWFhQUtDlMeI0X6odhJS06vs3rd0W9IiMI+j0Eg4ARUuPc8XP1jemNAIGAEKgKtx3HObWxBIIeTFDo5U2yncYxFbWR+IOCAVJ6pdqO44jE6H54MNQGPZTURtuOY0V7in8WMLDB8wFA4xt2/GcZEfEB8cDepl7MGPOyMWa0MWZ0amrbd7D3L76V4Tv7Mq7wEP529VVtXr8rio6MZGL8tSTvGMxVvktJ75tmO5Ijfn3y+RxYdC6+zMO478j7bcdxzJ9PfozKXeMI5p7L3affYTuOYw7u9W827jwDU/4Qhw863HYcR/xs2JlsKX6Y+dkXkJ78se04Vux3D99QMd8MnAZkA0uAXxlj1jVYZiJwmDHmBhG5HPiFMebSll5be/gqpVTbtLWH735/4GuM8YvIzcBMwAu8ZoxZJyIPAUuNMZ8DrwJvichW6o/4L9/f9pRSSjmnXTcKN8ZMB6Y3mnZfg8fVwC/b04ZSSinnaQ9fpZTqgbT4K6VUD6TFXymleiAt/kop1QNp8VdKqR6oS47kJSIFQOZ+rp4C7HEwTmfobpm7W17QzJ2lu2Xubnmh+cyDjTGt7iHbJYt/e4jI0rZ0dOgKulvm7pYXNHNn6W6Zu1tecC6znvZRSqkeSIu/Ukr1QG4s/i/bDrAfulvm7pYXNHNn6W6Zu1tecCiz6875K6WUapkbj/yVUkq1oNsW/+40eLyIDBSRr0Vkg4isE5EfjccoIuNEpEREVoa+7mvqtTqTiGSIyJpQnh/dY1vqPRPaxqtF5CgbORvkGd5g+60UkVIRua3RMta3s4i8JiL5IrK2wbQkEZktIltC3xObWffa0DJbRORai3kfF5GNoff9UxFJaGbdn9yHOjnzAyKS3eC9P6eZdX+ytnRy5g8a5M0QkZXNrNv27WyM6XZf1N9CehswFAgHVgEjGi1zE/Bi6PHlwAcW8/YFjgo9jqV+HITGeccBU21v20aZMoCUn5h/DjCD+hHbjgcW2c7caB/ZTf21z11qOwNjgaOAtQ2mPQbcHXp8N/D3JtZLAraHvieGHidayjse8IUe/72pvK3Zhzo58wPAH1ux3/xkbenMzI3mPwnc59R27q5H/v8ZPN4YUwvsGzy+oQuBN0KPPwZOE5GmhpXscMaYXGPM8tDjMmADPx7vuDu6EHjT1FsIJIhIX9uhQk4Dthlj9rezYIcxxnzLj0e0a7i/vgFc1MSqZwKzjTF7jTFFwGzgrA4LGtJUXmPMLFM/LjfAQupH8usymtnGrdGa2tIhfipzqHZdCrznVHvdtfh3qcHj2yJ0+ulIYFETs8eIyCoRmSEiIzs1WNMMMEtElonIhCbmt+Z9sOVymv9F6WrbGaCPMSYX6g8WgN5NLNNVt/dvqP8PsCkt7UOd7ebQqarXmjm11lW38c+APGPMlmbmt3k7d9fi7+jg8Z1FRGKAycBtxpjSRrOXU3+K4gjgWWBKZ+drwonGmKOAs4GJIjK20fwut40BRCQcuAD4qInZXXE7t1aX294ici/gB95pZpGW9qHO9AJwADAKyKX+NEpjXW4bh1zBTx/1t3k7d9fi7+jg8Z1BRMKoL/zvGGM+aTzfGFNqjCkPPZ4OhIlISifHbJwpJ/Q9H/iU+n+JG2rN+2DD2cByY0xe4xldcTuH5O07ZRb6nt/EMl1qe4c+cD4PuNKETjw31op9qNMYY/KMMQFjTBD4dzNZutQ2hv/Ur18AHzS3zP5s5+5a/JcAw0RkSOgo73Lg80bLfA7suxriEuCr5nbQjhY6X/cqsMEY81Qzy6Tt+0xCRI6l/r0p7LyUP8rTS0Ri9z2m/gO+tY0W+xy4JnTVz/FAyb5TF5Y1e5TU1bZzAw3312uBz5pYZiYwXkQSQ6csxoemdToROQu4C7jAGFPZzDKt2Yc6TaPPo37eTJbW1JbOdjqw0RiT1dTM/d7OnfEpdgd9Mn4O9VfNbAPuDU17iPqdESCS+n/7twKLgaEWs55E/b+Oq4GVoa9zgBuAG0LL3Ayso/7qgoXACZa379BQllWhXPu2ccPMAvwr9B6sAUZ3gf0imvpiHt9gWpfaztT/YcoF6qg/0rye+s+j5gJbQt+TQsuOBl5psO5vQvv0VuDXFvNupf7c+L79ed+Vdf2A6T+1D1nM/FZoP11NfUHv2zhz6PmPaoutzKHpk/btvw2Wbfd21h6+SinVA3XX0z5KKaXaQYu/Ukr1QFr8lVKqB9Lir5RSPZAWf6WU6oG0+CulVA+kxV8ppXogLf5KKdUD/T94jMplCZtvcQAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "m1 = 18\n", "m2 = 21\n", "m1inv = inverse(m1,m2)\n", "m2inv = inverse(m2,m1)\n", "\n", "from mpl_toolkits.mplot3d import Axes3D\n", "\n", "r = range(0,m1*m2)\n", "x = [x%m1 for x in r]\n", "y = [y%m2 for y in r]\n", "s = [5 for i in r]\n", "\n", "plt.scatter(x,y,c = r, s=s)\n", "plt.show()\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x = 430 \n", " x mod 25 = 5 \n", " x mod 4 = 2 \n", " x mod 7 = 3\n" ] } ], "source": [ "def CRT(xs, ms):\n", " #The input ms =[m1,m2,...,m_k] is a sequence of pairwise relatively prime moduli. xs =[x1,x2,... x_k] are integers \n", " #modulo m's. The output is an integer x that is congurent to x_i modulo m_i for all the elements in the list.\n", " x = 0\n", " m = 1\n", " for (y,n) in zip(xs,ms):\n", " x = SimpleCRT(x,y,m,n)\n", " m = n*m\n", " return x\n", " \n", "def SimpleCRT(x,y,m,n):\n", " #outputs an integer modulo mn that is congruent to x modulo m and y modulo n\n", " if gcd(m,n)!=1:\n", " print(\"Moduli are not relatively prime\")\n", " return None\n", " minv = inverse(m,n)\n", " ninv = inverse(n,m)\n", " return (x*n*ninv + y*m*minv)%(m*n)\n", "\n", "(x1,x2,x3) = (5,2,3)\n", "(m1,m2,m3) = (25,4,7)\n", "x = CRT([x1,x2,x3],[m1,m2,m3])\n", "print(\"x =\", x,'\\n x mod ', m1,' =', x%m1, '\\n x mod ', m2, ' =', x%m2,'\\n x mod ',m3, ' =', x%m3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Algorithm is as follows. Assume that the group $G$ is of order $N$ which factors as\n", "$$N = q_1^{k_1} \\ldots q_r^{k_r}.$$ For each prime factor $q_i^{k_i}$ raise both sides of the equation to the power of $N/q_i^{k_i}$.\n", "\n", "As an example take the multiplicative group $(\\mathbb{Z}/101 \\mathbb{Z})$ which has order $100 = 4 \\times 25$. Consider an equation of the form, \n", "$$g^x \\equiv A \\pmod{101}$$\n", "The solution to this equation is determined as $x \\mod 100$, since $g^{100} = 1$ (note that $(\\mathbb{Z}/101\\mathbb{Z})^*$ has $\\phi(101)= 100$ elements. Now we exponentiate both sides to $4$-th and $25$-th powers:\n", "$$(g^{4x} \\equiv A^{4} \\pmod{101}$$ is solvable quickly becasue $g^4$ has order at most $25$ not $100$. Also $$g^{25x} \\equiv A^{25}$$ is solvable quickly because the $g^{25}$ has order $4$. This gives two conditions on $x \\equiv x_1 \\pmod{4}$ and $x \\equiv x_2 \\pmod{25}$ and we solve them using Chinese remainder theorem to get a solution $x \\pmod{100}$. " ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import sympy\n", "\n", "p = 1234567811\n", "sympy.isprime(p)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{2: 1, 5: 1, 7: 1, 41: 1, 149: 1, 2887: 1}" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.factorint(p-1)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sympy.ntheory.factor_ import totient as phi\n", "\n", "def PohligHelman(g,A,p,N = None):\n", " if N == None:\n", " N = phi(p)\n", " fac = sympy.factorint(N)\n", " powerlist = [pr**fac[pr] for pr in fac]\n", " allbut = [N/x for x in powerlist]\n", " bases = [fastexp(g,a,p) for a in allbut]\n", " expos = [fastexp(A,a,p) for a in allbut]\n", " results = [BabyStepGiantStep(bases[i],expos[i],p, N = powerlist[i]) for i in range(len(powerlist))]\n", " return CRT(results, powerlist)\n", "\n", "PohligHelman(2,43,101)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "577740778" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "PohligHelman(7,47,p)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "577740778" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "BabyStepGiantStep(7,47,p, N = p-1)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "47" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fastexp(7,577740778,p)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }