From 30887db256c3361c19cdcbd0382cb5ba5b634a33 Mon Sep 17 00:00:00 2001 From: Ivan Golikov Date: Fri, 3 Jan 2025 09:19:57 +0100 Subject: [PATCH 1/5] Added cryptography dependency --- poetry.lock | 143 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 754e86a..b98aab9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -69,6 +69,85 @@ files = [ {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "click" version = "8.1.8" @@ -94,6 +173,57 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cryptography" +version = "44.0.0" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = "!=3.9.0,!=3.9.1,>=3.7" +files = [ + {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, + {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, + {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, + {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, + {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, + {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, + {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, +] + +[package.dependencies] +cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +sdist = ["build (>=1.0.0)"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] +test-randomorder = ["pytest-randomly"] + [[package]] name = "decorator" version = "5.1.1" @@ -778,6 +908,17 @@ files = [ [package.extras] tests = ["pytest"] +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + [[package]] name = "pydantic" version = "2.10.4" @@ -1501,4 +1642,4 @@ hiredis = ["hiredis"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "9f0f96c653fdc92b7a1ed18be32ff88814ac5188b207fda1ea7e672a7cd19d6c" +content-hash = "0da53315dee1155cfa3ec180a9120b32145497e290f13e17e481597179e2c993" diff --git a/pyproject.toml b/pyproject.toml index 326956a..afce1cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ click = "8.1.8" fastapi = { version = "0.115.6", extras = [ "standard" ] } redis = "5.2.1" hiredis = { version = "3.1.0", optional = true } +cryptography = "^44" [tool.poetry.extras] hiredis = ["hiredis"] -- 2.43.0 From ba7537e15e1d43d5ea688517f1f3bdcc415fe0c7 Mon Sep 17 00:00:00 2001 From: Ivan Golikov Date: Fri, 3 Jan 2025 12:04:51 +0100 Subject: [PATCH 2/5] Secrets encryption --- README.md | 3 +++ pssecret_server/fernet.py | 8 ++++++++ pssecret_server/main.py | 12 ++++++++---- pssecret_server/settings.py | 5 ++++- pssecret_server/utils.py | 10 ++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 pssecret_server/fernet.py diff --git a/README.md b/README.md index 03f3976..24e58c8 100644 --- a/README.md +++ b/README.md @@ -88,5 +88,8 @@ Configuration is done via environment variables. Environment variables: - `REDIS_URL`: URL for Redis access. Check what values are supported [here](https://redis.readthedocs.io/en/stable/connections.html#redis.Redis.from_url). +- `SECRETS_ENCRYPTION_KEY`: Key used for encrypting stored data. You can also declare these variables in a `.env` file in the working directory. +Protect this file (or other source from where `SECRETS_ENCRYPTION_KEY` is read by application) +from being read by unauthorized parties. diff --git a/pssecret_server/fernet.py b/pssecret_server/fernet.py new file mode 100644 index 0000000..c90d010 --- /dev/null +++ b/pssecret_server/fernet.py @@ -0,0 +1,8 @@ +from cryptography.fernet import Fernet +from pssecret_server.settings import Settings, get_settings +from typing import Annotated +from fastapi import Depends + + +def get_fernet(settings: Annotated[Settings, Depends(get_settings)]) -> Fernet: + return Fernet(settings.secrets_encryption_key) diff --git a/pssecret_server/main.py b/pssecret_server/main.py index 45dadd3..46c39d8 100644 --- a/pssecret_server/main.py +++ b/pssecret_server/main.py @@ -1,16 +1,19 @@ from typing import Annotated +from cryptography.fernet import Fernet from fastapi import Depends, FastAPI from fastapi.exceptions import HTTPException from redis.asyncio import Redis +from pssecret_server.fernet import get_fernet from pssecret_server.models import Secret, SecretSaveResult from pssecret_server.redis_db import get_redis -from pssecret_server.utils import save_secret +from pssecret_server.utils import decrypt_secret, encrypt_secret, save_secret app = FastAPI() RedisDep = Annotated[Redis, Depends(get_redis)] +FernetDep = Annotated[Fernet, Depends(get_fernet)] @app.post( @@ -23,7 +26,8 @@ RedisDep = Annotated[Redis, Depends(get_redis)] ), response_model=SecretSaveResult, ) -async def set_secret(data: Secret, redis: RedisDep) -> dict[str, str]: +async def set_secret(data: Secret, redis: RedisDep, fernet: FernetDep) -> dict[str, str]: + data = encrypt_secret(data, fernet) return { "key": await save_secret(data, redis), } @@ -40,12 +44,12 @@ async def set_secret(data: Secret, redis: RedisDep) -> dict[str, str]: response_model=Secret, responses={404: {"description": "The item was not found"}}, ) -async def get_secret(secret_key: str, redis: RedisDep) -> dict[str, bytes]: +async def get_secret(secret_key: str, redis: RedisDep, fernet: FernetDep) -> dict[str, bytes]: data: bytes | None = await redis.getdel(secret_key) if data is None: raise HTTPException(404) return { - "data": data, + "data": decrypt_secret(data, fernet), } diff --git a/pssecret_server/settings.py b/pssecret_server/settings.py index e761e9a..ae7fffe 100644 --- a/pssecret_server/settings.py +++ b/pssecret_server/settings.py @@ -1,9 +1,12 @@ from pydantic import RedisDsn -from pydantic_settings import BaseSettings +from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): + model_config = SettingsConfigDict(env_file=".env") + redis_url: RedisDsn = RedisDsn("redis://localhost") + secrets_encryption_key: bytes def get_settings() -> Settings: diff --git a/pssecret_server/utils.py b/pssecret_server/utils.py index 01dacfc..b1ae479 100644 --- a/pssecret_server/utils.py +++ b/pssecret_server/utils.py @@ -1,10 +1,20 @@ from uuid import uuid4 from redis.asyncio import Redis +from cryptography.fernet import Fernet from pssecret_server.models import Secret +def encrypt_secret(data: Secret, fernet: Fernet) -> Secret: + data.data = fernet.encrypt(data.data.encode()).decode() + return data + + +def decrypt_secret(secret: bytes, fernet: Fernet) -> bytes: + return fernet.decrypt(secret) + + async def get_new_key(redis: Redis) -> str: """Returns free Redis key""" while True: -- 2.43.0 From 34a9b059ddcecc23143d78377f3e77f7c979ff21 Mon Sep 17 00:00:00 2001 From: Ivan Golikov Date: Fri, 3 Jan 2025 15:24:09 +0100 Subject: [PATCH 3/5] Returning new secret instead of replacing data --- pssecret_server/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pssecret_server/utils.py b/pssecret_server/utils.py index b1ae479..239ff37 100644 --- a/pssecret_server/utils.py +++ b/pssecret_server/utils.py @@ -7,8 +7,8 @@ from pssecret_server.models import Secret def encrypt_secret(data: Secret, fernet: Fernet) -> Secret: - data.data = fernet.encrypt(data.data.encode()).decode() - return data + encrypted = fernet.encrypt(data.data.encode()).decode() + return Secret(data=encrypted) def decrypt_secret(secret: bytes, fernet: Fernet) -> bytes: -- 2.43.0 From fbe40107be2d5fc410a66d35f3abddbe57fdba8d Mon Sep 17 00:00:00 2001 From: Ivan Golikov Date: Fri, 3 Jan 2025 15:28:15 +0100 Subject: [PATCH 4/5] Tests for encryption --- tests/conftest.py | 7 +++++++ tests/unit/__init__.py | 0 tests/unit/test_utils.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tests/unit/__init__.py create mode 100644 tests/unit/test_utils.py diff --git a/tests/conftest.py b/tests/conftest.py index 87da6ad..b7e212f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,10 +1,12 @@ from collections.abc import AsyncGenerator +from cryptography.fernet import Fernet import pytest from fastapi.testclient import TestClient from pydantic_settings import SettingsConfigDict from redis import asyncio as aioredis +from pssecret_server.fernet import get_fernet from pssecret_server.main import app from pssecret_server.settings import Settings, get_settings @@ -29,6 +31,11 @@ def get_test_settings() -> Settings: return TestSettings() +@pytest.fixture +def fernet(settings: Settings) -> Fernet: + return get_fernet(settings) + + @pytest.fixture(scope="session") def client() -> TestClient: client_ = TestClient(app) diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py new file mode 100644 index 0000000..35cc82f --- /dev/null +++ b/tests/unit/test_utils.py @@ -0,0 +1,29 @@ +from cryptography.fernet import Fernet, InvalidToken +import pytest +from pssecret_server.utils import encrypt_secret, decrypt_secret +from ..factories import SecretFactory + + +def test_encrypte_secret_ok(fernet: Fernet): + secret = SecretFactory().build() + encrypted_secret = encrypt_secret(secret, fernet) + + assert secret.data != encrypted_secret.data + + +def test_secret_is_decryptable_by_correct_key(fernet: Fernet): + secret = SecretFactory().build() + encrypted_secret = encrypt_secret(secret, fernet) + decrypted_secret = decrypt_secret(encrypted_secret.data.encode(), fernet) + + assert decrypted_secret.decode() == secret.data + + +def test_secret_is_not_decryptable_by_random_key(fernet: Fernet): + secret = SecretFactory().build() + encrypted_secret = encrypt_secret(secret, fernet) + + random_fernet = Fernet(Fernet.generate_key()) + + with pytest.raises(InvalidToken): + decrypt_secret(encrypted_secret.data.encode(), random_fernet) -- 2.43.0 From f0be12394c3e22572e83881a331d2b3f5c7b8d37 Mon Sep 17 00:00:00 2001 From: Ivan Golikov Date: Fri, 3 Jan 2025 15:32:01 +0100 Subject: [PATCH 5/5] Linting --- pssecret_server/fernet.py | 6 ++++-- pssecret_server/main.py | 8 ++++++-- pssecret_server/utils.py | 2 +- tests/conftest.py | 4 ++-- tests/unit/test_utils.py | 8 +++++--- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/pssecret_server/fernet.py b/pssecret_server/fernet.py index c90d010..aa63600 100644 --- a/pssecret_server/fernet.py +++ b/pssecret_server/fernet.py @@ -1,8 +1,10 @@ -from cryptography.fernet import Fernet -from pssecret_server.settings import Settings, get_settings from typing import Annotated + +from cryptography.fernet import Fernet from fastapi import Depends +from pssecret_server.settings import Settings, get_settings + def get_fernet(settings: Annotated[Settings, Depends(get_settings)]) -> Fernet: return Fernet(settings.secrets_encryption_key) diff --git a/pssecret_server/main.py b/pssecret_server/main.py index 46c39d8..6c90499 100644 --- a/pssecret_server/main.py +++ b/pssecret_server/main.py @@ -26,7 +26,9 @@ FernetDep = Annotated[Fernet, Depends(get_fernet)] ), response_model=SecretSaveResult, ) -async def set_secret(data: Secret, redis: RedisDep, fernet: FernetDep) -> dict[str, str]: +async def set_secret( + data: Secret, redis: RedisDep, fernet: FernetDep +) -> dict[str, str]: data = encrypt_secret(data, fernet) return { "key": await save_secret(data, redis), @@ -44,7 +46,9 @@ async def set_secret(data: Secret, redis: RedisDep, fernet: FernetDep) -> dict[s response_model=Secret, responses={404: {"description": "The item was not found"}}, ) -async def get_secret(secret_key: str, redis: RedisDep, fernet: FernetDep) -> dict[str, bytes]: +async def get_secret( + secret_key: str, redis: RedisDep, fernet: FernetDep +) -> dict[str, bytes]: data: bytes | None = await redis.getdel(secret_key) if data is None: diff --git a/pssecret_server/utils.py b/pssecret_server/utils.py index 239ff37..e57b710 100644 --- a/pssecret_server/utils.py +++ b/pssecret_server/utils.py @@ -1,7 +1,7 @@ from uuid import uuid4 -from redis.asyncio import Redis from cryptography.fernet import Fernet +from redis.asyncio import Redis from pssecret_server.models import Secret diff --git a/tests/conftest.py b/tests/conftest.py index b7e212f..88c8915 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ from collections.abc import AsyncGenerator -from cryptography.fernet import Fernet import pytest +from cryptography.fernet import Fernet from fastapi.testclient import TestClient from pydantic_settings import SettingsConfigDict from redis import asyncio as aioredis @@ -31,7 +31,7 @@ def get_test_settings() -> Settings: return TestSettings() -@pytest.fixture +@pytest.fixture def fernet(settings: Settings) -> Fernet: return get_fernet(settings) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index 35cc82f..de2984b 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -1,13 +1,15 @@ -from cryptography.fernet import Fernet, InvalidToken import pytest -from pssecret_server.utils import encrypt_secret, decrypt_secret +from cryptography.fernet import Fernet, InvalidToken + +from pssecret_server.utils import decrypt_secret, encrypt_secret + from ..factories import SecretFactory def test_encrypte_secret_ok(fernet: Fernet): secret = SecretFactory().build() encrypted_secret = encrypt_secret(secret, fernet) - + assert secret.data != encrypted_secret.data -- 2.43.0