From 3a6190bdf228c4e3666b13108adc00cb139bc051 Mon Sep 17 00:00:00 2001 From: Gerald Teschl Date: Thu, 18 Jul 2024 15:21:59 +0200 Subject: [PATCH] Various Improvements --- doc/kryptools.ipynb | 324 +++++++++++++++++++++++++--------------- kryptools/Zmod.py | 40 +++-- kryptools/dlp.py | 9 +- kryptools/dlp_qs.py | 6 +- kryptools/ec.py | 2 +- kryptools/factor_ecm.py | 2 +- kryptools/la.py | 20 ++- kryptools/nt.py | 5 +- kryptools/poly.py | 52 ++++--- 9 files changed, 292 insertions(+), 168 deletions(-) diff --git a/doc/kryptools.ipynb b/doc/kryptools.ipynb index 4f221d4..4fa23bb 100644 --- a/doc/kryptools.ipynb +++ b/doc/kryptools.ipynb @@ -173,6 +173,35 @@ "gf(3).is_generator()" ] }, + { + "cell_type": "markdown", + "id": "e70ad322-0579-4ac8-81c3-3e7d43d39918", + "metadata": {}, + "source": [ + "For [Learning with errors](https://en.wikipedia.org/wiki/Learning_with_errors) a symmetric represnetative is frequently required:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "1edf6b6c-9f83-466d-831e-b225091a7bb4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 2, -2, -1]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[ gf(i).sharp() for i in range(gf.n) ]" + ] + }, { "cell_type": "markdown", "id": "05aa6a42-13fa-4a09-a584-22d758444fac", @@ -183,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "85f1596e-3d47-4f48-a9c2-b3ae2d0c7a1c", "metadata": {}, "outputs": [ @@ -193,7 +222,7 @@ "1 (mod 5)" ] }, - "execution_count": 7, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -221,7 +250,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "id": "58cf98f7-b507-4b4d-9822-a52afb9d7307", "metadata": {}, "outputs": [ @@ -231,7 +260,7 @@ "(2, 3, 5, 7, 11, 13, 17, 19)" ] }, - "execution_count": 8, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -252,7 +281,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "id": "2e105eeb-92a2-4b8a-86bc-3cb46c1d8b2e", "metadata": {}, "outputs": [ @@ -262,7 +291,7 @@ "True" ] }, - "execution_count": 9, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -283,7 +312,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "id": "bff9b093-f6cb-4158-a42e-7d347928af7f", "metadata": {}, "outputs": [ @@ -293,7 +322,7 @@ "True" ] }, - "execution_count": 10, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -322,7 +351,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "id": "23a398a8-d489-4dcf-bf8a-f8577ce04b50", "metadata": {}, "outputs": [ @@ -332,7 +361,7 @@ "101" ] }, - "execution_count": 11, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -353,7 +382,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "id": "2846c396-3edc-4140-b150-9fbd69dac282", "metadata": {}, "outputs": [ @@ -363,7 +392,7 @@ "128" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -386,7 +415,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "id": "c684e98a-8f99-42cb-a74b-0665afc861c4", "metadata": {}, "outputs": [ @@ -396,7 +425,7 @@ "128" ] }, - "execution_count": 13, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -419,7 +448,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "id": "4daf1ed9-1923-41dd-b882-13f3a5561c49", "metadata": {}, "outputs": [ @@ -429,7 +458,7 @@ "271" ] }, - "execution_count": 14, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -461,7 +490,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "id": "5bb1d486-3964-4c70-8e7b-7af2de14e777", "metadata": {}, "outputs": [ @@ -471,7 +500,7 @@ "(1, -1, 1)" ] }, - "execution_count": 15, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -496,7 +525,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "id": "1f75d7f0-ddee-42d1-afed-da3bbe4157fc", "metadata": {}, "outputs": [ @@ -506,7 +535,7 @@ "23" ] }, - "execution_count": 16, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -531,7 +560,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 18, "id": "c83aa21c-a85d-48f4-92de-9955a7fa68c7", "metadata": {}, "outputs": [ @@ -541,7 +570,7 @@ "[0, 1, 3, 1, 1, 2]" ] }, - "execution_count": 17, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -563,7 +592,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 19, "id": "585d546f-de97-4cac-8e4e-e112a54da1bb", "metadata": {}, "outputs": [ @@ -573,7 +602,7 @@ "[0, 1, 3/4, 4/5, 7/9, 18/23]" ] }, - "execution_count": 18, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -592,7 +621,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "id": "75a5460f-500d-4920-9dbd-f96959907ca4", "metadata": {}, "outputs": [ @@ -602,7 +631,7 @@ "1" ] }, - "execution_count": 19, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -623,7 +652,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "id": "4d16951d-bb88-4a16-affa-8a7757cb0d72", "metadata": {}, "outputs": [ @@ -633,7 +662,7 @@ "2" ] }, - "execution_count": 20, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -654,7 +683,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "id": "ade14b6b-025b-4bf9-b180-f28d57a14e27", "metadata": {}, "outputs": [ @@ -664,7 +693,7 @@ "(40, 20)" ] }, - "execution_count": 21, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -686,7 +715,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "id": "c71e085a-8c47-4714-bca3-de82db263d08", "metadata": {}, "outputs": [ @@ -696,7 +725,7 @@ "6" ] }, - "execution_count": 22, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -725,7 +754,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "id": "49a0a92d-e58d-49e5-b9fb-79c4d30c200a", "metadata": {}, "outputs": [ @@ -743,7 +772,7 @@ "{59649589127497217: 1, 5704689200685129054721: 1}" ] }, - "execution_count": 23, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -773,7 +802,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "id": "9a629204-562c-44eb-a012-7345b97035b5", "metadata": {}, "outputs": [ @@ -783,7 +812,7 @@ "[3, 19, 1579]" ] }, - "execution_count": 24, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -804,7 +833,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 26, "id": "39f76a97-1b88-4b95-aac7-bf403043d7b7", "metadata": {}, "outputs": [ @@ -814,7 +843,7 @@ "487" ] }, - "execution_count": 25, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -835,7 +864,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 27, "id": "e68d0db0-7d1d-4a00-ad6e-10656c829708", "metadata": {}, "outputs": [], @@ -855,7 +884,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 28, "id": "3b7c0474-835b-4b10-b0d3-a7b8f62eff23", "metadata": {}, "outputs": [ @@ -865,7 +894,7 @@ "1709" ] }, - "execution_count": 27, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -886,7 +915,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 29, "id": "8ee9854b-6ce0-43b6-906d-98f52fb74d8e", "metadata": {}, "outputs": [ @@ -896,7 +925,7 @@ "1709" ] }, - "execution_count": 28, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -925,7 +954,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 30, "id": "46ab20cc-8d39-4d7b-baef-f411cf34deb7", "metadata": {}, "outputs": [], @@ -958,7 +987,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 31, "id": "66ae327c-ff14-4bff-b12d-330c1787cd6b", "metadata": {}, "outputs": [], @@ -981,7 +1010,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 32, "id": "d1ce2beb-4e60-4a56-9943-d47f1945f13a", "metadata": {}, "outputs": [], @@ -1004,7 +1033,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 33, "id": "fb231c7c-293f-4353-8048-1de3d26568e1", "metadata": {}, "outputs": [], @@ -1027,7 +1056,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 34, "id": "ad8d5929-488e-44bc-9263-91044a2886d4", "metadata": {}, "outputs": [ @@ -1059,7 +1088,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 35, "id": "882543ac-a2f7-4448-93bd-d9385d3457f6", "metadata": {}, "outputs": [ @@ -1100,7 +1129,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 36, "id": "4626c758-753b-4d3a-9ed0-99038ca5f280", "metadata": {}, "outputs": [ @@ -1111,7 +1140,7 @@ "[ 35 ]" ] }, - "execution_count": 35, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } @@ -1134,7 +1163,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 37, "id": "8a2f83a9-7114-43a1-baee-7f6bb6c45f30", "metadata": {}, "outputs": [ @@ -1145,7 +1174,7 @@ "[ 3 ]" ] }, - "execution_count": 36, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -1164,7 +1193,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 38, "id": "ef4a7e98-4d55-482b-a264-6aab3283e6ec", "metadata": {}, "outputs": [ @@ -1175,7 +1204,7 @@ "[ 1, 2, 3 ]" ] }, - "execution_count": 37, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } @@ -1195,7 +1224,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 39, "id": "3bec64e6-937f-4041-a710-cf42c95a8689", "metadata": {}, "outputs": [ @@ -1216,7 +1245,7 @@ "[ 0, 0, 1 ]" ] }, - "execution_count": 38, + "execution_count": 39, "metadata": {}, "output_type": "execute_result" } @@ -1240,7 +1269,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 40, "id": "a99ed976-cbdd-4ce7-8a97-efcee7fd510d", "metadata": {}, "outputs": [ @@ -1266,7 +1295,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 41, "id": "64294f1f-d3ef-41b0-ad59-d68e69c89aba", "metadata": {}, "outputs": [ @@ -1287,7 +1316,7 @@ "[ 0, 0, 1 ]" ] }, - "execution_count": 40, + "execution_count": 41, "metadata": {}, "output_type": "execute_result" } @@ -1308,7 +1337,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 42, "id": "47961b0f-e632-4d1c-9445-de3c217bce10", "metadata": {}, "outputs": [ @@ -1318,7 +1347,7 @@ "2" ] }, - "execution_count": 41, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } @@ -1332,7 +1361,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 43, "id": "d9cfb165-6e94-413b-9a91-5c5aa3870aa3", "metadata": {}, "outputs": [ @@ -1353,7 +1382,7 @@ "[ 0, 0, 1 ]" ] }, - "execution_count": 42, + "execution_count": 43, "metadata": {}, "output_type": "execute_result" } @@ -1382,7 +1411,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 44, "id": "0f5a048b-767e-4848-bb23-c898365ee9dc", "metadata": {}, "outputs": [ @@ -1394,7 +1423,7 @@ "[ 0, 0, 1 ]" ] }, - "execution_count": 43, + "execution_count": 44, "metadata": {}, "output_type": "execute_result" } @@ -1416,7 +1445,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 45, "id": "61bad2d5-2fad-4f5a-b4cf-206fca8e09fd", "metadata": {}, "outputs": [ @@ -1427,7 +1456,7 @@ "[ 0, 1 ]" ] }, - "execution_count": 44, + "execution_count": 45, "metadata": {}, "output_type": "execute_result" } @@ -1451,7 +1480,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 46, "id": "5712d013-c037-4b03-9f62-13fdaaae855b", "metadata": {}, "outputs": [ @@ -1461,7 +1490,7 @@ "5.0" ] }, - "execution_count": 45, + "execution_count": 46, "metadata": {}, "output_type": "execute_result" } @@ -1482,7 +1511,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 47, "id": "0c56dbdc-caa4-4783-8c2f-8f586a8dc4a1", "metadata": {}, "outputs": [ @@ -1492,7 +1521,7 @@ "0.3521856535823236" ] }, - "execution_count": 46, + "execution_count": 47, "metadata": {}, "output_type": "execute_result" } @@ -1513,7 +1542,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 48, "id": "c3f8c523-114c-46b9-968d-4eb31615de4b", "metadata": {}, "outputs": [ @@ -1531,7 +1560,7 @@ "[ 0 ]" ] }, - "execution_count": 47, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } @@ -1556,7 +1585,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 49, "id": "b8ba76ae-092c-4f12-9a05-0b33fd54ebb2", "metadata": {}, "outputs": [ @@ -1574,7 +1603,7 @@ "[ 0 ]" ] }, - "execution_count": 48, + "execution_count": 49, "metadata": {}, "output_type": "execute_result" } @@ -1598,7 +1627,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 50, "id": "bd6ea8c7-85ba-4b8d-97d6-f3176e9a22d4", "metadata": {}, "outputs": [ @@ -1616,7 +1645,7 @@ "[ 0 ]" ] }, - "execution_count": 49, + "execution_count": 50, "metadata": {}, "output_type": "execute_result" } @@ -1640,7 +1669,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 51, "id": "ee41707c-8d92-468d-9a94-18b6bd44053c", "metadata": {}, "outputs": [ @@ -1652,7 +1681,7 @@ "[ 1, -1, 1 ]" ] }, - "execution_count": 50, + "execution_count": 51, "metadata": {}, "output_type": "execute_result" } @@ -1675,7 +1704,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 52, "id": "694c25e5-d01f-4acf-ab57-69bffb0fb9a8", "metadata": {}, "outputs": [ @@ -1687,7 +1716,7 @@ "[ 4, 2, 9 ]" ] }, - "execution_count": 51, + "execution_count": 52, "metadata": {}, "output_type": "execute_result" } @@ -1716,7 +1745,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 53, "id": "d3c69787-da17-4cd3-b282-a68ee4d177e6", "metadata": {}, "outputs": [ @@ -1726,7 +1755,7 @@ "(2 x^2 + 2, 4 x^3 + 3 x^2 + 2 x + 1)" ] }, - "execution_count": 52, + "execution_count": 53, "metadata": {}, "output_type": "execute_result" } @@ -1750,7 +1779,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 54, "id": "93326765-bb08-4c15-9d1a-97b1440ba986", "metadata": {}, "outputs": [ @@ -1760,7 +1789,7 @@ "8 x^5 + 6 x^4 + 12 x^3 + 8 x^2 + 4 x + 2" ] }, - "execution_count": 53, + "execution_count": 54, "metadata": {}, "output_type": "execute_result" } @@ -1779,7 +1808,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 55, "id": "81d433fc-6dcd-42a7-97ef-362913bf99c0", "metadata": {}, "outputs": [ @@ -1789,7 +1818,7 @@ "(2.0 x + 1.5, -2.0 x - 2.0)" ] }, - "execution_count": 54, + "execution_count": 55, "metadata": {}, "output_type": "execute_result" } @@ -1801,6 +1830,35 @@ "d, m" ] }, + { + "cell_type": "markdown", + "id": "33121f66-d268-43c6-95c3-30c74ac3c7e5", + "metadata": {}, + "source": [ + "Alternatively" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "f1e28f9a-0366-44a7-9649-d4d2b74a9280", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2.0 x + 1.5, -2.0 x - 2.0)" + ] + }, + "execution_count": 56, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "q // p, q % p" + ] + }, { "cell_type": "markdown", "id": "ffe59238-3093-4aec-8915-9f85dd2217c7", @@ -1811,7 +1869,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 57, "id": "f8094d46-9ca8-46dc-9be3-96eb363b3ade", "metadata": {}, "outputs": [ @@ -1821,7 +1879,7 @@ "(2 x + 3/2, -2 x - 2)" ] }, - "execution_count": 55, + "execution_count": 57, "metadata": {}, "output_type": "execute_result" } @@ -1833,6 +1891,36 @@ "q.divmod(p)" ] }, + { + "cell_type": "markdown", + "id": "48449ae6-1b5d-4409-878f-7392accaa9e8", + "metadata": {}, + "source": [ + "If you want the reduction of $q$ modulo $p$ to be made in place use:" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "c121753b-dc2c-4000-9f14-b71b78f65d60", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-2 x - 2" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "q.mod(p)\n", + "q" + ] + }, { "cell_type": "markdown", "id": "292c9b1a-8397-44e0-aa89-0d8b3ecd35cf", @@ -1843,7 +1931,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 59, "id": "cf284301-bb0d-44dc-b3cf-51ef187b01ad", "metadata": {}, "outputs": [ @@ -1853,7 +1941,7 @@ "x^4 + x^2 + x + 1" ] }, - "execution_count": 1, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } @@ -1876,7 +1964,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 60, "id": "85ce3cb2-faf5-4a75-b624-dfff2b2ce255", "metadata": {}, "outputs": [ @@ -1886,7 +1974,7 @@ "141" ] }, - "execution_count": 7, + "execution_count": 60, "metadata": {}, "output_type": "execute_result" } @@ -1918,7 +2006,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 61, "id": "8d4c4b43-e593-407a-92f8-86b653a09c8a", "metadata": {}, "outputs": [], @@ -1952,7 +2040,7 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 62, "id": "bf50f802-93f5-4c79-b982-a208486f9a72", "metadata": {}, "outputs": [ @@ -1963,7 +2051,7 @@ "[ 27 x^3 + 74 x^2 + 45 x + 61, 17 x^3 + 36 x^2 + 17 x + 64 ]" ] }, - "execution_count": 57, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } @@ -1988,7 +2076,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 63, "id": "9e0ebbd3-0d4b-4e1b-b4dd-323b5a86dc23", "metadata": {}, "outputs": [ @@ -1999,7 +2087,7 @@ "[ 96 x^2 + x + 1 ]" ] }, - "execution_count": 58, + "execution_count": 63, "metadata": {}, "output_type": "execute_result" } @@ -2019,7 +2107,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 64, "id": "563280a9-27b9-4707-ae14-9aeef9bbe5a6", "metadata": {}, "outputs": [ @@ -2030,7 +2118,7 @@ "[ 2 x ]" ] }, - "execution_count": 59, + "execution_count": 64, "metadata": {}, "output_type": "execute_result" } @@ -2051,7 +2139,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 65, "id": "fabcbecf-cf96-4211-a1e3-ad0f5a337a09", "metadata": {}, "outputs": [ @@ -2062,7 +2150,7 @@ "[ 47 x^3 + 30 x^2 + 42 x + 47 ]" ] }, - "execution_count": 60, + "execution_count": 65, "metadata": {}, "output_type": "execute_result" } @@ -2090,7 +2178,7 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 66, "id": "9b566550-f23c-4fbc-8b7c-63bbee8e0c72", "metadata": {}, "outputs": [ @@ -2129,7 +2217,7 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 67, "id": "55c29e0c-e0c2-409a-af23-6590fd9cc545", "metadata": {}, "outputs": [ @@ -2139,7 +2227,7 @@ "(113, 91)" ] }, - "execution_count": 62, + "execution_count": 67, "metadata": {}, "output_type": "execute_result" } @@ -2161,7 +2249,7 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 68, "id": "f980a2d0-4413-4812-a73d-1bab72a744f3", "metadata": {}, "outputs": [ @@ -2171,7 +2259,7 @@ "True" ] }, - "execution_count": 63, + "execution_count": 68, "metadata": {}, "output_type": "execute_result" } @@ -2190,7 +2278,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 69, "id": "2a3d8e7d-71b3-4a93-b6cc-803f00432c56", "metadata": {}, "outputs": [ @@ -2200,7 +2288,7 @@ "129" ] }, - "execution_count": 64, + "execution_count": 69, "metadata": {}, "output_type": "execute_result" } @@ -2220,7 +2308,7 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 70, "id": "76d3b602-4903-4218-b34c-a39fbe392ad1", "metadata": {}, "outputs": [ @@ -2230,7 +2318,7 @@ "0" ] }, - "execution_count": 65, + "execution_count": 70, "metadata": {}, "output_type": "execute_result" } @@ -2249,7 +2337,7 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 71, "id": "bb93b5fc-99c9-4977-8299-9342b84e143d", "metadata": {}, "outputs": [], @@ -2269,7 +2357,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 72, "id": "41e18357-da42-4cd7-bd4e-1c3355f1c69d", "metadata": {}, "outputs": [], @@ -2292,7 +2380,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 73, "id": "af81d5f2-a524-4555-8e74-06a0c9a7ea08", "metadata": {}, "outputs": [ @@ -2303,7 +2391,7 @@ " 0x03449ef2ed30a8deb96e584a08c329adbf1be87ce40f1a0e7b4e86178682c41a9c)" ] }, - "execution_count": 68, + "execution_count": 73, "metadata": {}, "output_type": "execute_result" } @@ -2317,7 +2405,7 @@ { "cell_type": "code", "execution_count": null, - "id": "13b8cec0-6a76-4af2-9885-613723ace898", + "id": "18d6e83b-e549-4d27-9900-825a00755f19", "metadata": {}, "outputs": [], "source": [] @@ -2339,7 +2427,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.1" + "version": "3.12.2" } }, "nbformat": 4, diff --git a/kryptools/Zmod.py b/kryptools/Zmod.py index 7dad53c..6a123ac 100644 --- a/kryptools/Zmod.py +++ b/kryptools/Zmod.py @@ -90,48 +90,66 @@ def __hash__(self): return hash(self.x) def __add__(self, other: "ZmodPoint") -> "ZmodPoint": - if isinstance(other, self.__class__) and self.ring == other.ring: + if isinstance(other, self.__class__): + if self.ring != other.ring: + raise NotImplementedError("Cannot add elements from different rings.") return self.__class__(self.x + other.x, self.ring) if isinstance(other, int): return self.__class__(self.x + other, self.ring) return NotImplemented def __radd__(self, scalar: int) -> "ZmodPoint": - return self.__class__(scalar + self.x, self.ring) + if isinstance(scalar, int): + return self.__class__(scalar + self.x, self.ring) + return NotImplemented def __neg__(self) -> "ZmodPoint": return self.__class__(-self.x, self.ring) def __sub__(self, other: "ZmodPoint") -> "ZmodPoint": - if isinstance(other, self.__class__) and self.ring == other.ring: + if isinstance(other, self.__class__): + if self.ring != other.ring: + raise NotImplementedError("Cannot subtract elements from different rings.") return self.__class__(self.x - other.x, self.ring) if isinstance(other, int): return self.__class__(self.x - other, self.ring) return NotImplemented def __rsub__(self, scalar: int) -> "ZmodPoint": - return self.__class__(scalar - self.x, self.ring) + if isinstance(scalar, int): + return self.__class__(scalar - self.x, self.ring) + return NotImplemented def __mul__(self, other: "ZmodPoint") -> "ZmodPoint": - if isinstance(other, self.__class__) and self.ring == other.ring: + if isinstance(other, self.__class__): + if self.ring != other.ring: + raise NotImplementedError("Cannot multiply elements from different rings.") return self.__class__(self.x * other.x, self.ring) if isinstance(other, int): return self.__class__(self.x * other, self.ring) return NotImplemented def __rmul__(self, scalar: int) -> "ZmodPoint": - return self.__class__(scalar * self.x, self.ring) + if isinstance(scalar, int): + return self.__class__(scalar * self.x, self.ring) + return NotImplemented def __truediv__(self, other: "ZmodPoint") -> "ZmodPoint": - if not isinstance(other, self.__class__) or self.ring != other.ring: - return NotImplemented - return self.__class__(self.x * pow(other.x, -1, self.ring.n), self.ring) + if isinstance(other, self.__class__): + if self.ring != other.ring: + raise NotImplementedError("Cannot divide elements from different rings.") + return self.__class__(self.x * pow(other.x, -1, self.ring.n), self.ring) + return NotImplemented def __rtruediv__(self, scalar: int) -> "ZmodPoint": - return self.__class__(scalar * pow(self.x, -1, self.ring.n), self.ring) + if isinstance(scalar, int): + return self.__class__(scalar * pow(self.x, -1, self.ring.n), self.ring) + return NotImplemented def __pow__(self, scalar: int) -> "ZmodPoint": - return self.__class__(pow(self.x, scalar, self.ring.n), self.ring) + if isinstance(scalar, int): + return self.__class__(pow(self.x, scalar, self.ring.n), self.ring) + return NotImplemented def sharp(self): "Returns a symmetric (w.r.t. 0) representative." diff --git a/kryptools/dlp.py b/kryptools/dlp.py index 4a73d99..4f7852c 100644 --- a/kryptools/dlp.py +++ b/kryptools/dlp.py @@ -11,7 +11,7 @@ from .factor import factorint -def dlog_naive(a: int, b: int, n: int, m: int = None) -> int: +def dlog_naive(a: int, b: int, n: int, m: int = None) -> int|None: """Compute the discrete log_a(b) in Z_n of an element a of order m by exhaustive search.""" a %= n b %= n @@ -43,14 +43,14 @@ def _dlog_ph(a: int, b: int, n: int, q: int, k: int) -> int: for j in range(2, k + 1): aj = pow(a, q ** (k - j), n) bj = pow(b, q ** (k - j), n) - yj = _dlog_switch(a1, bj * pow(aj, -xj, n) % n, n, q) + yj = _dlog_switch(a1, bj * pow(aj, -xj, n) % n, n, q) # pylint: disable=E1130 if yj is None: return None xj = xj + q ** (j - 1) * yj % q**j return xj -def dlog(a: int, b: int, n: int, m: int = None) -> int: +def dlog(a: int, b: int, n: int, m: int|None = None) -> int: """Compute the discrete log_a(b) in Z_n of an element a of order m using Pohlig-Hellman reduction.""" a %= n b %= n @@ -60,7 +60,8 @@ def dlog(a: int, b: int, n: int, m: int = None) -> int: mf = factorint(m) else: m, mf = order(a, n, True) - assert pow(b, m, n) == 1, "DLP not solvable." + if pow(b, m, n) != 1: + raise ValueError("DLP not solvable.") # We first use Pohlig-Hellman to split m into powers of prime factors mm = [] ll = [] diff --git a/kryptools/dlp_qs.py b/kryptools/dlp_qs.py index 45204cd..d1eceba 100644 --- a/kryptools/dlp_qs.py +++ b/kryptools/dlp_qs.py @@ -227,7 +227,7 @@ def process_relation(relation: list) -> None or int: if r == 0: roots = [ -(inv2 * aa) % p ] # one root else: - roots = [ (inv2 * (r - aa)) % p, (inv2 * (-r - aa)) % p ] # two roots + roots = [ (inv2 * (r - aa)) % p, (inv2 * (-r - aa)) % p ] # two roots pylint: disable=E1130 for r in roots: x = r # start value for x while x < max_j: @@ -255,10 +255,10 @@ def process_relation(relation: list) -> None or int: relation = find_relation(include_b) res = process_relation(relation) if res: - return(res) + return res # - # find the B-smooth numbers and add them to the system + # find the B-smooth numbers and add them to the system # for s in range(sieve_bound): diff --git a/kryptools/ec.py b/kryptools/ec.py index 29751f8..ec3b564 100644 --- a/kryptools/ec.py +++ b/kryptools/ec.py @@ -320,7 +320,7 @@ def __rmul__(self, scalar: int) -> "ECPoint": def __neg__(self) -> "ECPoint": if self.x is None or not self.y: return self - return ECPoint(self.x, -self.y, self.curve) + return ECPoint(self.x, -self.y, self.curve) # pylint: disable=E1130 def order(self) -> int: """Compute the order of an element.""" diff --git a/kryptools/factor_ecm.py b/kryptools/factor_ecm.py index 4adad6a..3f4aa22 100644 --- a/kryptools/factor_ecm.py +++ b/kryptools/factor_ecm.py @@ -84,7 +84,7 @@ def _ecm_parameters(B1: int, B2: int = None, D: int = None, primes: tuple = None return D, stage_one, stage_two_deltas -def factor_ecm(n: int, B1: int = 11000, B2: int = 1900000, curves: int = 74, ecm_parameters: tuple = None): +def factor_ecm(n: int, B1: int = 11000, B2: int = 1900000, curves: int = 74, ecm_parameters: tuple|None = None): "Factors a number n using Lentsta's ECM method." if ecm_parameters: diff --git a/kryptools/la.py b/kryptools/la.py index 5c82643..c9f13cb 100644 --- a/kryptools/la.py +++ b/kryptools/la.py @@ -3,6 +3,8 @@ """ from math import inf, sqrt, prod +from numbers import Number + class Matrix: """ @@ -149,12 +151,16 @@ def multiply(self, other) -> "Matrix": return result def __add__(self, other) -> "Matrix": - if isinstance(other, Matrix) and other.cols == self.cols and other.rows == self.rows: + if isinstance(other, Matrix): + if other.cols != self.cols or other.rows != self.rows: + raise NotImplementedError("Matrix dimensions do not match!") return Matrix([ [ x1 + y1 for x1, y1 in zip(x,y)] for x, y in zip(self.matrix, other.matrix)]) return NotImplemented def __sub__(self, other) -> "Matrix": - if isinstance(other, Matrix) and other.cols == self.cols and other.rows == self.rows: + if isinstance(other, Matrix): + if other.cols != self.cols or other.rows != self.rows: + raise NotImplementedError("Matrix dimensions do not match!") return Matrix([ [ x1 - y1 for x1, y1 in zip(x,y)] for x, y in zip(self.matrix, other.matrix)]) return NotImplemented @@ -164,12 +170,14 @@ def __neg__(self) -> "Matrix": def __mul__(self, other) -> "Matrix": if isinstance(other, Matrix): return self.multiply(other) - return Matrix([ [item * other for item in row] for row in self.matrix ]) + if isinstance(other, Number) or type(other) == type(self.matrix[0][0]): + return Matrix([ [item * other for item in row] for row in self.matrix ]) + return NotImplemented def __rmul__(self, other) -> "Matrix": - if isinstance(other, Matrix): - return self.multiply(other) - return Matrix([ [item * other for item in row] for row in self.matrix ]) + if isinstance(other, Number) or type(other) == type(self.matrix[0][0]): + return Matrix([ [item * other for item in row] for row in self.matrix ]) + return NotImplemented def rref(self) -> "Matrix": "Compute the reduced echelon form of a matrix M." diff --git a/kryptools/nt.py b/kryptools/nt.py index 0ea9e5a..15bcb23 100644 --- a/kryptools/nt.py +++ b/kryptools/nt.py @@ -104,6 +104,7 @@ def crt(a: list[int], m: list[int]) -> int: def fraction_repr(self): + "Representation of a fraction." if self.denominator == 1: return str(self.numerator) return str(self.numerator) + "/" + str(self.denominator) @@ -228,7 +229,7 @@ def order(a: int, n: int, factor=False) -> int: """Compute the order of `a` in the group Z_n^*.""" a %= n assert a != 0 and gcd(a, n) == 1, f"{a} and {n} are not coprime!" - factors = dict() # We compute euler_phi(n) and its factorization in one pass + factors = {} # We compute euler_phi(n) and its factorization in one pass for p, k in factorint(n).items(): # first factorize n for pm, km in factorint(p - 1).items(): # factor p-1 and add the factors if pm in factors: @@ -255,7 +256,7 @@ def order(a: int, n: int, factor=False) -> int: else: break if factor and i < k: - factors_order[p] = k - i + factors_order[p] = k - i # pylint: disable=E0606 if factor: return order_a, factors_order return order_a diff --git a/kryptools/poly.py b/kryptools/poly.py index 6f08349..4ebb357 100644 --- a/kryptools/poly.py +++ b/kryptools/poly.py @@ -2,6 +2,8 @@ Polynomials """ +from numbers import Number + class Poly: """ Represents a polynomial as a list of coefficients. @@ -94,12 +96,11 @@ def map(self, func): def __add__(self, other: "Poly") -> "Poly": if not isinstance(other, self.__class__): - try: - tmp = self.coeff[:] + tmp = self.coeff[:] + if isinstance(other, int) or type(other) == type(tmp[0]): tmp[0] += other return self.__class__(tmp, modulus=self.modulus) - except: - return NotImplemented + return NotImplemented ls, lo = len(self.coeff), len(other.coeff) if ls < lo: scoeff = self.coeff + (lo - ls) * [0] @@ -116,12 +117,10 @@ def __add__(self, other: "Poly") -> "Poly": def __radd__(self, other: "Poly") -> "Poly": if not isinstance(other, self.__class__): - try: + if isinstance(other, Number) or type(other) == type(self.coeff[0]): tmp = self.coeff[:] tmp[0] += other return self.__class__(tmp, modulus=self.modulus) - except: - pass return NotImplemented def __neg__(self) -> "Poly": @@ -129,12 +128,11 @@ def __neg__(self) -> "Poly": def __sub__(self, other: "Poly") -> "Poly": if not isinstance(other, self.__class__): - try: + if isinstance(other, int) or type(other) == type(self.coeff[0]): tmp = self.coeff[:] tmp[0] -= other return self.__class__(tmp, modulus=self.modulus) - except: - return NotImplemented + return NotImplemented ls, lo = len(self.coeff), len(other.coeff) if ls < lo: scoeff = self.coeff + (lo - ls) * [0] @@ -147,24 +145,21 @@ def __sub__(self, other: "Poly") -> "Poly": modulus = self.modulus if not modulus and other.modulus: modulus = other.modulus - return self.__class__([s - o for s, o in zip(scoeff, ocoeff)], modulus=modulus) + return self.__class__([s - o for s, o in zip(scoeff, ocoeff)], modulus = modulus) def __rsub__(self, other: "Poly") -> "Poly": if not isinstance(other, self.__class__): - try: + if isinstance(other, int) or type(other) == type(self.coeff[0]): tmp = self.coeff[:] tmp[0] -= other return self.__class__(tmp, modulus=self.modulus) - except: - pass return NotImplemented def __mul__(self, other: "Poly") -> "Poly": if not isinstance(other, self.__class__): - try: - return Poly([other * s for s in self.coeff]) - except: - return NotImplemented + if isinstance(other, int) or type(other) == type(self.coeff[0]): + return Poly([other * s for s in self.coeff], modulus = self.modulus) + return NotImplemented ls, lo = len(self.coeff), len(other.coeff) coeff = [0] * (ls + lo - 1) for k in range(ls + lo - 1): @@ -177,23 +172,36 @@ def __mul__(self, other: "Poly") -> "Poly": modulus = self.modulus if not modulus and other.modulus: modulus = other.modulus - return self.__class__(coeff, modulus=modulus) + return self.__class__(coeff, modulus = modulus) def __rmul__(self, other: int) -> "Poly": - return self.__class__([other * s for s in self.coeff], modulus=self.modulus) + if isinstance(other, int) or type(other) == type(self.coeff[0]): + return self.__class__([other * s for s in self.coeff], modulus=self.modulus) + return NotImplemented def __pow__(self, i: int) -> "Poly": - res = self.__class__([1], modulus=self.modulus) + if not isinstance(i, int): + return NotImplemented + zero = 0 * self.coeff[0] + one = zero + 1 + res = self.__class__([one], modulus=self.modulus) if i < 0: if not self.modulus: - raise NotImplementedError("Cannot divide.") + raise NotImplementedError("Cannot divide polynomials without modulus.") tmp = self.inv() + i *= -1 else: tmp = self for _ in range(i): res *= tmp return res + def __floordiv__(self, other: "Poly") -> "Poly": + return self.divmod(other)[0] + + def __mod__(self, other: "Poly") -> "Poly": + return self.divmod(other)[1] + def divmod(self, other: "Poly") -> ("Poly", "Poly"): "Polynom division with remainder." if isinstance(other, list):