diff --git a/doc/cryptools.ipynb b/doc/cryptools.ipynb deleted file mode 100644 index 89d8c2c..0000000 --- a/doc/cryptools.ipynb +++ /dev/null @@ -1,1313 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "c9057db5-a6f9-488d-8a33-ab6046336a7c", - "metadata": {}, - "source": [ - "# Cryptools" - ] - }, - { - "cell_type": "markdown", - "id": "cb7ef98f-faad-4ab5-ba5b-849edf604a62", - "metadata": {}, - "source": [ - "## Zmod: Ring of integers modulo n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "ea0cd1ac-9634-42ad-a02b-bd59456f2553", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3 (mod 5)" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import Zmod\n", - "\n", - "gf = Zmod(5)\n", - "\n", - "gf(3)" - ] - }, - { - "cell_type": "markdown", - "id": "83c3171a-a903-47b7-8322-4d1f86a0b34a", - "metadata": {}, - "source": [ - "To define a finite Galois field modulo the prime $5$ use" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "e1e6e7b4-7263-467e-898f-108d57464b29", - "metadata": {}, - "outputs": [], - "source": [ - "gf = Zmod(5)" - ] - }, - { - "cell_type": "markdown", - "id": "f9f647d5-d690-4b4b-8c79-da1089dcd9e0", - "metadata": {}, - "source": [ - "To declare $3$ as an element of our Galois field use" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "4f307cf0-375a-496e-80ef-a1d137c710b0", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3 (mod 5)" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gf(3)" - ] - }, - { - "cell_type": "markdown", - "id": "4d852941-fa90-42a4-8dba-51850349d032", - "metadata": {}, - "source": [ - "Basic arithmetic operations work as expected:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "14f46d2c-9d6e-46de-8a82-c5d60a33da27", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0 (mod 5)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gf(3) + gf(2)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "7fa8f53d-a8d0-4e48-adb3-e24c1483cfc4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2 (mod 5)" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gf(3) ** -1" - ] - }, - { - "cell_type": "markdown", - "id": "05aa6a42-13fa-4a09-a584-22d758444fac", - "metadata": {}, - "source": [ - "Don't display $\\pmod{5}$ using" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "85f1596e-3d47-4f48-a9c2-b3ae2d0c7a1c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gf.short = True\n", - "gf(6)" - ] - }, - { - "cell_type": "markdown", - "id": "a6d87a55-5338-49d5-92cf-d273f248de58", - "metadata": {}, - "source": [ - "## Primes" - ] - }, - { - "cell_type": "markdown", - "id": "acc2b166-3c90-4fc5-9f7f-a52c313353e7", - "metadata": {}, - "source": [ - "A tuple of primes below a bound $B$ can be obtained using the [sieve of Eratosthenes](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes):" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "58cf98f7-b507-4b4d-9822-a52afb9d7307", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(2, 3, 5, 7, 11, 13, 17, 19)" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import sieve_eratosthenes\n", - "\n", - "sieve_eratosthenes(20)" - ] - }, - { - "cell_type": "markdown", - "id": "e15a4f75-90fd-4d26-9025-70c9cb4dfbef", - "metadata": {}, - "source": [ - "To test if a number is probable prime you can use" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "2e105eeb-92a2-4b8a-86bc-3cb46c1d8b2e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import isprime\n", - "\n", - "isprime(17)" - ] - }, - { - "cell_type": "markdown", - "id": "7ead50a3-838c-435f-aa5c-e84c2a842cc1", - "metadata": {}, - "source": [ - "For numbers below $3317044064679887385961981$ it performs a deterministic variant of the [Miller-Rabin test](https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "bff9b093-f6cb-4158-a42e-7d347928af7f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools.primes import miller_rabin_test\n", - "\n", - "miller_rabin_test(17, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41])" - ] - }, - { - "cell_type": "markdown", - "id": "9c0b4bc1-cbe3-43fc-8e23-02553846f92e", - "metadata": {}, - "source": [ - "Otherwise it combines a Miller-Rabin test with base $2$ with a strong Lucas test ([Baillie–PSW primality test](https://en.wikipedia.org/wiki/Baillie%E2%80%93PSW_primality_test))." - ] - }, - { - "cell_type": "markdown", - "id": "3b6ab9a9-6651-40bc-a723-a6551e99c63a", - "metadata": {}, - "source": [ - "## Number theory" - ] - }, - { - "cell_type": "markdown", - "id": "4fac1421-0d8f-43e3-94de-242beabc7d06", - "metadata": {}, - "source": [ - "To perform the [extended Euclidean algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm) use" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "5bb1d486-3964-4c70-8e7b-7af2de14e777", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1, -1, 1)" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools.nt import egcd\n", - "\n", - "a, b = 7, 8\n", - "g, x, y = egcd(a, b)\n", - "\n", - "assert x * a + y * b == g\n", - "g, x, y" - ] - }, - { - "cell_type": "markdown", - "id": "875e1278-c6d0-43de-a1eb-c4f271500fd3", - "metadata": {}, - "source": [ - "To solve a list of congruences using the [Chinese Remainder Theorem](https://en.wikipedia.org/wiki/Chinese_remainder_theorem) use" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "1f75d7f0-ddee-42d1-afed-da3bbe4157fc", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "23" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools.nt import crt\n", - "\n", - "a, m = [1, 2, 3], [2, 3, 5]\n", - "sol = crt(a, m)\n", - "\n", - "assert [sol % p for p in m] == a\n", - "sol" - ] - }, - { - "cell_type": "markdown", - "id": "577d10df-7fd6-4924-8aa0-016894494268", - "metadata": {}, - "source": [ - "To compute the continued fraction expansion of a rational number use" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "c83aa21c-a85d-48f4-92de-9955a7fa68c7", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0, 1, 3, 1, 1, 2]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from fractions import Fraction\n", - "\n", - "from cryptools import cf, convergents\n", - "\n", - "cf(Fraction(18, 23))" - ] - }, - { - "cell_type": "markdown", - "id": "111d21cd-d958-4e4c-9928-f2ae97a55e3f", - "metadata": {}, - "source": [ - "To get the convergents use" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "585d546f-de97-4cac-8e4e-e112a54da1bb", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0, 1, 3/4, 4/5, 7/9, 18/23]" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "convergents(_)" - ] - }, - { - "cell_type": "markdown", - "id": "a75df0e6-4887-4ae7-a892-dd8b4170bf9d", - "metadata": {}, - "source": [ - "To compute the [Jacobi symbol](https://en.wikipedia.org/wiki/Jacobi_symbol) use" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "75a5460f-500d-4920-9dbd-f96959907ca4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-1" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import jacobi_symbol\n", - "\n", - "jacobi_symbol(3, 7)" - ] - }, - { - "cell_type": "markdown", - "id": "bea6a5f6-911f-4154-95c1-8e841d8a0930", - "metadata": {}, - "source": [ - "Since it equals $+1$ the number has a [quadratic residue](https://en.wikipedia.org/wiki/Quadratic_residue) and has a square root modulo the prime $7$" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "4d16951d-bb88-4a16-affa-8a7757cb0d72", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import sqrt_mod\n", - "\n", - "sqrt_mod(4, 7)" - ] - }, - { - "cell_type": "markdown", - "id": "4b651b8b-71cc-4060-bedd-72f8bdc26b19", - "metadata": {}, - "source": [ - "To compute [Euler's $\\varphi$ function](https://en.wikipedia.org/wiki/Euler%27s_totient_function) (a.k.a totient function) or [Carmichael's $\\lambda$ function](https://en.wikipedia.org/wiki/Carmichael_function) use" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "ade14b6b-025b-4bf9-b180-f28d57a14e27", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(40, 20)" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools.nt import carmichael_lambda, euler_phi\n", - "\n", - "n = 100\n", - "euler_phi(n), carmichael_lambda(n)" - ] - }, - { - "cell_type": "markdown", - "id": "76fb4f61-d902-4432-92c9-7383c4e068cd", - "metadata": {}, - "source": [ - "To compute the order of a element of the [multiplicative group of integers modulo $n$](https://en.wikipedia.org/wiki/Multiplicative_group_of_integers_modulo_n), $\\mathbb{Z}_n^*$, use" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "c71e085a-8c47-4714-bca3-de82db263d08", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools.nt import order\n", - "\n", - "order(5, 7)" - ] - }, - { - "cell_type": "markdown", - "id": "1abd4c61-aef3-46be-bc87-0a37b7440e58", - "metadata": {}, - "source": [ - "## Factoring integers" - ] - }, - { - "cell_type": "markdown", - "id": "32ef7b6f-6748-4f5d-9a7c-266a9a80b22d", - "metadata": {}, - "source": [ - "To factor an integer $n$ into its prime factors use" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "49a0a92d-e58d-49e5-b9fb-79c4d30c200a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Trial division found: []\n", - "Factors found ( ecm ): [59649589127497217, 5704689200685129054721]\n" - ] - }, - { - "data": { - "text/plain": [ - "{59649589127497217: 1, 5704689200685129054721: 1}" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import factorint\n", - "\n", - "n = 2**128 + 1\n", - "factorint(n, verbose=1)" - ] - }, - { - "cell_type": "markdown", - "id": "94f81f47-b7a6-444e-87fa-2d5390506708", - "metadata": {}, - "source": [ - "## Linear Algebra" - ] - }, - { - "cell_type": "markdown", - "id": "7ba2b164-df1a-417a-a0f0-8c127b04bbbd", - "metadata": {}, - "source": [ - "The basic class for working with matrices:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "4626c758-753b-4d3a-9ed0-99038ca5f280", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 19 ]\n", - "[ 35 ]" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools.la import Matrix\n", - "\n", - "M = Matrix([[1, 2, 3], [3, 4, 5]])\n", - "N = Matrix([[1], [3], [4]])\n", - "M * N" - ] - }, - { - "cell_type": "markdown", - "id": "358b9f09-2048-4652-9351-a37b3ab6dd93", - "metadata": {}, - "source": [ - "Slicing to access (e.g.) rows:" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "8a2f83a9-7114-43a1-baee-7f6bb6c45f30", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 1 ]\n", - "[ 3 ]" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "M[:, 0]" - ] - }, - { - "cell_type": "markdown", - "id": "178cec9c-29a5-4f10-9d62-4e40ba3b9f9d", - "metadata": {}, - "source": [ - "Also works with assignments, e.g., to swap two columns:" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "ef4a7e98-4d55-482b-a264-6aab3283e6ec", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 3, 4, 5 ]\n", - "[ 1, 2, 3 ]" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "M[0, :], M[1, :] = M[1, :], M[0, :]\n", - "M" - ] - }, - { - "cell_type": "markdown", - "id": "72e95acf-ae6f-4d26-b22e-4baf15813016", - "metadata": {}, - "source": [ - "The coefficients can be from a field, e.g. `Fractions`. The `map` method applies a given function to all elements. Here we compute the [row reduced echelon form](https://en.wikipedia.org/wiki/Row_echelon_form)." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "3bec64e6-937f-4041-a710-cf42c95a8689", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ 1, 2, 3 ]\n", - "[ 4, 5, 6 ]\n", - "[ 7, 8, 12 ]\n" - ] - }, - { - "data": { - "text/plain": [ - "[ 1, 0, 0 ]\n", - "[ 0, 1, 0 ]\n", - "[ 0, 0, 1 ]" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from fractions import Fraction\n", - "\n", - "M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 12]])\n", - "M.map(Fraction)\n", - "print(M)\n", - "M.rref()" - ] - }, - { - "cell_type": "markdown", - "id": "996ccdd5-7d72-4df5-83bb-fa2f7172a1f2", - "metadata": {}, - "source": [ - "The [determinant](https://en.wikipedia.org/wiki/Determinant)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "a99ed976-cbdd-4ce7-8a97-efcee7fd510d", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-9\n" - ] - } - ], - "source": [ - "print(M.det())" - ] - }, - { - "cell_type": "markdown", - "id": "18a119f0-b89d-419b-a36a-121db619dc80", - "metadata": {}, - "source": [ - "or the [inverse](https://en.wikipedia.org/wiki/Invertible_matrix)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "64294f1f-d3ef-41b0-ad59-d68e69c89aba", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ -4/3, 0, 1/3 ]\n", - "[ 2/3, 1, -2/3 ]\n", - "[ 1/3, -2/3, 1/3 ]\n" - ] - }, - { - "data": { - "text/plain": [ - "[ 1, 0, 0 ]\n", - "[ 0, 1, 0 ]\n", - "[ 0, 0, 1 ]" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Mi = M.inv()\n", - "print(Mi)\n", - "M * Mi" - ] - }, - { - "cell_type": "markdown", - "id": "d79248b1-0b22-4b5a-bf2c-9d6cb71aaf7c", - "metadata": {}, - "source": [ - "Same works if the coefficients are from a finite field or ring:" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "47961b0f-e632-4d1c-9445-de3c217bce10", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gf = Zmod(11, short = True)\n", - "\n", - "M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 12]], ring = gf)\n", - "M.det()" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "d9cfb165-6e94-413b-9a91-5c5aa3870aa3", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[ 6, 0, 4 ]\n", - "[ 8, 1, 3 ]\n", - "[ 4, 3, 4 ]\n" - ] - }, - { - "data": { - "text/plain": [ - "[ 1, 0, 0 ]\n", - "[ 0, 1, 0 ]\n", - "[ 0, 0, 1 ]" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Mi = M.inv()\n", - "print(Mi)\n", - "M * Mi" - ] - }, - { - "cell_type": "markdown", - "id": "6a18d736-a6f2-40bf-a154-a143a9252f02", - "metadata": {}, - "source": [ - "## Lattice" - ] - }, - { - "cell_type": "markdown", - "id": "68b25452-c46b-40fb-80e5-bbfe94ec7666", - "metadata": {}, - "source": [ - "To compute the [Hermite normal form](https://en.wikipedia.org/wiki/Hermite_normal_form) use" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "0f5a048b-767e-4848-bb23-c898365ee9dc", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 69, 58, 36 ]\n", - "[ 0, 1, 0 ]\n", - "[ 0, 0, 1 ]" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import hermite_nf\n", - "\n", - "M = Matrix([[1, 2, 3, 1], [4, 5, 6, 4], [7, -8, 0, 7]])\n", - "hermite_nf(M)" - ] - }, - { - "cell_type": "markdown", - "id": "a1dbf2dc-1a7c-49f0-aa4f-223ee7d83966", - "metadata": {}, - "source": [ - "To compute the [Gram-Schmidt decomposition](https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process) use" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "61bad2d5-2fad-4f5a-b4cf-206fca8e09fd", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 5, 0 ]\n", - "[ 0, 1 ]" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import gram_schmidt\n", - "\n", - "V = Matrix([[5, 8], [0, 1]], ring = Fraction)\n", - "Vs, M = gram_schmidt(V)\n", - "assert V == Vs * M\n", - "Vs" - ] - }, - { - "cell_type": "markdown", - "id": "e79e180e-d7d2-43fc-a9d2-1753f80caf5e", - "metadata": {}, - "source": [ - "LLL reduction" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "ee41707c-8d92-468d-9a94-18b6bd44053c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 0, 1, 2 ]\n", - "[ -1, 0, 2 ]\n", - "[ 1, -1, 1 ]" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import lll\n", - "\n", - "V = Matrix([[1, 1, 2], [1, 0, -2], [3, 4, 5]])\n", - "U = lll(V)\n", - "U" - ] - }, - { - "cell_type": "markdown", - "id": "c8427b8b-db49-4fa1-ba07-63382746bcca", - "metadata": {}, - "source": [ - "## Polynomials" - ] - }, - { - "cell_type": "markdown", - "id": "536b50bf-6c66-4253-b525-3938da8d1747", - "metadata": {}, - "source": [ - "A basic class for polynomials, entered as a list of coefficients" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "d3c69787-da17-4cd3-b282-a68ee4d177e6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3 x^2 + 2 x + 1" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from cryptools import Poly\n", - "\n", - "Poly([1, 2, 3])" - ] - }, - { - "cell_type": "markdown", - "id": "292c9b1a-8397-44e0-aa89-0d8b3ecd35cf", - "metadata": {}, - "source": [ - "Computations in a polynomial ring can be done as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "8d4c4b43-e593-407a-92f8-86b653a09c8a", - "metadata": {}, - "outputs": [], - "source": [ - "from random import binomialvariate, randint, seed\n", - "\n", - "seed(0)\n", - "\n", - "p = 97\n", - "n = 4\n", - "k = 2\n", - "gf = Zmod(p)\n", - "gf.short = True\n", - "\n", - "\n", - "def kyber(n: int) -> list:\n", - " return [1] + [0] * (n - 1) + [1]\n", - "\n", - "\n", - "def PolyKyber(c: list) -> \"Poly\":\n", - " return Poly(c, ring = gf, modulus = kyber(n))" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "bf50f802-93f5-4c79-b982-a208486f9a72", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 33 x^3 + 5 x^2 + 53 x + 49, 38 x^3 + 51 x^2 + 62 x + 65 ]\n", - "[ 27 x^3 + 74 x^2 + 45 x + 61, 17 x^3 + 36 x^2 + 17 x + 64 ]" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Matrix(\n", - " [\n", - " [PolyKyber([randint(0, p - 1) for _ in range(n)]) for i in range(k)]\n", - " for j in range(k)\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "9e0ebbd3-0d4b-4e1b-b4dd-323b5a86dc23", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ x^3 + x + 96, 96 x^2 + x + 1 ]" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Matrix([[PolyKyber([randint(-1, 1) for _ in range(n)]) for i in range(k)]])" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "563280a9-27b9-4707-ae14-9aeef9bbe5a6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 96 x^3 + x + 95, 2 x ]" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "q = p // (4 * k * n)\n", - "Matrix([[PolyKyber([binomialvariate(2 * q) - q for _ in range(n)]) for i in range(k)]])" - ] - }, - { - "cell_type": "markdown", - "id": "cd27fc5e-66d3-4e12-b29a-f5d9d7ddd9a2", - "metadata": {}, - "source": [ - "## Discrete logarithms" - ] - }, - { - "cell_type": "markdown", - "id": "aeb83159-f78d-44f0-a86c-3bb78db102c3", - "metadata": {}, - "source": [ - "To solve a [discrete log](https://en.wikipedia.org/wiki/Discrete_logarithm) problem use" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "2e9c7c97-0896-4444-ae8e-4ea390b2231d", - "metadata": {}, - "outputs": [], - "source": [ - "from random import randint\n", - "\n", - "from cryptools import dlog\n", - "\n", - "p, m, a = [557639, 278819, 2]\n", - "x = randint(2, m - 1)\n", - "b = pow(a, x, p)\n", - "assert dlog(a, b, p, m) == x" - ] - }, - { - "cell_type": "markdown", - "id": "e806524f-1aff-4971-b4d5-44c51dd9a452", - "metadata": {}, - "source": [ - "## Eliptic curves" - ] - }, - { - "cell_type": "markdown", - "id": "1f5fdb01-b2c4-407d-92a6-61b1251fa21d", - "metadata": {}, - "source": [ - "To declare an [elliptic curves](https://en.wikipedia.org/wiki/Elliptic_curve) in Weierstrass normal form use" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "9b566550-f23c-4fbc-8b7c-63bbee8e0c72", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Weierstrass curve y^2 = x^3 + 3 x + 1 over Z_239.\n", - "Order: 258\n" - ] - } - ], - "source": [ - "from cryptools import EC_Weierstrass\n", - "\n", - "ec = EC_Weierstrass(239, 3, 1)\n", - "ec.info()\n", - "print(\"Order:\", ec.order())" - ] - }, - { - "cell_type": "markdown", - "id": "e1b2a51c-fafa-4693-8d1d-8ee1c5f386ad", - "metadata": {}, - "source": [ - "Basic arithmetic" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "55c29e0c-e0c2-409a-af23-6590fd9cc545", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(103, 114)" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "P = ec.random()\n", - "Q = ec.random()\n", - "O = ec(None, None) # point at infinity\n", - "P + Q" - ] - }, - { - "cell_type": "markdown", - "id": "babb9780-b05b-452d-a769-b2f467d660e0", - "metadata": {}, - "source": [ - "To compute the order of a point use" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "2a3d8e7d-71b3-4a93-b6cc-803f00432c56", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "258" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "Q.order()" - ] - }, - { - "cell_type": "markdown", - "id": "ee964846-0f24-4134-9772-39bea8dd04c1", - "metadata": {}, - "source": [ - "To compute a discrete log use" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "id": "bb93b5fc-99c9-4977-8299-9342b84e143d", - "metadata": {}, - "outputs": [], - "source": [ - "k = 12\n", - "R = k * Q\n", - "assert R.dlog(Q) == k" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "41e18357-da42-4cd7-bd4e-1c3355f1c69d", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.12.1" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -}