From 3a16dfb0f7ba0da18cef1d988ff08f72f5615057 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Fri, 31 Mar 2023 01:52:22 +0200 Subject: [PATCH 1/3] Backport crypto from 21a207e273b0fa61de776b2f3b56b0f727bacb83 which include sequester support --- Cargo.lock | 349 +++- oxidation/libparsec/crates/crypto/Cargo.toml | 88 +- .../crates/crypto/src/common/error.rs | 8 + .../libparsec/crates/crypto/src/common/mod.rs | 2 + .../crates/crypto/src/common/secret.rs | 5 +- .../crates/crypto/src/common/sequester.rs | 71 + oxidation/libparsec/crates/crypto/src/lib.rs | 27 +- .../crates/crypto/src/rustcrypto/mod.rs | 2 + .../crates/crypto/src/rustcrypto/private.rs | 8 +- .../crates/crypto/src/rustcrypto/secret.rs | 40 +- .../crates/crypto/src/rustcrypto/sequester.rs | 328 +++ .../crates/crypto/src/rustcrypto/sign.rs | 21 +- .../crates/crypto/src/sodiumoxide/mod.rs | 2 + .../crates/crypto/src/sodiumoxide/secret.rs | 63 +- .../crypto/src/sodiumoxide/sequester.rs | 401 ++++ .../crates/crypto/src/sodiumoxide/sign.rs | 18 +- .../libparsec/crates/crypto/src/traits.rs | 162 -- .../crates/crypto/tests/anti_leak.rs | 10 + .../crates/crypto/tests/common/mod.rs | 4 +- .../libparsec/crates/crypto/tests/secret.rs | 21 +- .../crates/crypto/tests/sequester.rs | 307 +++ .../libparsec/crates/crypto/tests/sign.rs | 12 +- parsec/_parsec_pyi/crypto.pyi | 41 + parsec/backend/asgi/rpc.py | 3 +- parsec/crypto.py | 17 +- parsec/sequester_crypto.py | 180 +- poetry.lock | 1826 ++++++++--------- pyproject.toml | 2 - src/api_crypto.rs | 374 +++- src/binding_utils.rs | 16 + src/lib.rs | 8 +- tests/conftest.py | 16 +- 32 files changed, 2857 insertions(+), 1575 deletions(-) create mode 100644 oxidation/libparsec/crates/crypto/src/common/sequester.rs create mode 100644 oxidation/libparsec/crates/crypto/src/rustcrypto/sequester.rs create mode 100644 oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs delete mode 100644 oxidation/libparsec/crates/crypto/src/traits.rs create mode 100644 oxidation/libparsec/crates/crypto/tests/anti_leak.rs create mode 100644 oxidation/libparsec/crates/crypto/tests/sequester.rs diff --git a/Cargo.lock b/Cargo.lock index 1a285146a55..7c43169d25f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,12 +10,12 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aead" -version = "0.4.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8" dependencies = [ - "generic-array 0.14.6", - "rand_core 0.6.3", + "crypto-common", + "generic-array 0.14.7", ] [[package]] @@ -283,9 +283,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake2" -version = "0.10.4" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cf849ee05b2ee5fba5e36f97ff8ec2533916700fc0758d40d92136a42f3388" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ "digest 0.10.5", ] @@ -308,7 +308,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] @@ -317,7 +317,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] @@ -375,9 +375,9 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cesu8" @@ -393,21 +393,20 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chacha20" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" +checksum = "c7fc89c7c5b9e7a02dfe45cd2367bae382f9ed31c61ca8debe5f827c420a2f08" dependencies = [ "cfg-if", "cipher", "cpufeatures", - "zeroize", ] [[package]] name = "chacha20poly1305" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ "aead", "chacha20", @@ -434,11 +433,13 @@ dependencies = [ [[package]] name = "cipher" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array 0.14.6", + "crypto-common", + "inout", + "zeroize", ] [[package]] @@ -491,6 +492,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "const-oid" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" + [[package]] name = "core-foundation" version = "0.9.3" @@ -537,25 +544,26 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", + "rand_core 0.6.3", "typenum", ] [[package]] name = "crypto_box" -version = "0.7.2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2bcbd5e4fc3ad3de2d0e75509f870a6fa9f488e0e2c9a8ce49721a52efc4e" +checksum = "fd26c32de5307fd08aac445a75c43472b14559d5dccdfba8022dbcd075838ebc" dependencies = [ + "aead", "chacha20", "chacha20poly1305", - "rand_core 0.6.3", "salsa20", - "x25519-dalek", + "x25519-dalek 1.1.1", "xsalsa20poly1305", "zeroize", ] @@ -572,9 +580,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", "digest 0.9.0", @@ -624,6 +632,17 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "diesel" version = "2.0.2" @@ -668,7 +687,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] @@ -678,6 +697,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" dependencies = [ "block-buffer 0.10.2", + "const-oid", "crypto-common", "subtle", ] @@ -690,9 +710,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] name = "ed25519" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ "signature", ] @@ -824,7 +844,7 @@ dependencies = [ "futures-sink", "nanorand", "pin-project", - "spin", + "spin 0.9.3", ] [[package]] @@ -989,9 +1009,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "serde", "typenum", @@ -1232,6 +1252,15 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05a0bd019339e5d968b37855180087b7b9d512c5046fbd244cf8c95687927d6e" +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.7", +] + [[package]] name = "instant" version = "0.1.12" @@ -1340,6 +1369,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" @@ -1357,6 +1389,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "libparsec" version = "0.1.0" @@ -1446,7 +1484,7 @@ dependencies = [ "pretty_assertions", "regex", "rmp-serde", - "rstest", + "rstest 0.15.0", "rstest_reuse", "serde", "serde_bytes", @@ -1467,7 +1505,7 @@ dependencies = [ "libparsec_protocol", "libparsec_types", "rmp-serde", - "rstest", + "rstest 0.15.0", "serde", "serde_with", "tests_fixtures", @@ -1484,7 +1522,7 @@ dependencies = [ "libparsec_types", "libsqlite3-sys", "regex", - "rstest", + "rstest 0.15.0", "tests_fixtures", "thiserror", "uuid", @@ -1500,26 +1538,30 @@ dependencies = [ "crypto_box", "digest 0.10.5", "ed25519-dalek", - "generic-array 0.14.6", + "generic-array 0.14.7", "getrandom 0.1.16", "getrandom 0.2.6", "hex", "hex-literal", "lazy_static", "libsodium-sys", + "openssl", "pretty_assertions", "rand 0.7.3", "rand 0.8.5", "rmp-serde", - "rstest", + "rsa", + "rstest 0.16.0", "serde", "serde_bytes", "serde_test", + "sha1", "sha2 0.10.6", "sodiumoxide", "thiserror", - "x25519-dalek", + "x25519-dalek 2.0.0-pre.1", "xsalsa20poly1305", + "zeroize", ] [[package]] @@ -1552,7 +1594,7 @@ dependencies = [ "http", "libparsec_protocol", "libparsec_types", - "rstest", + "rstest 0.15.0", "smol", "tests_fixtures", ] @@ -1573,7 +1615,7 @@ dependencies = [ "paste", "rand 0.8.5", "rmp-serde", - "rstest", + "rstest 0.15.0", "serde", "serde_json", "serde_with", @@ -1602,7 +1644,7 @@ dependencies = [ "rand 0.8.5", "regex", "rmp-serde", - "rstest", + "rstest 0.15.0", "rstest_reuse", "serde", "serde_bytes", @@ -1804,6 +1846,23 @@ dependencies = [ "smallvec", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1814,6 +1873,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1821,6 +1891,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1892,6 +1963,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-src" +version = "111.25.2+1.1.1t" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320708a054ad9b3bf314688b5db87cf4d6683d64cfc835e2337924ae62bf4431" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.74" @@ -1901,6 +1981,7 @@ dependencies = [ "autocfg", "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -1999,6 +2080,15 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.2.0" @@ -2080,6 +2170,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719" +dependencies = [ + "der", + "pkcs8", + "spki", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -2101,9 +2213,9 @@ dependencies = [ [[package]] name = "poly1305" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ "cpufeatures", "opaque-debug 0.3.0", @@ -2422,6 +2534,27 @@ dependencies = [ "serde", ] +[[package]] +name = "rsa" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" +dependencies = [ + "byteorder", + "digest 0.10.5", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.3", + "signature", + "smallvec", + "subtle", + "zeroize", +] + [[package]] name = "rstest" version = "0.15.0" @@ -2430,7 +2563,19 @@ checksum = "e9c9dc66cc29792b663ffb5269be669f1613664e69ad56441fdb895c2347b930" dependencies = [ "futures", "futures-timer", - "rstest_macros", + "rstest_macros 0.14.0", + "rustc_version", +] + +[[package]] +name = "rstest" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f2d176c472198ec1e6551dc7da28f1c089652f66a7b722676c2238ebc0edf" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros 0.16.0", "rustc_version", ] @@ -2447,6 +2592,20 @@ dependencies = [ "syn", ] +[[package]] +name = "rstest_macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7229b505ae0706e64f37ffc54a9c163e11022a6636d58fe1f3f52018257ff9f7" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "rustc_version", + "syn", + "unicode-ident", +] + [[package]] name = "rstest_reuse" version = "0.4.0" @@ -2489,12 +2648,11 @@ checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" [[package]] name = "salsa20" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" dependencies = [ "cipher", - "zeroize", ] [[package]] @@ -2592,9 +2750,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.7" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" +checksum = "416bda436f9aab92e02c8e10d49a15ddd339cea90b6e340fe51ed97abb548294" dependencies = [ "serde", ] @@ -2623,9 +2781,9 @@ dependencies = [ [[package]] name = "serde_test" -version = "1.0.145" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c17d2112159132660b4c5399e274f676fb75a2f8d70b7468f18f045b71138ed" +checksum = "f259aa64e48efaf5a4fea11f97cacb109f7fc3ae9db7244cbb40c01c7faf42bc" dependencies = [ "serde", ] @@ -2680,7 +2838,7 @@ dependencies = [ "pretty_assertions", "proc-macro2", "quote", - "rstest", + "rstest 0.15.0", "serde", "serde_json", "syn", @@ -2709,6 +2867,17 @@ dependencies = [ "digest 0.10.5", ] +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.5", +] + [[package]] name = "sha2" version = "0.9.9" @@ -2731,16 +2900,6 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.10.5", - "sha2-asm", -] - -[[package]] -name = "sha2-asm" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf27176fb5d15398e3a479c652c20459d9dac830dedd1fa55b42a77dbcdbfcea" -dependencies = [ - "cc", ] [[package]] @@ -2764,9 +2923,13 @@ dependencies = [ [[package]] name = "signature" -version = "1.5.0" +version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.5", + "rand_core 0.6.3", +] [[package]] name = "simple_logger" @@ -2789,9 +2952,9 @@ checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smol" @@ -2833,6 +2996,12 @@ dependencies = [ "serde", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.3" @@ -2842,6 +3011,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "strsim" version = "0.10.0" @@ -2926,7 +3105,7 @@ dependencies = [ "libparsec_client_types", "libparsec_crypto", "libparsec_types", - "rstest", + "rstest 0.15.0", "uuid", ] @@ -3133,9 +3312,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -3160,11 +3339,11 @@ checksum = "52fee519a3e570f7df377a06a1a7775cdbfb7aa460be7e08de2b1f0e69973a44" [[package]] name = "universal-hash" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" dependencies = [ - "generic-array 0.14.6", + "crypto-common", "subtle", ] @@ -3515,24 +3694,34 @@ dependencies = [ [[package]] name = "x25519-dalek" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" dependencies = [ "curve25519-dalek", "rand_core 0.5.1", "zeroize", ] +[[package]] +name = "x25519-dalek" +version = "2.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.3", + "zeroize", +] + [[package]] name = "xsalsa20poly1305" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68bcb965d6c650091450b95cea12f07dcd299a01c15e2f9433b0813ea3c0886" +checksum = "472c385ee974833d7e59979eeb74175d56774be3768b5bcc581337e21396bda3" dependencies = [ "aead", "poly1305", - "rand_core 0.6.3", "salsa20", "subtle", "zeroize", @@ -3546,9 +3735,9 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zeroize" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" dependencies = [ "zeroize_derive", ] diff --git a/oxidation/libparsec/crates/crypto/Cargo.toml b/oxidation/libparsec/crates/crypto/Cargo.toml index cc45d382d3c..e13189aefb4 100644 --- a/oxidation/libparsec/crates/crypto/Cargo.toml +++ b/oxidation/libparsec/crates/crypto/Cargo.toml @@ -6,36 +6,74 @@ license = " BUSL-1.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = ["use-sodiumoxide"] +test-unsecure-but-fast-secretkey-from-password = [] +use-sodiumoxide = [ + "dep:sodiumoxide", + "dep:libsodium-sys", + "dep:openssl", + "dep:zeroize", +] +use-rustcrypto = [ + "dep:argon2", + "dep:blake2", + "dep:crypto_box", + "dep:digest", + "dep:ed25519-dalek", + "dep:generic-array", + "dep:getrandom_01", + "dep:getrandom_02", + "dep:lazy_static", + "dep:rand_07", + "dep:rand_08", + "dep:rsa", + "dep:sha1", + "dep:sha2", + "dep:x25519-dalek", + "dep:xsalsa20poly1305", +] + [dependencies] serde = { version = "1.0.147", features = ["derive"] } -serde_bytes = { version = "0.11.7" } +serde_bytes = { version = "0.11.9" } hex = "0.4" thiserror = "1.0.37" base32 = "0.4.0" +# +# SodiumOxide&friends stuff +# + sodiumoxide = { version = "0.2.7", optional = true } libsodium-sys = { version = "0.2.7", optional = true } +openssl = { version = "0.10", optional = true, features = ["vendored"] } +zeroize = { version = "1", optional = true, features = ["alloc"]} argon2 = { version = "0.4.1", optional = true } -blake2 = { version = "0.10.0", optional = true } -crypto_box = { version = "0.7.0", optional = true, features = ["std"] } +blake2 = { version = "0.10.6", optional = true } +crypto_box = { version = "0.8.2", features = ["std"], optional = true } digest = { version = "0.10.5", optional = true } ed25519-dalek = { version = "1.0.1", optional = true } -generic-array = { version = "0.14.6", optional = true, features = ["serde"] } +generic-array = { version = "0.14.7", features = ["serde"], optional = true } lazy_static = { version = "1.4.0", optional = true } +rsa = { version = "0.7.2", optional = true } +sha1 = { version = "0.10.5", optional = true } sha2 = { version = "0.10.6", optional = true } -x25519-dalek = { version = "1.2.0", optional = true } -xsalsa20poly1305 = { version = "0.8.0", optional = true } - +# This is exceptionally allowed since no significant changes +# were made from the last stable version to this major pre-release version. +# TODO: bump to a stable version. +x25519-dalek = { version = "2.0.0-pre.1", optional = true } +xsalsa20poly1305 = { version = "0.9.0", optional = true } # Cryptographic randomness is required for generating SecretKey, SigningKey and PrivateKey # For SecretKey, we have `crypto_box` -> [...] -> `rand_core~=0.6` -> `getrandom~=0.2` # For SingingKey&PrivateKey we have `` -> `rand~=0.5` -> `getrandom~=0.1` -# So we endup with two version of `getrandom` which have each they own way of +# So we end up with two version of `getrandom` which have each they own way of # configuring wasm-unknown-unknown web support (see [features] part). getrandom_01 = { package = "getrandom", version = "0.1.16", optional = true } getrandom_02 = { package = "getrandom", version = "0.2.3", optional = true } # On top of that we need to have access to the two version of rand (0.7 and 0.8) -# to provide the randmoness configuration to the crypto functions. +# to provide the randomness configuration to the crypto functions. # rand 0.7 relies on rand_core~=0.5/getrandom~=0.1 rand_07 = { package = "rand", version = "0.7", optional = true } # rand 0.8 relies on rand_core~=0.6/getrandom~=0.2 @@ -43,34 +81,16 @@ rand_08 = { package = "rand", version = "0.8", optional = true } [dev-dependencies] pretty_assertions = "1.3.0" -serde_test = "1.0.145" +serde_test = "1.0.152" hex-literal = "0.3.3" rmp-serde = "1.1.1" -rstest = "0.15.0" - -[features] -default = ["use-rustcrypto"] -use-sodiumoxide = ["sodiumoxide", "libsodium-sys"] -use-rustcrypto = [ - "argon2", - "blake2", - "crypto_box", - "digest", - "ed25519-dalek", - "generic-array", - "getrandom_01", - "getrandom_02", - "lazy_static", - "rand_07", - "rand_08", - "sha2", - "x25519-dalek", - "xsalsa20poly1305", -] -# The asm feature will enable asm feature for sha2 if something else enables the sha2 dependency. -# This feature is needed due to platform which doesn't support asm -asm = ["sha2?/asm"] +rstest = "0.16.0" [target.'cfg(target_arch = "wasm32")'.dependencies] + +# +# RustCrypto stuff +# + getrandom_01 = { package = "getrandom", version = "0.1.16", features = ["wasm-bindgen"], optional = true } getrandom_02 = { package = "getrandom", version = "0.2.3", features = ["js"], optional = true } diff --git a/oxidation/libparsec/crates/crypto/src/common/error.rs b/oxidation/libparsec/crates/crypto/src/common/error.rs index ebc5069f734..71f23179e18 100644 --- a/oxidation/libparsec/crates/crypto/src/common/error.rs +++ b/oxidation/libparsec/crates/crypto/src/common/error.rs @@ -4,6 +4,8 @@ use thiserror::Error; #[derive(Error, Debug, PartialEq, Eq)] pub enum CryptoError { + #[error("Unsupported algorithm: {0}")] + Algorithm(String), #[error("Invalid signature")] Signature, #[error("Signature was forged or corrupt")] @@ -12,8 +14,14 @@ pub enum CryptoError { DataSize, #[error("Decryption error")] Decryption, + #[error("Invalid key size: expected {expected} bytes, got {got} bytes")] + KeySize { expected: usize, got: usize }, #[error("The nonce must be exactly 24 bytes long")] Nonce, + #[error("Invalid SequesterPrivateKeyDer {0}")] + SequesterPrivateKeyDer(String), + #[error("Invalid SequesterPublicKeyDer {0}")] + SequesterPublicKeyDer(String), } pub type CryptoResult = Result; diff --git a/oxidation/libparsec/crates/crypto/src/common/mod.rs b/oxidation/libparsec/crates/crypto/src/common/mod.rs index 806f6a4ced6..ee1ec69f10e 100644 --- a/oxidation/libparsec/crates/crypto/src/common/mod.rs +++ b/oxidation/libparsec/crates/crypto/src/common/mod.rs @@ -2,9 +2,11 @@ mod error; mod secret; +mod sequester; pub use error::*; pub(crate) use secret::*; +pub use sequester::*; macro_rules! impl_key_debug { ($name: ident) => { diff --git a/oxidation/libparsec/crates/crypto/src/common/secret.rs b/oxidation/libparsec/crates/crypto/src/common/secret.rs index e8159e94064..e902a632704 100644 --- a/oxidation/libparsec/crates/crypto/src/common/secret.rs +++ b/oxidation/libparsec/crates/crypto/src/common/secret.rs @@ -61,7 +61,10 @@ macro_rules! impl_secret_key { fn try_from(data: &[u8]) -> Result { <[u8; Self::SIZE]>::try_from(data) .map(Self::from) - .map_err(|_| CryptoError::DataSize) + .map_err(|_| CryptoError::KeySize { + expected: Self::SIZE, + got: data.len(), + }) } } diff --git a/oxidation/libparsec/crates/crypto/src/common/sequester.rs b/oxidation/libparsec/crates/crypto/src/common/sequester.rs new file mode 100644 index 00000000000..34d81235996 --- /dev/null +++ b/oxidation/libparsec/crates/crypto/src/common/sequester.rs @@ -0,0 +1,71 @@ +// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS + +use crate::{CryptoError, CryptoResult}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(usize)] +pub enum SequesterKeySize { + _1024Bits = 1024, + _2048Bits = 2048, + _3072Bits = 3072, + _4096Bits = 4096, +} + +/// Here we avoid unnecessary allocation & enforce output has `key_size` +pub(crate) fn serialize_with_armor( + output: &[u8], + data: &[u8], + key_size_bytes: usize, + algo: &str, +) -> Vec { + // It is important `output` has a constant size given this + // is how it is retrieved during decryption + assert!(output.len() <= key_size_bytes); + let mut res = vec![0; algo.len() + 1 + key_size_bytes + data.len()]; + + let (algorithm_part, others) = res.split_at_mut(algo.len()); + let (colon, others) = others.split_at_mut(1); + // Here we enforce output has key size with zeros + // Using RSA, we should end up with a number as big as the key size and + // provided as big endian bytes. + // However it is possible the number can be represented with less bytes if + // enough of its most significant bits are equal to zero. + // In such case, certain implementations (at least oscrypto on macOS 12) trim + // the null bytes and hence return a bytes array smaller than the key size. + // + // For instance, considering a 16bits RSA key size (state-of-the-art security ^^) + // and a RSA output `42`, the output can be represented as b"\x42" or b"\x00\x42) + // + // Long story short, we want to make sure our RSA output are always of the + // same size than the key, this simplify splitting messages and protect us + // if an RSA implementation on another platform is picky about output size. + let (_zeros, others) = others.split_at_mut(key_size_bytes - output.len()); + let (output_part, data_part) = others.split_at_mut(output.len()); + + algorithm_part.copy_from_slice(algo.as_bytes()); + colon[0] = b':'; + output_part.copy_from_slice(output); + data_part.copy_from_slice(data); + + res +} + +pub(crate) fn deserialize_with_armor<'a>( + data: &'a [u8], + key_size_bytes: usize, + algo: &str, +) -> CryptoResult<(&'a [u8], &'a [u8])> { + let index = data + .iter() + .position(|x| *x == b':') + .ok_or(CryptoError::Decryption)?; + let (algorithm, output_and_data) = data.split_at(index + 1); + + if &algorithm[..index] != algo.as_bytes() { + return Err(CryptoError::Algorithm( + String::from_utf8_lossy(&algorithm[..index]).into(), + )); + } + + Ok(output_and_data.split_at(key_size_bytes)) +} diff --git a/oxidation/libparsec/crates/crypto/src/lib.rs b/oxidation/libparsec/crates/crypto/src/lib.rs index 98f88fa0fb5..6a3baa6c5d1 100644 --- a/oxidation/libparsec/crates/crypto/src/lib.rs +++ b/oxidation/libparsec/crates/crypto/src/lib.rs @@ -1,34 +1,19 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS -#[cfg(all(not(feature = "use-sodiumoxide"), not(feature = "use-rustcrypto")))] -compile_error!("feature `use-sodiumoxide` or `use-rustcrypto` is mandatory"); -#[cfg(all(feature = "use-sodiumoxide", feature = "use-rustcrypto"))] -compile_error!("features `use-sodiumoxide` and `use-rustcrypto` are mutually exclusive"); - -#[cfg(any( - all(feature = "use-rustcrypto", not(feature = "use-sodiumoxide")), - all(feature = "use-sodiumoxide", not(feature = "use-rustcrypto")), -))] mod common; -#[cfg(all(feature = "use-rustcrypto", not(feature = "use-sodiumoxide")))] + +// Default to RustCrypto as it is much more convenient for dev ;-) +#[cfg(not(feature = "use-sodiumoxide"))] mod rustcrypto; -#[cfg(all(feature = "use-sodiumoxide", not(feature = "use-rustcrypto")))] +#[cfg(feature = "use-sodiumoxide")] mod sodiumoxide; -#[cfg(any( - all(feature = "use-rustcrypto", not(feature = "use-sodiumoxide")), - all(feature = "use-sodiumoxide", not(feature = "use-rustcrypto")), -))] pub mod prelude { pub use crate::common::*; - #[cfg(all(feature = "use-rustcrypto", not(feature = "use-sodiumoxide")))] + #[cfg(not(feature = "use-sodiumoxide"))] pub use crate::rustcrypto::*; - #[cfg(all(feature = "use-sodiumoxide", not(feature = "use-rustcrypto")))] + #[cfg(feature = "use-sodiumoxide")] pub use crate::sodiumoxide::*; } -#[cfg(any( - all(feature = "use-rustcrypto", not(feature = "use-sodiumoxide")), - all(feature = "use-sodiumoxide", not(feature = "use-rustcrypto")), -))] pub use prelude::*; diff --git a/oxidation/libparsec/crates/crypto/src/rustcrypto/mod.rs b/oxidation/libparsec/crates/crypto/src/rustcrypto/mod.rs index 8a499335017..d7df67e1658 100644 --- a/oxidation/libparsec/crates/crypto/src/rustcrypto/mod.rs +++ b/oxidation/libparsec/crates/crypto/src/rustcrypto/mod.rs @@ -3,11 +3,13 @@ mod hash; mod private; mod secret; +mod sequester; mod sign; mod utils; pub use hash::*; pub use private::*; pub use secret::*; +pub use sequester::*; pub use sign::*; pub use utils::*; diff --git a/oxidation/libparsec/crates/crypto/src/rustcrypto/private.rs b/oxidation/libparsec/crates/crypto/src/rustcrypto/private.rs index bdb734cf018..28357da6621 100644 --- a/oxidation/libparsec/crates/crypto/src/rustcrypto/private.rs +++ b/oxidation/libparsec/crates/crypto/src/rustcrypto/private.rs @@ -16,7 +16,7 @@ mod sealed_box { //re-export keys pub use crypto_box::{PublicKey, SecretKey}; - const BOX_NONCELENGTH: usize = 24; + const BOX_NONCE_LENGTH: usize = 24; const BOX_OVERHEAD: usize = 16; //32 = PublicKey length @@ -26,15 +26,15 @@ mod sealed_box { /// /// nonce = Blake2b(ephemeral_pk||target_pk) /// nonce_length = 24 - fn get_nonce(ephemeral_pk: &PublicKey, target_pk: &PublicKey) -> [u8; BOX_NONCELENGTH] { - let mut hasher = Blake2bVar::new(BOX_NONCELENGTH).unwrap(); + fn get_nonce(ephemeral_pk: &PublicKey, target_pk: &PublicKey) -> [u8; BOX_NONCE_LENGTH] { + let mut hasher = Blake2bVar::new(BOX_NONCE_LENGTH).unwrap(); hasher.update(ephemeral_pk.as_bytes()); hasher.update(target_pk.as_bytes()); let out = hasher.finalize_boxed(); - let mut array = [0u8; BOX_NONCELENGTH]; + let mut array = [0u8; BOX_NONCE_LENGTH]; array.copy_from_slice(&out); array diff --git a/oxidation/libparsec/crates/crypto/src/rustcrypto/secret.rs b/oxidation/libparsec/crates/crypto/src/rustcrypto/secret.rs index 71be916a780..a4b4d0c97b3 100644 --- a/oxidation/libparsec/crates/crypto/src/rustcrypto/secret.rs +++ b/oxidation/libparsec/crates/crypto/src/rustcrypto/secret.rs @@ -2,14 +2,12 @@ use argon2::{Algorithm, Argon2, Params, Version}; use blake2::Blake2bMac; -use digest::{consts::U5, Mac}; +use crypto_box::aead::Aead; +use digest::{consts::U5, KeyInit, Mac}; use rand_08::{rngs::OsRng, RngCore}; use serde::Deserialize; use serde_bytes::Bytes; -use xsalsa20poly1305::{ - aead::{Aead, NewAead}, - generate_nonce, Key, XSalsa20Poly1305, KEY_SIZE, NONCE_SIZE, -}; +use xsalsa20poly1305::{Key, XSalsa20Poly1305, KEY_SIZE, NONCE_SIZE}; use crate::CryptoError; @@ -41,7 +39,7 @@ lazy_static::lazy_static! { ); } -#[derive(Clone, PartialEq, Eq, Deserialize)] +#[derive(Clone, PartialEq, Eq, Deserialize, Hash)] #[serde(try_from = "&Bytes")] pub struct SecretKey(Key); @@ -58,7 +56,7 @@ impl SecretKey { // TODO: zero copy with preallocated buffer // let mut ciphered = Vec::with_capacity(NONCE_SIZE + TAG_SIZE + data.len()); let cipher = XSalsa20Poly1305::new(&self.0); - let nonce = generate_nonce(&mut rand_08::thread_rng()); + let nonce = XSalsa20Poly1305::generate_nonce(&mut rand_08::thread_rng()); // TODO: handle this error ? let mut ciphered = cipher.encrypt(&nonce, data).expect("encryption failure !"); let mut res = vec![]; @@ -78,13 +76,10 @@ impl SecretKey { pub fn hmac(&self, data: &[u8], digest_size: usize) -> Vec { // TODO only work for 5 bytes -> need to improve if digest_size != 5 { - panic!("Not implemeted for this digest size"); + panic!("Not implemented for this digest size"); } - // TODO investigate why new() is not working - // let mut hasher = Blake2bMac40::new(&self.0); - // &self.0 always provide the correct key size - let mut hasher = - Blake2bMac40::new_from_slice(self.0.as_ref()).unwrap_or_else(|_| unreachable!()); + let mut hasher = ::new_from_slice(self.0.as_ref()) + .unwrap_or_else(|_| unreachable!()); hasher.update(data); let res = hasher.finalize(); res.into_bytes().to_vec() @@ -103,9 +98,22 @@ impl SecretKey { pub fn from_password(password: &str, salt: &[u8]) -> Self { let mut key = [0; KEY_SIZE]; - ARGON2 - .hash_password_into(password.as_bytes(), salt, &mut key) - .expect("Invalid salt"); + // During test we want to skip the `argon2` algorithm for hashing the password + // Because it takes some time. + // For that we replace argon with a very basic algorithm that copy the `password + salt` to the first key bytes. + if cfg!(feature = "test-unsecure-but-fast-secretkey-from-password") { + let password_end = KEY_SIZE.min(password.len()); + + key[..password_end].copy_from_slice(&password.as_bytes()[..password_end]); + + let salt_end = (KEY_SIZE - password_end).min(salt.len()); + + key[password_end..password_end + salt_end].copy_from_slice(&salt[..salt_end]); + } else { + ARGON2 + .hash_password_into(password.as_bytes(), salt, &mut key) + .expect("Invalid salt"); + } Self::from(key) } diff --git a/oxidation/libparsec/crates/crypto/src/rustcrypto/sequester.rs b/oxidation/libparsec/crates/crypto/src/rustcrypto/sequester.rs new file mode 100644 index 00000000000..9e7db3b17ee --- /dev/null +++ b/oxidation/libparsec/crates/crypto/src/rustcrypto/sequester.rs @@ -0,0 +1,328 @@ +// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS + +use ed25519_dalek::Verifier; +use rsa::{ + pkcs8::{ + der::zeroize::Zeroizing, DecodePrivateKey, DecodePublicKey, EncodePrivateKey, + EncodePublicKey, + }, + pss::{Signature, SigningKey, VerifyingKey}, + signature::RandomizedSigner, + PaddingScheme, PublicKey, PublicKeyParts, RsaPrivateKey, RsaPublicKey, +}; +use serde::{Deserialize, Serialize}; +use serde_bytes::Bytes; +use sha1::Sha1; +use sha2::Sha256; + +use crate::{ + deserialize_with_armor, serialize_with_armor, CryptoError, CryptoResult, SecretKey, + SequesterKeySize, +}; + +/* + * PrivateKey + */ + +#[derive(Clone, PartialEq, Eq)] +pub struct SequesterPrivateKeyDer(RsaPrivateKey); + +crate::impl_key_debug!(SequesterPrivateKeyDer); + +impl TryFrom<&[u8]> for SequesterPrivateKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + RsaPrivateKey::from_pkcs8_der(bytes) + .map(Self) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string())) + } +} + +impl SequesterPrivateKeyDer { + const ALGORITHM: &str = "RSAES-OAEP-XSALSA20-POLY1305"; + + pub fn generate_pair(size_in_bits: SequesterKeySize) -> (Self, SequesterPublicKeyDer) { + let priv_key = RsaPrivateKey::new(&mut rand_08::thread_rng(), size_in_bits as usize) + .expect("Cannot generate the RSA key"); + let pub_key = RsaPublicKey::from(&priv_key); + + (Self(priv_key), SequesterPublicKeyDer(pub_key)) + } + + pub fn size_in_bytes(&self) -> usize { + self.0.n().bits() / 8 + } + + pub fn dump(&self) -> Zeroizing> { + self.0.to_pkcs8_der().expect("Unreachable").to_bytes() + } + + pub fn dump_pem(&self) -> Zeroizing { + self.0 + .to_pkcs8_pem(rsa::pkcs8::LineEnding::default()) + .expect("Unreachable") + } + + pub fn load_pem(s: &str) -> CryptoResult { + RsaPrivateKey::from_pkcs8_pem(s) + .map(Self) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string())) + } + + pub fn decrypt(&self, data: &[u8]) -> CryptoResult> { + let (cipherkey, ciphertext) = + deserialize_with_armor(data, self.size_in_bytes(), Self::ALGORITHM)?; + let padding = PaddingScheme::new_oaep::(); + + let clearkey = SecretKey::try_from( + &self + .0 + .decrypt(padding, cipherkey) + .map_err(|_| CryptoError::Decryption)?[..], + )?; + + clearkey.decrypt(ciphertext) + } +} + +/* + * PublicKey + */ + +#[derive(Clone, PartialEq, Eq, Deserialize)] +#[serde(try_from = "&Bytes")] +pub struct SequesterPublicKeyDer(RsaPublicKey); + +crate::impl_key_debug!(SequesterPublicKeyDer); + +impl TryFrom<&[u8]> for SequesterPublicKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + RsaPublicKey::from_public_key_der(bytes) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } +} + +impl TryFrom<&Bytes> for SequesterPublicKeyDer { + type Error = CryptoError; + + fn try_from(data: &Bytes) -> Result { + Self::try_from(data.as_ref()) + } +} + +impl Serialize for SequesterPublicKeyDer { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(&self.dump()) + } +} + +impl SequesterPublicKeyDer { + const ALGORITHM: &str = "RSAES-OAEP-XSALSA20-POLY1305"; + + pub fn size_in_bytes(&self) -> usize { + self.0.n().bits() / 8 + } + + pub fn dump(&self) -> Vec { + self.0.to_public_key_der().expect("Unreachable").into_vec() + } + + pub fn dump_pem(&self) -> String { + self.0 + .to_public_key_pem(rsa::pkcs8::LineEnding::default()) + .expect("Unreachable") + } + + pub fn load_pem(s: &str) -> CryptoResult { + RsaPublicKey::from_public_key_pem(s) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } + + // Encryption format: + // : + pub fn encrypt(&self, data: &[u8]) -> Vec { + let mut rng = rand_08::thread_rng(); + // No choice but to use SHA1 here: this is the default in PKCS#1 OAEP standard + let padding = PaddingScheme::new_oaep::(); + let secret_key = SecretKey::generate(); + let secret_key_encrypted = self + .0 + .encrypt(&mut rng, padding, secret_key.as_ref()) + .expect("Unreachable"); + + // RSAES-OAEP uses 42 bytes for padding, hence even with an insecure + // 1024 bits RSA key there is still 86 bytes available for payload + // which is plenty to store the 32 bytes XSalsa20 key + serialize_with_armor( + &secret_key_encrypted, + &secret_key.encrypt(data), + self.size_in_bytes(), + Self::ALGORITHM, + ) + } +} + +/* + * SigningKey + */ + +#[derive(Clone)] +pub struct SequesterSigningKeyDer(SigningKey); + +crate::impl_key_debug!(SequesterSigningKeyDer); + +impl PartialEq for SequesterSigningKeyDer { + fn eq(&self, other: &Self) -> bool { + self.0.as_ref() == other.0.as_ref() + } +} + +impl Eq for SequesterSigningKeyDer {} + +impl TryFrom<&[u8]> for SequesterSigningKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + RsaPrivateKey::from_pkcs8_der(bytes) + .map(SigningKey::from) + .map(Self) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string())) + } +} + +impl SequesterSigningKeyDer { + const ALGORITHM: &str = "RSASSA-PSS-SHA256"; + + pub fn generate_pair(size_in_bits: SequesterKeySize) -> (Self, SequesterVerifyKeyDer) { + let (priv_key, pub_key) = SequesterPrivateKeyDer::generate_pair(size_in_bits); + let signing_key = SigningKey::from(priv_key.0); + let verify_key = VerifyingKey::from(pub_key.0); + + (Self(signing_key), SequesterVerifyKeyDer(verify_key)) + } + + pub fn size_in_bytes(&self) -> usize { + self.0.as_ref().n().bits() / 8 + } + + pub fn dump(&self) -> Zeroizing> { + self.0.to_pkcs8_der().expect("Unreachable").to_bytes() + } + + pub fn dump_pem(&self) -> Zeroizing { + self.0 + .to_pkcs8_pem(rsa::pkcs8::LineEnding::default()) + .expect("Unreachable") + } + + pub fn load_pem(s: &str) -> CryptoResult { + RsaPrivateKey::from_pkcs8_pem(s) + .map(|x| Self(SigningKey::from(x))) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string())) + } + + // Signature format: + // : + pub fn sign(&self, data: &[u8]) -> Vec { + let mut rng = rand_08::thread_rng(); + let signature = self.0.sign_with_rng(&mut rng, data); + + serialize_with_armor( + signature.as_ref(), + data, + self.size_in_bytes(), + Self::ALGORITHM, + ) + } +} + +/* + * VerifyKey + */ + +#[derive(Clone, Deserialize)] +#[serde(try_from = "&Bytes")] +pub struct SequesterVerifyKeyDer(VerifyingKey); + +crate::impl_key_debug!(SequesterVerifyKeyDer); + +impl PartialEq for SequesterVerifyKeyDer { + fn eq(&self, other: &Self) -> bool { + self.0.as_ref() == other.0.as_ref() + } +} + +impl Eq for SequesterVerifyKeyDer {} + +impl TryFrom<&[u8]> for SequesterVerifyKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + RsaPublicKey::from_public_key_der(bytes) + .map(VerifyingKey::from) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } +} + +impl TryFrom<&Bytes> for SequesterVerifyKeyDer { + type Error = CryptoError; + + fn try_from(data: &Bytes) -> Result { + Self::try_from(data.as_ref()) + } +} + +impl Serialize for SequesterVerifyKeyDer { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(&self.dump()) + } +} + +impl SequesterVerifyKeyDer { + const ALGORITHM: &str = "RSASSA-PSS-SHA256"; + + pub fn size_in_bytes(&self) -> usize { + self.0.as_ref().n().bits() / 8 + } + + pub fn dump(&self) -> Vec { + self.0.to_public_key_der().expect("Unreachable").into_vec() + } + + pub fn dump_pem(&self) -> String { + self.0 + .to_public_key_pem(rsa::pkcs8::LineEnding::default()) + .expect("Unreachable") + } + + pub fn load_pem(s: &str) -> CryptoResult { + RsaPublicKey::from_public_key_pem(s) + .map(|x| Self(VerifyingKey::from(x))) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } + + pub fn verify(&self, data: &[u8]) -> CryptoResult> { + let (signature, data) = + deserialize_with_armor(data, self.size_in_bytes(), Self::ALGORITHM)?; + + // TODO: It Seems to be a mistake from RustCrypto/RSA + // Why should we allocate there ? + self.0 + .verify(data, &Signature::from(signature.to_vec())) + .map_err(|_| CryptoError::SignatureVerification)?; + + Ok(data.to_vec()) + } +} diff --git a/oxidation/libparsec/crates/crypto/src/rustcrypto/sign.rs b/oxidation/libparsec/crates/crypto/src/rustcrypto/sign.rs index a15d53923be..8b723ea1f3f 100644 --- a/oxidation/libparsec/crates/crypto/src/rustcrypto/sign.rs +++ b/oxidation/libparsec/crates/crypto/src/rustcrypto/sign.rs @@ -80,7 +80,7 @@ impl TryFrom<&[u8]> for SigningKey { impl From<[u8; Self::SIZE]> for SigningKey { fn from(key: [u8; Self::SIZE]) -> Self { - // TODO: zerocopy + // TODO: zero copy Self::try_from(key.as_ref()).unwrap() } } @@ -125,26 +125,25 @@ impl VerifyKey { pub fn verify(&self, signed: &[u8]) -> Result, CryptoError> { // Signature::try_from expects a [u8;64] and I have no idea how to get // one except by slicing, so we make sure the array is large enough before slicing. - if signed.len() < Signature::BYTE_SIZE { + if signed.len() < SigningKey::SIGNATURE_SIZE { return Err(CryptoError::Signature); } self.verify_with_signature( - &signed[..Signature::BYTE_SIZE], - &signed[Signature::BYTE_SIZE..], + signed[..SigningKey::SIGNATURE_SIZE] + .try_into() + .expect("Unreachable, because it's the correct size"), + &signed[SigningKey::SIGNATURE_SIZE..], ) } /// Verify a signature using the given [VerifyKey], `signature` and `message` pub fn verify_with_signature( &self, - raw_signature: &[u8], + raw_signature: [u8; SigningKey::SIGNATURE_SIZE], message: &[u8], ) -> Result, CryptoError> { - if raw_signature.len() != Signature::BYTE_SIZE { - return Err(CryptoError::Signature); - } - let signature = Signature::try_from(raw_signature) - .expect("Precondition already checked for the signature size"); + let signature = + Signature::from_bytes(&raw_signature).map_err(|_| CryptoError::Signature)?; self.0 .verify(message, &signature) .map_err(|_| CryptoError::SignatureVerification)?; @@ -170,7 +169,7 @@ impl TryFrom<&[u8]> for VerifyKey { impl From<[u8; Self::SIZE]> for VerifyKey { fn from(key: [u8; Self::SIZE]) -> Self { - // TODO: zerocopy + // TODO: zero copy Self::try_from(key.as_ref()).unwrap() } } diff --git a/oxidation/libparsec/crates/crypto/src/sodiumoxide/mod.rs b/oxidation/libparsec/crates/crypto/src/sodiumoxide/mod.rs index 8a499335017..d7df67e1658 100644 --- a/oxidation/libparsec/crates/crypto/src/sodiumoxide/mod.rs +++ b/oxidation/libparsec/crates/crypto/src/sodiumoxide/mod.rs @@ -3,11 +3,13 @@ mod hash; mod private; mod secret; +mod sequester; mod sign; mod utils; pub use hash::*; pub use private::*; pub use secret::*; +pub use sequester::*; pub use sign::*; pub use utils::*; diff --git a/oxidation/libparsec/crates/crypto/src/sodiumoxide/secret.rs b/oxidation/libparsec/crates/crypto/src/sodiumoxide/secret.rs index 99928dadddd..d458ada67a6 100644 --- a/oxidation/libparsec/crates/crypto/src/sodiumoxide/secret.rs +++ b/oxidation/libparsec/crates/crypto/src/sodiumoxide/secret.rs @@ -22,6 +22,14 @@ use crate::CryptoError; #[serde(try_from = "&Bytes")] pub struct SecretKey(Key); +// see https://github.com/rust-lang/rust-clippy/issues/2627 +#[allow(clippy::derive_hash_xor_eq)] +impl std::hash::Hash for SecretKey { + fn hash(&self, state: &mut H) { + self.0 .0.hash(state) + } +} + impl SecretKey { pub const ALGORITHM: &'static str = "xsalsa20poly1305"; pub const SIZE: usize = KEYBYTES; @@ -47,13 +55,23 @@ impl SecretKey { Ok(plaintext) } + /// # Safety + /// + /// This function requires access to libsodium methods that are not + /// exposed directly, so it uses the unsafe C API + /// ... pub fn hmac(&self, data: &[u8], digest_size: usize) -> Vec { - // Sodiumoxide doesn't expose those methods, so we have to access - // the libsodium C API directly + let mut state = libsodium_sys::crypto_generichash_blake2b_state { + opaque: [0u8; 384usize], + }; + let mut out = Vec::with_capacity(digest_size); + + // SAFETY: Sodiumoxide doesn't expose those methods, so we have to access + // the libsodium C API directly. + // this remains safe because we provide bounds defined in Rust land when passing vectors. + // The only data structure provided by remote code is dropped + // at the end of the function. unsafe { - let mut state = libsodium_sys::crypto_generichash_blake2b_state { - opaque: [0u8; 384usize], - }; libsodium_sys::crypto_generichash_blake2b_init( &mut state, self.as_ref().as_ptr(), @@ -65,7 +83,6 @@ impl SecretKey { data.as_ptr(), data.len() as u64, ); - let mut out = Vec::with_capacity(digest_size); libsodium_sys::crypto_generichash_blake2b_final( &mut state, out.as_mut_ptr(), @@ -82,16 +99,30 @@ impl SecretKey { pub fn from_password(password: &str, salt: &[u8]) -> Self { let mut key = [0; KEYBYTES]; - let salt = Salt::from_slice(&salt).expect("Invalid salt"); - - derive_key( - &mut key, - password.as_bytes(), - &salt, - OPSLIMIT_INTERACTIVE, - MEMLIMIT_INTERACTIVE, - ) - .expect("Can't fail"); + + // During test we want to skip the `argon2` algorithm for hashing the password + // Because it takes some time. + // For that we replace argon with a very basic algorithm that copy the `password + salt` to the first key bytes. + if cfg!(feature = "test-unsecure-but-fast-secretkey-from-password") { + let password_end = KEYBYTES.min(password.len()); + + key[..password_end].copy_from_slice(&password.as_bytes()[..password_end]); + + let salt_end = (KEYBYTES - password_end).min(salt.len()); + + key[password_end..password_end + salt_end].copy_from_slice(&salt[..salt_end]); + } else { + let salt = Salt::from_slice(salt).expect("Invalid salt"); + + derive_key( + &mut key, + password.as_bytes(), + &salt, + OPSLIMIT_INTERACTIVE, + MEMLIMIT_INTERACTIVE, + ) + .expect("Can't fail"); + } Self::from(key) } diff --git a/oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs b/oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs new file mode 100644 index 00000000000..60713cb1c54 --- /dev/null +++ b/oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs @@ -0,0 +1,401 @@ +// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS + +use zeroize::Zeroizing; + +use openssl::hash::MessageDigest; +use openssl::pkey::{PKey, Private, Public}; +use openssl::rsa::{Padding, Rsa}; +use openssl::sign::{RsaPssSaltlen, Signer, Verifier}; + +use serde::{Deserialize, Serialize}; +use serde_bytes::Bytes; + +use crate::{ + deserialize_with_armor, serialize_with_armor, CryptoError, CryptoResult, SecretKey, + SequesterKeySize, +}; + +/* + * PrivateKey + */ + +#[derive(Clone)] +pub struct SequesterPrivateKeyDer(Rsa); + +crate::impl_key_debug!(SequesterPrivateKeyDer); + +impl PartialEq for SequesterPrivateKeyDer { + fn eq(&self, other: &Self) -> bool { + self.0.n() == other.0.n() + && self.0.e() == other.0.e() + && self.0.d() == other.0.d() + && self.0.p() == other.0.p() + && self.0.q() == other.0.q() + && self.0.dmp1() == other.0.dmp1() + && self.0.dmq1() == other.0.dmq1() + && self.0.iqmp() == other.0.iqmp() + } +} + +impl Eq for SequesterPrivateKeyDer {} + +impl TryFrom<&[u8]> for SequesterPrivateKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + PKey::private_key_from_der(bytes) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string()))? + .rsa() + .map(Self) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string())) + } +} + +impl SequesterPrivateKeyDer { + const ALGORITHM: &str = "RSAES-OAEP-XSALSA20-POLY1305"; + + pub fn generate_pair(size_in_bits: SequesterKeySize) -> (Self, SequesterPublicKeyDer) { + let priv_key = Rsa::generate(size_in_bits as u32).expect("Cannot generate the RSA key"); + let pub_key = Rsa::from_public_components( + priv_key.n().to_owned().expect("Unreachable"), + priv_key.e().to_owned().expect("Unreachable"), + ) + .expect("Unreachable"); + + (Self(priv_key), SequesterPublicKeyDer(pub_key)) + } + + pub fn size_in_bytes(&self) -> usize { + self.0.size() as usize + } + + pub fn dump(&self) -> Zeroizing> { + Zeroizing::new(self.0.private_key_to_der().expect("Unreachable")) + } + + pub fn dump_pem(&self) -> Zeroizing { + let pkey_pem = PKey::from_rsa(self.0.to_owned()) + .expect("Unreachable") + .private_key_to_pem_pkcs8() + .expect("Unreachable"); + + Zeroizing::new(String::from_utf8(pkey_pem).expect("Unreachable")) + } + + pub fn load_pem(s: &str) -> CryptoResult { + PKey::private_key_from_pem(s.as_bytes()) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string()))? + .rsa() + .map(Self) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string())) + } + + pub fn decrypt(&self, data: &[u8]) -> CryptoResult> { + let (cipherkey, ciphertext) = + deserialize_with_armor(data, self.size_in_bytes(), Self::ALGORITHM)?; + + let mut decrypted_key_der = vec![0; cipherkey.len()]; + let decrypted_key_bytecount = self + .0 + .private_decrypt(cipherkey, &mut decrypted_key_der, Padding::PKCS1_OAEP) + .map_err(|_| CryptoError::Decryption)?; + + let clearkey = SecretKey::try_from(&decrypted_key_der[..decrypted_key_bytecount])?; + + clearkey.decrypt(ciphertext) + } +} + +/* + * PublicKey + */ + +#[derive(Clone, Deserialize)] +#[serde(try_from = "&Bytes")] +pub struct SequesterPublicKeyDer(Rsa); + +crate::impl_key_debug!(SequesterPublicKeyDer); + +impl PartialEq for SequesterPublicKeyDer { + fn eq(&self, other: &Self) -> bool { + // This is the only way I could find to compare two public keys. + // There is also public_eq, but it is defined on the PKey type, and to get + // a PKey from a Rsa we have to give up ownership, which + // we can't do because we take a reference to both the keys we want to compare. + // We could also clone the keys, but that would mean having an allocation in the + // comparison method. + self.0.n() == other.0.n() && self.0.e() == other.0.e() + } +} + +impl Eq for SequesterPublicKeyDer {} + +impl TryFrom<&[u8]> for SequesterPublicKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + Rsa::public_key_from_der(bytes) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } +} + +impl TryFrom<&Bytes> for SequesterPublicKeyDer { + type Error = CryptoError; + + fn try_from(data: &Bytes) -> Result { + Self::try_from(data.as_ref()) + } +} + +impl Serialize for SequesterPublicKeyDer { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(&self.dump()) + } +} + +impl SequesterPublicKeyDer { + const ALGORITHM: &str = "RSAES-OAEP-XSALSA20-POLY1305"; + + pub fn size_in_bytes(&self) -> usize { + self.0.size() as usize + } + + pub fn dump(&self) -> Vec { + self.0.public_key_to_der().expect("Unreachable") + } + + pub fn dump_pem(&self) -> String { + let pkey_pem = self.0.public_key_to_pem().expect("Unreachable"); + + String::from_utf8(pkey_pem).expect("Unreachable") + } + + pub fn load_pem(s: &str) -> CryptoResult { + Rsa::public_key_from_pem(s.as_bytes()) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } + + // Encryption format: + // : + pub fn encrypt(&self, data: &[u8]) -> Vec { + let secret_key = SecretKey::generate(); + + let mut encrypted_secret_key = vec![0; self.0.size() as usize]; + + let encrypted_key_bytes = self + .0 + .public_encrypt( + secret_key.as_ref(), + &mut encrypted_secret_key, + Padding::PKCS1_OAEP, + ) + .expect("Unable to decrypt a secret key"); + + // RSAES-OAEP uses 42 bytes for padding, hence even with an insecure + // 1024 bits RSA key there is still 86 bytes available for payload + // which is plenty to store the 32 bytes XSalsa20 key + serialize_with_armor( + &encrypted_secret_key[0..encrypted_key_bytes], + &secret_key.encrypt(data), + self.size_in_bytes(), + Self::ALGORITHM, + ) + } +} + +/* + * SigningKey + */ + +#[derive(Clone)] +pub struct SequesterSigningKeyDer(PKey); + +crate::impl_key_debug!(SequesterSigningKeyDer); + +impl PartialEq for SequesterSigningKeyDer { + fn eq(&self, other: &Self) -> bool { + self.0.public_eq(other.0.as_ref()) + } +} + +impl Eq for SequesterSigningKeyDer {} + +impl TryFrom<&[u8]> for SequesterSigningKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + let key = PKey::private_key_from_der(bytes) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string()))?; + + // Verify it's RSA key + key.0 + .rsa() + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string()))?; + + Ok(key) + } +} + +impl SequesterSigningKeyDer { + const ALGORITHM: &str = "RSASSA-PSS-SHA256"; + + pub fn generate_pair(size_in_bits: SequesterKeySize) -> (Self, SequesterVerifyKeyDer) { + let (priv_key, pub_key) = SequesterPrivateKeyDer::generate_pair(size_in_bits); + let signing_key = PKey::from_rsa(priv_key.0).expect("Unreachable"); + let verify_key = PKey::from_rsa(pub_key.0).expect("Unreachable"); + + (Self(signing_key), SequesterVerifyKeyDer(verify_key)) + } + + pub fn size_in_bytes(&self) -> usize { + self.0.bits() as usize / 8 + } + + pub fn dump(&self) -> Zeroizing> { + Zeroizing::new(self.0.private_key_to_der().expect("Unreachable")) + } + + pub fn dump_pem(&self) -> Zeroizing { + let pkey_pem = self.0.private_key_to_pem_pkcs8().expect("Unreachable"); + + Zeroizing::new(String::from_utf8(pkey_pem).expect("Unreachable")) + } + + pub fn load_pem(s: &str) -> CryptoResult { + let key = PKey::private_key_from_pem(s.as_bytes()) + .map(Self) + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string()))?; + + // Verify it's RSA key + key.0 + .rsa() + .map_err(|err| CryptoError::SequesterPrivateKeyDer(err.to_string()))?; + + Ok(key) + } + + // Signature format: + // : + pub fn sign(&self, data: &[u8]) -> Vec { + let mut signer = + Signer::new(MessageDigest::sha256(), &self.0).expect("Unable to build a Signer"); + + signer + .set_rsa_padding(Padding::PKCS1_PSS) + .expect("OpenSSL error"); + signer + .set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH) + .expect("OpenSSL error"); + + signer.update(data).expect("Unreachable"); + let signed_data = signer.sign_to_vec().expect("Unable to sign a message"); + + serialize_with_armor(&signed_data, data, self.size_in_bytes(), Self::ALGORITHM) + } +} + +/* + * VerifyKey + */ + +#[derive(Clone, Deserialize)] +#[serde(try_from = "&Bytes")] +pub struct SequesterVerifyKeyDer(PKey); + +crate::impl_key_debug!(SequesterVerifyKeyDer); + +impl PartialEq for SequesterVerifyKeyDer { + fn eq(&self, other: &Self) -> bool { + self.0.public_eq(other.0.as_ref()) + } +} + +impl Eq for SequesterVerifyKeyDer {} + +impl TryFrom<&[u8]> for SequesterVerifyKeyDer { + type Error = CryptoError; + + fn try_from(bytes: &[u8]) -> Result { + // Verify it's RSA key + Rsa::public_key_from_der(bytes) + .map(|x| PKey::from_rsa(x).expect("Unreachable")) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } +} + +impl TryFrom<&Bytes> for SequesterVerifyKeyDer { + type Error = CryptoError; + + fn try_from(data: &Bytes) -> Result { + Self::try_from(data.as_ref()) + } +} + +impl Serialize for SequesterVerifyKeyDer { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(&self.dump()) + } +} + +impl SequesterVerifyKeyDer { + const ALGORITHM: &str = "RSASSA-PSS-SHA256"; + + pub fn size_in_bytes(&self) -> usize { + self.0.bits() as usize / 8 + } + + pub fn dump(&self) -> Vec { + self.0.public_key_to_der().expect("Unreachable") + } + + pub fn dump_pem(&self) -> String { + let pkey_pem = self.0.public_key_to_pem().expect("Unreachable"); + + String::from_utf8(pkey_pem).expect("Unable to get UTF-8 String from public key PEM") + } + + pub fn load_pem(s: &str) -> CryptoResult { + // Verify it's RSA key + Rsa::public_key_from_pem(s.as_bytes()) + .map(|x| PKey::from_rsa(x).expect("Unreachable")) + .map(Self) + .map_err(|err| CryptoError::SequesterPublicKeyDer(err.to_string())) + } + + pub fn verify(&self, data: &[u8]) -> CryptoResult> { + let (signature, contents) = + deserialize_with_armor(data, self.size_in_bytes(), Self::ALGORITHM)?; + + let mut verifier = Verifier::new(MessageDigest::sha256(), &self.0) + .map_err(|_| CryptoError::SignatureVerification)?; + + verifier + .set_rsa_padding(Padding::PKCS1_PSS) + .expect("OpenSSL error"); + verifier + .set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH) + .expect("OpenSSL error"); + + verifier + .update(contents) + .map_err(|_| CryptoError::SignatureVerification)?; + + match verifier.verify(signature) { + Ok(signature_is_valid) => match signature_is_valid { + true => Ok(contents.to_vec()), + false => Err(CryptoError::Signature), + }, + Err(_) => Err(CryptoError::SignatureVerification), + } + } +} diff --git a/oxidation/libparsec/crates/crypto/src/sodiumoxide/sign.rs b/oxidation/libparsec/crates/crypto/src/sodiumoxide/sign.rs index 814b0f4b7cd..4418e833490 100644 --- a/oxidation/libparsec/crates/crypto/src/sodiumoxide/sign.rs +++ b/oxidation/libparsec/crates/crypto/src/sodiumoxide/sign.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use serde_bytes::Bytes; -use sodiumoxide::crypto::sign::{ed25519, gen_keypair, sign, verify}; +use sodiumoxide::crypto::sign::{ed25519, gen_keypair, sign, verify, verify_detached, Signature}; use crate::CryptoError; @@ -55,7 +55,7 @@ impl TryFrom<&[u8]> for SigningKey { impl From<[u8; Self::SIZE]> for SigningKey { fn from(key: [u8; Self::SIZE]) -> Self { - // TODO: zerocopy + // TODO: zero copy let (_, sk) = ed25519::keypair_from_seed(&ed25519::Seed(key)); Self(sk) } @@ -109,6 +109,20 @@ impl VerifyKey { pub fn verify(&self, signed: &[u8]) -> Result, CryptoError> { verify(signed, &self.0).or(Err(CryptoError::SignatureVerification)) } + + /// Verify a signature using the given [VerifyKey], `signature` and `message` + pub fn verify_with_signature( + &self, + raw_signature: [u8; SigningKey::SIGNATURE_SIZE], + message: &[u8], + ) -> Result, CryptoError> { + let signature = + Signature::from_bytes(&raw_signature).map_err(|_| CryptoError::Signature)?; + if !verify_detached(&signature, message, &self.0) { + return Err(CryptoError::SignatureVerification); + } + Ok(message.into()) + } } impl AsRef<[u8]> for VerifyKey { diff --git a/oxidation/libparsec/crates/crypto/src/traits.rs b/oxidation/libparsec/crates/crypto/src/traits.rs deleted file mode 100644 index b058cb2b2e8..00000000000 --- a/oxidation/libparsec/crates/crypto/src/traits.rs +++ /dev/null @@ -1,162 +0,0 @@ -// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS - -// Traits to make sure both implementation share the same api - -use serde_bytes::ByteBuf; - -pub(crate) trait BaseHashDigest<'de, 'f>: - serde::Serialize - + serde::Deserialize<'de> - + AsRef<[u8]> - + TryFrom<&'f [u8]> - + From<[u8; HashDigest::SIZE]> - + TryFrom - + Into -{ - const ALGORITHM: &'static str; - const SIZE: usize; - - fn from_data(data: &[u8]) -> Self; - fn hexdigest(&self) -> String; -} - -pub(crate) trait BasePrivateKey { - const SIZE: usize; - type PublicKey; - type SecretKey; - - fn as_bytes(&self) -> &[u8]; - fn public_key(&self) -> Self::PublicKey; - fn generate() -> Self; - // TODO: implement API ! - fn decrypt_from_self(&self, ciphered: &[u8]) -> Vec; - fn generate_shared_secret_key(&self, peer_public_key: &Self::PublicKey) -> Self::SecretKey; -} - -pub(crate) trait BasePublicKey { - const SIZE: usize; - - fn as_bytes(&self) -> &[u8]; - // TODO: implement API ! - fn encrypt_from_self(&self, data: &[u8]) -> Vec; -} - -pub(crate) trait BaseSecretKey { - const SIZE: usize; - - fn generate() -> Self; - fn encrypt(&self, data: &[u8]) -> Vec; - fn decrypt(&self, ciphered: &[u8]) -> Vec; - fn hmac(&self, data: &[u8], digest_size: usize) -> Vec; -} - -pub(crate) trait BaseSigningKey { - const SIZE: usize; - type VerifyKey; - - fn as_bytes(&self) -> &[u8]; - fn verify_key(&self) -> Self::VerifyKey; - fn generate() -> Self; - fn verify(self, data: &[u8]) -> Result, &'static str>; -} - -pub(crate) trait BaseVerifyKey { - const SIZE: usize; - - fn as_bytes(&self) -> &[u8]; - fn unsecure_unwrap(&self, signed: &[u8]) -> Vec; - fn verify(self, signed: &[u8]) -> Result, &'static str>; -} - -// trait BytesSerialized : std::marker::Sized { -// const SIZE: usize; - -// fn as_bytes(&self) -> &[u8]; -// fn from_bytes(data: &[u8]) -> Result; -// } - -// use serde::ser::{Serialize, Serializer}; - -// impl Serialize for T { -// fn serialize(&self, serializer: S) -> Result -// where -// S: Serializer, -// { -// serializer.serialize_bytes(self.as_bytes()) -// } -// } - -// use serde::de::{self, Deserialize, Deserializer, Visitor}; - -// impl<'de, T: BytesSerialized> Deserialize<'de> for T { -// fn deserialize(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// U: BytesSerializedVisitor, -// { -// // TODO: use deserialize_byte_buf instead ? -// deserializer.deserialize_bytes(U) -// } -// } - -// struct BytesSerializedVisitor (std::marker::PhantomData); - -// impl<'de, T: BytesSerialized> Visitor<'de> for BytesSerializedVisitor { -// type Value = T; - -// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { -// formatter.write_str(concat!("a ", stringify!(T::size()), " long bytes array")) -// } - -// fn visit_bytes(self, value: &[u8]) -> Result -// where -// E: de::Error, -// { -// T::from_bytes(value).map_err(|e| E::custom(e)) -// } -// } - -// macro_rules! impl_serde { -// ($name:ident) => { -// use serde::de::{self, Deserialize, Deserializer, Visitor}; -// use serde::ser::{Serialize, Serializer}; - -// impl Serialize for T { -// fn serialize(&self, serializer: S) -> Result -// where -// S: Serializer, -// { -// serializer.serialize_bytes(&self.0.0) -// } -// } - -// paste::paste! { -// impl Deserialize<'de> for T { -// fn deserialize(deserializer: D) -> Result -// where -// D: Deserializer<'de>, -// { -// deserializer.deserialize_bytes([]) -// } -// } - -// struct []; - -// impl Visitor<'de> for [] { -// type Value = T; - -// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { -// formatter.write_str(concat!("a ", stringify!(T::size()), " long bytes array")) -// } - -// fn visit_bytes(self, value: &[u8]) -> Result -// where -// E: de::Error, -// { -// T::try_from(value).map_err(|e| E::custom(e)) -// } -// } -// } - -// }; -// } diff --git a/oxidation/libparsec/crates/crypto/tests/anti_leak.rs b/oxidation/libparsec/crates/crypto/tests/anti_leak.rs new file mode 100644 index 00000000000..fa3ee76b329 --- /dev/null +++ b/oxidation/libparsec/crates/crypto/tests/anti_leak.rs @@ -0,0 +1,10 @@ +// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS + +use libparsec_crypto::{PrivateKey, SecretKey, SigningKey}; + +#[test] +fn test_anti_leak_debug() { + assert_eq!(format!("{:?}", SecretKey::generate()), "SecretKey(****)"); + assert_eq!(format!("{:?}", PrivateKey::generate()), "PrivateKey(****)"); + assert_eq!(format!("{:?}", SigningKey::generate()), "SigningKey(****)"); +} diff --git a/oxidation/libparsec/crates/crypto/tests/common/mod.rs b/oxidation/libparsec/crates/crypto/tests/common/mod.rs index 52842df1f34..6f38c98e931 100644 --- a/oxidation/libparsec/crates/crypto/tests/common/mod.rs +++ b/oxidation/libparsec/crates/crypto/tests/common/mod.rs @@ -18,7 +18,7 @@ macro_rules! test_msgpack_serialization { let data = &$data; let serialized = &$serialized; - // bytes should be serialized in msgpck using the bin format familly + // bytes should be serialized in msgpack using the bin format family // (see. https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family) let sk: $cls = rmp_serde::from_slice(serialized).unwrap(); @@ -28,7 +28,7 @@ macro_rules! test_msgpack_serialization { let re_serialized = rmp_serde::to_vec(&sk).unwrap(); assert_eq!(re_serialized, serialized); - // str format familly shouldn't be used for bytes, but Python's msgpack + // str format family shouldn't be used for bytes, but Python's msgpack // deserializes it fine, so we should also handle this just in case // (see. https://github.com/msgpack/msgpack/blob/master/spec.md#str-format-family) diff --git a/oxidation/libparsec/crates/crypto/tests/secret.rs b/oxidation/libparsec/crates/crypto/tests/secret.rs index c7e11d08009..41eec4324f6 100644 --- a/oxidation/libparsec/crates/crypto/tests/secret.rs +++ b/oxidation/libparsec/crates/crypto/tests/secret.rs @@ -73,7 +73,7 @@ fn secret_key_should_verify_length_when_deserialize() { rmp_serde::from_slice::(&data) .unwrap_err() .to_string(), - "Invalid data size" + "Invalid key size: expected 32 bytes, got 5 bytes" ); } @@ -91,17 +91,24 @@ fn test_recovery_passphrase() { } #[rstest] -#[case::empty("")] -#[case::only_invalid_characters("-@//白")] -#[case::too_short("D5VR-53YO-QYJW-VJ4A-4DQR-4LVC-W425-3CXN-F3AQ-J6X2-YVPZ-XBAO")] -#[case::too_long("D5VR-53YO-QYJW-VJ4A-4DQR-4LVC-W425-3CXN-F3AQ-J6X2-YVPZ-XBAO-NU4Q-NU4Q")] -fn test_invalid_passphrase(#[case] bad_passphrase: &str) { +#[case::empty("", 0)] +#[case::only_invalid_characters("-@//白", 0)] +#[case::too_short("D5VR-53YO-QYJW-VJ4A-4DQR-4LVC-W425-3CXN-F3AQ-J6X2-YVPZ-XBAO", 30)] +#[case::too_long( + "D5VR-53YO-QYJW-VJ4A-4DQR-4LVC-W425-3CXN-F3AQ-J6X2-YVPZ-XBAO-NU4Q-NU4Q", + 35 +)] +fn test_invalid_passphrase(#[case] bad_passphrase: &str, #[case] key_length: usize) { assert_eq!( SecretKey::from_recovery_passphrase(bad_passphrase).unwrap_err(), - CryptoError::DataSize + CryptoError::KeySize { + expected: SecretKey::SIZE, + got: key_length, + } ); } +#[cfg_attr(feature = "test-unsecure-but-fast-secretkey-from-password", ignore)] #[test] fn test_from_password() { let password = "P@ssw0rd."; diff --git a/oxidation/libparsec/crates/crypto/tests/sequester.rs b/oxidation/libparsec/crates/crypto/tests/sequester.rs new file mode 100644 index 00000000000..e7c3df69333 --- /dev/null +++ b/oxidation/libparsec/crates/crypto/tests/sequester.rs @@ -0,0 +1,307 @@ +// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS + +use hex_literal::hex; +use rstest::rstest; + +use libparsec_crypto::{ + SequesterKeySize, SequesterPrivateKeyDer, SequesterPublicKeyDer, SequesterSigningKeyDer, + SequesterVerifyKeyDer, +}; + +const PRIVATE_KEY_PEM_1024: &str = r#"-----BEGIN PRIVATE KEY----- +MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALLcAKPDtcaJsGnz +9AxJTSpb4xOxA0+/Hf4O7uDzbPvPYkQAJWzGYNUIR4JzijBF11tYTBlDvATHEj1o +rAzvJTtO6Neb0J2hkWLcwINmImm3tiyzhYL4owIZBHsIfBG2AYSwST4MHIsdEPnX +5qLrWv9m9+4YMDGV87zHKrVyB+v9AgMBAAECgYBBfQRO8g3QkAGkCcrF5OD4LYTL +ZPjNbjDRIS6d9wNkf95+/360gT5bQhjMzvk+C5R6wa27Ym2pYipvia/VXIrIuwoP +GDKyUg/B2SrDIBgLlleosVmOZwERnY939ShaxXA/TAqT4eXr5uwXm8z/YkledzTV +iZ2G0ty962SJI9KbEQJBAOsrXVrVvCjK4WVFBcFqKw2Cz6I3+PEPcOXnozMwKKre +XeT54rPoqfkkoFOPcRngiPPBHxJYMZxZ2gPWN6MkxmMCQQDCs8SRRd/XkwrH9Wga ++kO3sY9pcWNGnHq5psqOEhaOqxozzE5ztT9FCcSAUqMf8onnNXpU+I4o7lQwQACZ +dmIfAkAmtgiz/yLuBBd+OBJueC+GFdZf+Z6877HB5pNyxaasGdaS7p9mxhHUtTa/ +ComvnMpudYfL2UCxYAkHQKf/7vnJAkEAk1Zqd+zCmWXikLK7Fz8vo4CwoAB4OeUM +UhVPzvcNLuV4LJ58976+pEXh96GRZAmsJdUoP8jf+0VvXBvy2C7nzQJAGLjFefMr +vXTMHxDHhuHg4ZJSbJ5BNMZb/HZ5m4KQCt9Gelx/sxZOt3VlCrquCFALxmkeYMhX +W1pav08hVpEcTg== +-----END PRIVATE KEY----- +"#; + +const PRIVATE_KEY_DER_1024: [u8; 634] = hex!( + "30820276020100300d06092a864886f70d0101010500048202603082025c02010002818100" + "b2dc00a3c3b5c689b069f3f40c494d2a5be313b1034fbf1dfe0eeee0f36cfbcf624400256c" + "c660d5084782738a3045d75b584c1943bc04c7123d68ac0cef253b4ee8d79bd09da19162dc" + "c083662269b7b62cb38582f8a30219047b087c11b60184b0493e0c1c8b1d10f9d7e6a2eb5a" + "ff66f7ee18303195f3bcc72ab57207ebfd0203010001028180417d044ef20dd09001a409ca" + "c5e4e0f82d84cb64f8cd6e30d1212e9df703647fde7eff7eb4813e5b4218cccef93e0b947a" + "c1adbb626da9622a6f89afd55c8ac8bb0a0f1832b2520fc1d92ac320180b9657a8b1598e67" + "01119d8f77f5285ac5703f4c0a93e1e5ebe6ec179bccff62495e7734d5899d86d2dcbdeb64" + "8923d29b11024100eb2b5d5ad5bc28cae1654505c16a2b0d82cfa237f8f10f70e5e7a33330" + "28aade5de4f9e2b3e8a9f924a0538f7119e088f3c11f1258319c59da03d637a324c6630241" + "00c2b3c49145dfd7930ac7f5681afa43b7b18f697163469c7ab9a6ca8e12168eab1a33cc4e" + "73b53f4509c48052a31ff289e7357a54f88e28ee543040009976621f024026b608b3ff22ee" + "04177e38126e782f8615d65ff99ebcefb1c1e69372c5a6ac19d692ee9f66c611d4b536bf0a" + "89af9cca6e7587cbd940b160090740a7ffeef9c902410093566a77ecc29965e290b2bb173f" + "2fa380b0a0007839e50c52154fcef70d2ee5782c9e7cf7bebea445e1f7a1916409ac25d528" + "3fc8dffb456f5c1bf2d82ee7cd024018b8c579f32bbd74cc1f10c786e1e0e192526c9e4134" + "c65bfc76799b82900adf467a5c7fb3164eb775650abaae08500bc6691e60c8575b5a5abf4f" + "2156911c4e"); + +const PUBLIC_KEY_PEM_1024: &str = r#"-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCy3ACjw7XGibBp8/QMSU0qW+MT +sQNPvx3+Du7g82z7z2JEACVsxmDVCEeCc4owRddbWEwZQ7wExxI9aKwM7yU7TujX +m9CdoZFi3MCDZiJpt7Yss4WC+KMCGQR7CHwRtgGEsEk+DByLHRD51+ai61r/Zvfu +GDAxlfO8xyq1cgfr/QIDAQAB +-----END PUBLIC KEY----- +"#; + +const PUBLIC_KEY_DER_1024: [u8; 162] = hex!( + "30819f300d06092a864886f70d010101050003818d0030818902818100b2dc00a3c3b5c689" + "b069f3f40c494d2a5be313b1034fbf1dfe0eeee0f36cfbcf624400256cc660d5084782738a" + "3045d75b584c1943bc04c7123d68ac0cef253b4ee8d79bd09da19162dcc083662269b7b62c" + "b38582f8a30219047b087c11b60184b0493e0c1c8b1d10f9d7e6a2eb5aff66f7ee18303195" + "f3bcc72ab57207ebfd0203010001" +); + +const PRIVATE_KEY_PEM_2048: &str = r#"-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnDVsZGa7iu45E +2d++JupEgmdlo8EGFjfXJzVgXduWT42rmxGEKCARzHt5RK0EjSsfmLg4uQqvVlEc +lUtN4HR466nU6tqnf+PLjYJNVQQVh1rRM27N97gfRxuOVwkb6tAMIFUytWRyQd9C +FEzMpLJebFeZc/dWQ76gOXhBY71L5/7O+m8xugwIpex8qvao+aVgHaQqGNHJN+CB +Zys2/GzMO/6ypbbhy6nr/OSknvc00I7XiQDynq77fciZNuqPIa7Za+N14rIrUsyK +bCEc8RH0sn2wcdieVXHPdvF3ZasFbD5tNJOHo//SplOLEwhdYAGs7NEcjEOmXksk +8t0gCJcxAgMBAAECggEAfJIqF6qeTnd8XP13qo3MbnAr+JBHdWmGFIwpcoYrJIiI +ZaqKQlnFqGAqx0CeIOHAgZxZ6/qY7C1a6QyvjhBN6ooaKCtGCFgHH5iTzWUTWZaI +863999u9Up2s/9UJducAY7qMrfa0Q7u5Z8ZJiuVaGa2DGWxvycVU1phkg6aD16Cg +nZ3+9oWbaBfELPEFdktYwa5fwflOMN6+Fw7isIVlOC4tvGpiR1scXKEwjr2P5a0P +D0s6ca4D9xlCrlJ6CpdyKbLwz5ya+gBwjW3OJYI8+NzIw5SwmnnZoP3MqI96ME70 +RGBfyqPs4DZjEaqWSSiaDMu10nndEvdakFwgCBzCAQKBgQDeIAouUgnG53RCjukN +mLTHLDpuQk7yycmVcjqWgq2Dkg2FxGbl7f9p6vLDicbMieXYbSTbt5rYTnU6c5j0 +o2uAiGsUK8E7JsD8qid7XV7M6r0mTCAqP16SEcf9oSureYFXIWq6pkgnQLS6LVw6 +rWwG+uaaCw3qjQvlPk17pvKGYQKBgQDAhzf5EJG3LICmgSKsz6qS/G82N8gxqCwC +Gf8egXGweQSSYrUaemtsAHHbVNIxEqPoedpj+ErofvYo2exNbQVyp33rC1kGNqqT +YTzsV83jp0vv9cn6LwgeK+5mfuNTs13H/YfKpdfJRgoo78Ot7c//FpcM4iwtcFEm +CDhD7DAi0QKBgCSBmYrBWvAAzD/AIxdj+Jofb779UOJgPaw9KNnhwki0cVqBy/OQ +KQEsZxeyBiVJqKfoUD14MI/KXUPtCb9zOFDYmtim1Ew3c1JTWMfSsaj2D35C1qp6 +3b0eBQNvQLEe+B3s1RC2EXe6D7nliJnwNKf1Bn9cv73DzqevlKZ06rkhAoGBAJAF +VuCw/WAaIU7s8QR3AHGd9o+HYPGMjQcxbT/jsylBDiN3RWS+SRdsqb9aDzZ4bDae +2LjJ5zdOqlPa2UL+GAIxuycVwQ293RIMvmdKM5Fl949UvTey8Q6o7Fit+N4HIlNV +m7wDHY3KIBWJbkbwzBRVUL9pfYSsLXgW1AgzabrRAoGAUW82mYl9HAwQOBPb40OK +j2qKisC4VA8vR/Uco9yda5XT7iqG3htvUa+Ugj5r4XFRJvOyQG2WUiOWwGYlzfz2 +1Ogu8O8RHcaJafAIMTJJtjsO8pIf6Y7aWHA3Ze3to+01fTkGB2I8tDKc3fn+iKlX +z0mxbH0U7CoeRzfgJ6UmIio= +-----END PRIVATE KEY----- +"#; + +const PRIVATE_KEY_DER_2048: [u8; 1217] = hex!( + "308204bd020100300d06092a864886f70d0101010500048204a7308204a302010002820101" + "00a70d5b1919aee2bb8e44d9dfbe26ea44826765a3c1061637d72735605ddb964f8dab9b11" + "84282011cc7b7944ad048d2b1f98b838b90aaf56511c954b4de07478eba9d4eadaa77fe3cb" + "8d824d550415875ad1336ecdf7b81f471b8e57091bead00c205532b5647241df42144ccca4" + "b25e6c579973f75643bea039784163bd4be7fecefa6f31ba0c08a5ec7caaf6a8f9a5601da4" + "2a18d1c937e081672b36fc6ccc3bfeb2a5b6e1cba9ebfce4a49ef734d08ed78900f29eaefb" + "7dc89936ea8f21aed96be375e2b22b52cc8a6c211cf111f4b27db071d89e5571cf76f17765" + "ab056c3e6d349387a3ffd2a6538b13085d6001acecd11c8c43a65e4b24f2dd200897310203" + "010001028201007c922a17aa9e4e777c5cfd77aa8dcc6e702bf89047756986148c2972862b" + "24888865aa8a4259c5a8602ac7409e20e1c0819c59ebfa98ec2d5ae90caf8e104dea8a1a28" + "2b460858071f9893cd6513599688f3adfdf7dbbd529dacffd50976e70063ba8cadf6b443bb" + "b967c6498ae55a19ad83196c6fc9c554d6986483a683d7a0a09d9dfef6859b6817c42cf105" + "764b58c1ae5fc1f94e30debe170ee2b08565382e2dbc6a62475b1c5ca1308ebd8fe5ad0f0f" + "4b3a71ae03f71942ae527a0a977229b2f0cf9c9afa00708d6dce25823cf8dcc8c394b09a79" + "d9a0fdcca88f7a304ef444605fcaa3ece0366311aa9649289a0ccbb5d279dd12f75a905c20" + "081cc20102818100de200a2e5209c6e774428ee90d98b4c72c3a6e424ef2c9c995723a9682" + "ad83920d85c466e5edff69eaf2c389c6cc89e5d86d24dbb79ad84e753a7398f4a36b80886b" + "142bc13b26c0fcaa277b5d5ecceabd264c202a3f5e9211c7fda12bab798157216abaa64827" + "40b4ba2d5c3aad6c06fae69a0b0dea8d0be53e4d7ba6f2866102818100c08737f91091b72c" + "80a68122accfaa92fc6f3637c831a82c0219ff1e8171b079049262b51a7a6b6c0071db54d2" + "3112a3e879da63f84ae87ef628d9ec4d6d0572a77deb0b590636aa93613cec57cde3a74bef" + "f5c9fa2f081e2bee667ee353b35dc7fd87caa5d7c9460a28efc3adedcfff16970ce22c2d70" + "5126083843ec3022d10281802481998ac15af000cc3fc0231763f89a1f6fbefd50e2603dac" + "3d28d9e1c248b4715a81cbf39029012c6717b2062549a8a7e8503d78308fca5d43ed09bf73" + "3850d89ad8a6d44c3773525358c7d2b1a8f60f7e42d6aa7addbd1e05036f40b11ef81decd5" + "10b61177ba0fb9e58899f034a7f5067f5cbfbdc3cea7af94a674eab92102818100900556e0" + "b0fd601a214eecf1047700719df68f8760f18c8d07316d3fe3b329410e23774564be49176c" + "a9bf5a0f36786c369ed8b8c9e7374eaa53dad942fe180231bb2715c10dbddd120cbe674a33" + "9165f78f54bd37b2f10ea8ec58adf8de072253559bbc031d8dca2015896e46f0cc145550bf" + "697d84ac2d7816d4083369bad1028180516f3699897d1c0c103813dbe3438a8f6a8a8ac0b8" + "540f2f47f51ca3dc9d6b95d3ee2a86de1b6f51af94823e6be1715126f3b2406d96522396c0" + "6625cdfcf6d4e82ef0ef111dc68969f008313249b63b0ef2921fe98eda58703765ededa3ed" + "357d390607623cb4329cddf9fe88a957cf49b16c7d14ec2a1e4737e027a526222a"); + +const PUBLIC_KEY_PEM_2048: &str = r#"-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApw1bGRmu4ruORNnfvibq +RIJnZaPBBhY31yc1YF3blk+Nq5sRhCggEcx7eUStBI0rH5i4OLkKr1ZRHJVLTeB0 +eOup1Orap3/jy42CTVUEFYda0TNuzfe4H0cbjlcJG+rQDCBVMrVkckHfQhRMzKSy +XmxXmXP3VkO+oDl4QWO9S+f+zvpvMboMCKXsfKr2qPmlYB2kKhjRyTfggWcrNvxs +zDv+sqW24cup6/zkpJ73NNCO14kA8p6u+33ImTbqjyGu2WvjdeKyK1LMimwhHPER +9LJ9sHHYnlVxz3bxd2WrBWw+bTSTh6P/0qZTixMIXWABrOzRHIxDpl5LJPLdIAiX +MQIDAQAB +-----END PUBLIC KEY----- +"#; + +const PUBLIC_KEY_DER_2048: [u8; 294] = hex!( + "30820122300d06092a864886f70d01010105000382010f003082010a0282010100a70d5b19" + "19aee2bb8e44d9dfbe26ea44826765a3c1061637d72735605ddb964f8dab9b1184282011cc" + "7b7944ad048d2b1f98b838b90aaf56511c954b4de07478eba9d4eadaa77fe3cb8d824d5504" + "15875ad1336ecdf7b81f471b8e57091bead00c205532b5647241df42144ccca4b25e6c5799" + "73f75643bea039784163bd4be7fecefa6f31ba0c08a5ec7caaf6a8f9a5601da42a18d1c937" + "e081672b36fc6ccc3bfeb2a5b6e1cba9ebfce4a49ef734d08ed78900f29eaefb7dc89936ea" + "8f21aed96be375e2b22b52cc8a6c211cf111f4b27db071d89e5571cf76f17765ab056c3e6d" + "349387a3ffd2a6538b13085d6001acecd11c8c43a65e4b24f2dd200897310203010001"); + +#[test] +fn only_rsa_is_supported() { + let unsupported_key = hex!( + "308201b73082012b06072a8648ce3804013082011e02818100f8df308877a3bcf66db78734" + "882f854f934cb5e3bc3cd284b62751d2b6490fd0793dfd43e68393c5fe02f897236fe40949" + "892aa7718939be9aec22e813c7ab55a245b0b3d2cef69123c862c2449af305ce30784929a3" + "ba4ac3e5f14cf50508558ee9600c74b5ff1020fe3728ff92c303292dcf13c54aac726ba462" + "bfee65d3b302150086d038ac40999b7fb3cb7d6253f9ff71a932ca57028180517dea95129a" + "3e46e7aee51e00fd4eb0bc90eec8c340fe27dc8e72287ebddbdb7c748b67d7416a54b12a1b" + "d09248d1b6e9291a7d266c02fcf76c887a710065e0fdc767e74dfa13edb5d1a8bca331dd32" + "dccc199cc2055b446b35a30bd6edde35d08cfbbfd2fbbda2fecce75d4ab5eab2c772cbf914" + "1325e0e6e05348b035b3ff03818500028181008fb6c7096b0f95aa2baa71e32ba1c1f54088" + "59f573a4786c55fe050e29180a60b6487885c18a294d1f4655032c1fc3c88eb113dae0cddb" + "cd5faa40a312dc339256e019aeffd2410c71ef00bf2c519444f3d43024adfc55be6e5db2b7" + "8e7d6c54c6cc882ffa606e76e53fc73b3443347507e91227944aeed42004a305de09918b"); + + assert!(SequesterPublicKeyDer::try_from(&unsupported_key[..]).is_err()); + assert!(SequesterVerifyKeyDer::try_from(&unsupported_key[..]).is_err()); +} + +#[rstest] +#[case(&PUBLIC_KEY_DER_1024[..])] +#[case(&PUBLIC_KEY_DER_2048[..])] +fn test_key_equality(#[case] pub_key: &[u8]) { + let pub_key = SequesterPublicKeyDer::try_from(pub_key).unwrap(); + + let pub_key2 = pub_key.clone(); + + assert_eq!(pub_key, pub_key2); +} + +#[rstest] +#[case(SequesterKeySize::_1024Bits)] +#[case(SequesterKeySize::_2048Bits)] +fn test_size(#[case] size_in_bits: SequesterKeySize) { + let (priv_key, pub_key) = SequesterPrivateKeyDer::generate_pair(size_in_bits); + let (signing_key, verify_key) = SequesterSigningKeyDer::generate_pair(size_in_bits); + assert_eq!(priv_key.size_in_bytes(), size_in_bits as usize / 8); + assert_eq!(pub_key.size_in_bytes(), size_in_bits as usize / 8); + assert_eq!(signing_key.size_in_bytes(), size_in_bits as usize / 8); + assert_eq!(verify_key.size_in_bytes(), size_in_bits as usize / 8); +} + +#[rstest] +#[case(SequesterKeySize::_1024Bits)] +#[case(SequesterKeySize::_2048Bits)] +fn test_encrypt_decrypt(#[case] size_in_bits: SequesterKeySize) { + let (priv_key, pub_key) = SequesterPrivateKeyDer::generate_pair(size_in_bits); + + let encrypted = pub_key.encrypt(b"foo"); + + assert_eq!(priv_key.decrypt(&encrypted).unwrap(), b"foo"); +} + +#[rstest] +#[case(SequesterKeySize::_1024Bits)] +#[case(SequesterKeySize::_2048Bits)] +fn test_sign_verify(#[case] size_in_bits: SequesterKeySize) { + let (signing_key, verify_key) = SequesterSigningKeyDer::generate_pair(size_in_bits); + + let signed = signing_key.sign(b"foo"); + + assert_eq!(verify_key.verify(&signed).unwrap(), b"foo"); +} + +#[rstest] +#[case(PRIVATE_KEY_PEM_1024, &PRIVATE_KEY_DER_1024[..], PUBLIC_KEY_PEM_1024, &PUBLIC_KEY_DER_1024[..])] +#[case(PRIVATE_KEY_PEM_2048, &PRIVATE_KEY_DER_2048[..], PUBLIC_KEY_PEM_2048, &PUBLIC_KEY_DER_2048[..])] +fn test_import_export( + #[case] private_key_pem: &str, + #[case] private_key_der: &[u8], + #[case] public_key_pem: &str, + #[case] public_key_der: &[u8], +) { + let priv_key_pem = SequesterPrivateKeyDer::load_pem(private_key_pem).unwrap(); + let priv_key_der = SequesterPrivateKeyDer::try_from(private_key_der).unwrap(); + + let pub_key_pem = SequesterPublicKeyDer::load_pem(public_key_pem).unwrap(); + let pub_key_der = SequesterPublicKeyDer::try_from(public_key_der).unwrap(); + + let signing_key_pem = SequesterSigningKeyDer::load_pem(private_key_pem).unwrap(); + let signing_key_der = SequesterSigningKeyDer::try_from(private_key_der).unwrap(); + + let verify_key_pem = SequesterVerifyKeyDer::load_pem(public_key_pem).unwrap(); + let verify_key_der = SequesterVerifyKeyDer::try_from(public_key_der).unwrap(); + + assert_eq!(priv_key_pem, priv_key_der); + assert_eq!(pub_key_pem, pub_key_der); + + // Also test roundtrip + assert_eq!( + SequesterPrivateKeyDer::load_pem(&priv_key_pem.dump_pem()).unwrap(), + priv_key_pem + ); + assert_eq!( + SequesterPrivateKeyDer::try_from(&priv_key_der.dump()[..]).unwrap(), + priv_key_der + ); + + assert_eq!( + SequesterPublicKeyDer::load_pem(&pub_key_pem.dump_pem()).unwrap(), + pub_key_pem + ); + assert_eq!( + SequesterPublicKeyDer::try_from(&pub_key_der.dump()[..]).unwrap(), + pub_key_der + ); + + assert_eq!( + SequesterSigningKeyDer::load_pem(&signing_key_pem.dump_pem()).unwrap(), + signing_key_pem + ); + assert_eq!( + SequesterSigningKeyDer::try_from(&signing_key_der.dump()[..]).unwrap(), + signing_key_der + ); + + assert_eq!( + SequesterVerifyKeyDer::load_pem(&verify_key_pem.dump_pem()).unwrap(), + verify_key_pem + ); + assert_eq!( + SequesterVerifyKeyDer::try_from(&verify_key_der.dump()[..]).unwrap(), + verify_key_der + ); +} + +#[test] +fn test_sign_compat() { + let verify_key = SequesterVerifyKeyDer::try_from(&PUBLIC_KEY_DER_1024[..]).unwrap(); + + let signed = hex!( + "5253415353412d5053532d5348413235363a0afc141b03789ac3f2c69bd1e577e279d4570b" + "f3fe387f389fe52c2b4ac08a9cacbd3c5c1b080cb39969cf3ff7a375619b4b5adc4aef2aec" + "2800f6ead1d78019f8e37d036880b71e6ba4e89562e14ab2d6b35d0db4db48d818f8d4395f" + "8d692be38fcdfa8d526a352bb811393dd987ed5a8257b7583d145099037178456baf3c4865" + "6c6c6f20776f726c64" + ); + + assert_eq!(verify_key.verify(&signed).unwrap(), b"Hello world"); +} + +#[test] +fn test_encrypt_compat() { + let priv_key = SequesterPrivateKeyDer::try_from(&PRIVATE_KEY_DER_1024[..]).unwrap(); + + let encrypted = hex!( + "52534145532d4f4145502d5853414c534132302d504f4c59313330353a278b9346743cc609" + "258a4a82023059411d78c29aed9cf9893dc36b1f1f0055e3db8fa3624b4e3ced4fa1d3683b" + "97cff2694ddbebeb9a59d1533e9b4dba005958f70a1b7b4b54fef420fb200146a73ac0f457" + "168e71decb50d98af9332da36b5143e3470f7858a1a43f0f7ffff6e98e2487579d96a3791d" + "69d48ba307e9984dad42781a567fa27e74e9ee88fd945736968855588eec48f43faa396464" + "d9a5e8cfd5326ea0193ff5732b51423146d683b74870ed" + ); + + assert_eq!(priv_key.decrypt(&encrypted).unwrap(), b"Hello world"); +} diff --git a/oxidation/libparsec/crates/crypto/tests/sign.rs b/oxidation/libparsec/crates/crypto/tests/sign.rs index c62f900e3c3..21c38741b4f 100644 --- a/oxidation/libparsec/crates/crypto/tests/sign.rs +++ b/oxidation/libparsec/crates/crypto/tests/sign.rs @@ -42,7 +42,7 @@ fn signature_verification_spec() { let vk = VerifyKey::from(hex!( "78958e49abad190be2d51bab73af07f87682cfcd65cceedd27e4b2a94bfd8537" )); - // Signedtext generated with base python implementation + // Signed text generated with base python implementation let signed_text = hex!("32d26711dc973e8df13bbafddc23fc26efe4aca1b86a4e0e7dad7c03df7ffc25d24b865478d164f8868ad0e087587e2c45e45d5598c7929b4605699bbab4b109616c6c20796f75722062617365206172652062656c6f6e6720746f207573"); let text = vk.verify(&signed_text).unwrap(); @@ -65,9 +65,15 @@ fn signature_only() { let vk = sk.verify_key(); let signed_message = Vec::from_iter(signed.iter().chain(data).copied()); - let res = vk.verify(&signed_message); + let res = vk.verify(&signed_message).unwrap(); - assert_eq!(res, Ok(data.to_vec())); + assert_eq!(res, data); + + // Also test verify_with_signature + + let res = vk.verify_with_signature(signed, data).unwrap(); + + assert_eq!(res, data); } test_msgpack_serialization!( diff --git a/parsec/_parsec_pyi/crypto.pyi b/parsec/_parsec_pyi/crypto.pyi index c15e7f28bbc..4172e2889c8 100644 --- a/parsec/_parsec_pyi/crypto.pyi +++ b/parsec/_parsec_pyi/crypto.pyi @@ -62,4 +62,45 @@ class PublicKey: def encrypt_for_self(self, data: bytes) -> bytes: ... def encode(self) -> bytes: ... +class SequesterPrivateKeyDer: + def __init__(self, data: bytes) -> None: ... + @classmethod + def generate_pair( + cls, size_in_bits: int + ) -> tuple[SequesterPrivateKeyDer, SequesterPublicKeyDer]: ... + def dump(self) -> bytes: ... + def dump_pem(self) -> str: ... + @classmethod + def load_pem(cls, s: str) -> SequesterPrivateKeyDer: ... + def decrypt(self, data: bytes) -> bytes: ... + +class SequesterPublicKeyDer: + def __init__(self, data: bytes) -> None: ... + def dump(self) -> bytes: ... + def dump_pem(self) -> str: ... + @classmethod + def load_pem(cls, s: str) -> SequesterPublicKeyDer: ... + def encrypt(self, data: bytes) -> bytes: ... + +class SequesterSigningKeyDer: + @classmethod + def generate_pair( + cls, size_in_bits: int + ) -> tuple[SequesterSigningKeyDer, SequesterVerifyKeyDer]: ... + def dump(self) -> bytes: ... + def dump_pem(self) -> str: ... + @classmethod + def load_pem(cls, s: str) -> SequesterSigningKeyDer: ... + def sign(self, data: bytes) -> bytes: ... + +class SequesterVerifyKeyDer: + def __init__(self, data: bytes) -> None: ... + def dump(self) -> bytes: ... + def dump_pem(self) -> str: ... + @classmethod + def load_pem(cls, s: str) -> SequesterVerifyKeyDer: ... + def verify(self, data: bytes) -> bytes: ... + def generate_nonce() -> bytes: ... + +class CryptoError(Exception): ... diff --git a/parsec/backend/asgi/rpc.py b/parsec/backend/asgi/rpc.py index 7e4bd4556eb..d427e95c72c 100644 --- a/parsec/backend/asgi/rpc.py +++ b/parsec/backend/asgi/rpc.py @@ -4,10 +4,9 @@ from base64 import b64decode from typing import NoReturn, Tuple -from nacl.exceptions import CryptoError from quart import Blueprint, Response, current_app, g, request -from parsec._parsec import ClientType, DateTime +from parsec._parsec import ClientType, CryptoError, DateTime from parsec.api.protocol import ( DeviceID, IncompatibleAPIVersionsError, diff --git a/parsec/crypto.py b/parsec/crypto.py index 0b7223aebcc..72e63f5895a 100644 --- a/parsec/crypto.py +++ b/parsec/crypto.py @@ -1,15 +1,17 @@ # Parsec Cloud (https://parsec.cloud) Copyright (c) AGPL-3.0 2016-present Scille SAS from __future__ import annotations -from nacl.exceptions import CryptoError -from nacl.pwhash import argon2i - -from parsec._parsec import HashDigest, PrivateKey, PublicKey, SecretKey, SigningKey, VerifyKey - -# Note to simplify things, we adopt `nacl.CryptoError` as our root error cls +from parsec._parsec import ( + CryptoError, + HashDigest, + PrivateKey, + PublicKey, + SecretKey, + SigningKey, + VerifyKey, +) __all__ = ( - # Exceptions "CryptoError", # Types "SecretKey", @@ -18,5 +20,4 @@ "PublicKey", "SigningKey", "VerifyKey", - "argon2i", ) diff --git a/parsec/sequester_crypto.py b/parsec/sequester_crypto.py index 0070383fe99..814cbeb9a9d 100644 --- a/parsec/sequester_crypto.py +++ b/parsec/sequester_crypto.py @@ -1,168 +1,18 @@ # Parsec Cloud (https://parsec.cloud) Copyright (c) AGPL-3.0 2016-present Scille SAS from __future__ import annotations -from enum import Enum -from typing import Union - -import oscrypto.asymmetric -import oscrypto.errors - -from parsec.crypto import CryptoError, SecretKey - - -class SequesterKeyAlgorithm(Enum): - RSA = "RSA" - - -def _enforce_rsa_output_has_key_size( - key: oscrypto.asymmetric.PrivateKey | oscrypto.asymmetric.PublicKey, output: bytes -) -> bytes: - # Using RSA, we should end up with a number as big as the key size and - # provided as big endian bytes. - # However it is possible the number can be represented with less bytes if - # enough of its most significant bits are equal to zero. - # In such case, certain implementations (at least oscrypt on macOS 12) trim - # the null bytes and hence return a bytes array smaller than the key size. - # - # For instance, considering a 16bits RSA key size (state-of-the-art security ^^) - # and a RSA output `42`, the output can be represented as b"\x42" or b"\x00\x42) - # - # Long story short, we want to make sure our RSA output are always of the - # same size than the key, this simplify splitting messages and protect us - # if an RSA implementation on another platform is picky about output size. - if len(output) == key.byte_size: - return output - else: - assert len(output) <= key.byte_size # Sanity check - # Add enough null bytes to have output of the same size than the key - return (b"\x00" * (key.byte_size - len(output))) + output - - -class _SequesterPublicKeyDer: - __slots__ = ("_key",) - - def __init__(self, der_key: Union[bytes, oscrypto.asymmetric.PublicKey]): - if isinstance(der_key, bytes): - try: - self._key = oscrypto.asymmetric.load_public_key(der_key) - except (oscrypto.errors.AsymmetricKeyError, OSError) as exc: - raise ValueError(str(exc)) from exc - else: - assert isinstance(der_key, oscrypto.asymmetric.PublicKey) - self._key = der_key - - if self._key.algorithm != "rsa": - raise ValueError("Unsupported key format") - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _SequesterPublicKeyDer): - return NotImplemented - return self._key == other._key - - @property - def algorithm(self) -> SequesterKeyAlgorithm: - return SequesterKeyAlgorithm.RSA - - def dump(self) -> bytes: - return oscrypto.asymmetric.dump_public_key(self._key, encoding="der") - - def __repr__(self) -> str: - return f"{type(self).__name__}({self._key})" - - @property - def secret(self) -> oscrypto.asymmetric.PublicKey: - return self._key - - -class SequesterVerifyKeyDer(_SequesterPublicKeyDer): - __slots__ = () - - # Signature format: - # : - SIGNING_ALGORITHM = b"RSASSA-PSS-SHA256" - - def verify(self, data: bytes) -> bytes: - """ - Raises: - CryptoError: if key or signature are invalid. - """ - try: - algo, signature_and_content = data.split(b":", 1) - if algo != self.SIGNING_ALGORITHM: - raise ValueError - except ValueError as exc: - raise CryptoError("Unsupported algorithm") from exc - - # In RSASSA-PSS, signature is as big as the key size - signature = signature_and_content[: self._key.byte_size] - content = signature_and_content[self._key.byte_size :] - - try: - oscrypto.asymmetric.rsa_pss_verify(self._key, signature, content, "sha256") - except (oscrypto.errors.SignatureError, OSError) as exc: - raise CryptoError(str(exc)) from exc - - return content - - -def sequester_authority_sign(signing_key: oscrypto.asymmetric.PrivateKey, data: bytes) -> bytes: - try: - signature = oscrypto.asymmetric.rsa_pss_sign(signing_key, data, "sha256") - except OSError as exc: - raise CryptoError(str(exc)) from exc - - # It is import `signature` has a constant size given this is how it is - # retrieved during verification - signature = _enforce_rsa_output_has_key_size(signing_key, signature) - - return SequesterVerifyKeyDer.SIGNING_ALGORITHM + b":" + signature + data - - -class SequesterEncryptionKeyDer(_SequesterPublicKeyDer): - __slots__ = () - - # Encryption format: - # : - ENCRYPTION_ALGORITHM = b"RSAES-OAEP-XSALSA20-POLY1305" - - def encrypt(self, data: bytes) -> bytes: - """ - Raises: - CryptoError: if key is invalid. - """ - secret_key = SecretKey.generate() - try: - # RSAES-OAEP uses 42 bytes for padding, hence even with an insecure - # 1024 bits RSA key there is still 86 bytes available for payload - # which is plenty to store the 32 bytes XSalsa20 key - secret_key_encrypted = oscrypto.asymmetric.rsa_oaep_encrypt( - self._key, secret_key.secret - ) - except OSError as exc: - raise CryptoError(str(exc)) from exc - - # It is import `secret_key_encrypted` has a constant size given this - # is how it is retrieved during decryption - secret_key_encrypted = _enforce_rsa_output_has_key_size(self._key, secret_key_encrypted) - - return self.ENCRYPTION_ALGORITHM + b":" + secret_key_encrypted + secret_key.encrypt(data) - - -def sequester_service_decrypt(decryption_key: oscrypto.asymmetric.PrivateKey, data: bytes) -> bytes: - try: - algo, cipherkey_and_ciphertext = data.split(b":", 1) - if algo != SequesterEncryptionKeyDer.ENCRYPTION_ALGORITHM: - raise ValueError - except ValueError as exc: - raise CryptoError("Unsupported algorithm") from exc - - cipherkey = cipherkey_and_ciphertext[: decryption_key.byte_size] - ciphertext = cipherkey_and_ciphertext[decryption_key.byte_size :] - - try: - clearkey = SecretKey(oscrypto.asymmetric.rsa_oaep_decrypt(decryption_key, cipherkey)) - except OSError as exc: - raise CryptoError(str(exc)) from exc - - cleartext = clearkey.decrypt(ciphertext) - return cleartext +from parsec._parsec import ( + CryptoError, + SequesterEncryptionKeyDer, + SequesterVerifyKeyDer, + sequester_authority_sign, + sequester_service_decrypt, +) + +__all__ = ( + "CryptoError", + "SequesterVerifyKeyDer", + "SequesterEncryptionKeyDer", + "sequester_authority_sign", + "sequester_service_decrypt", +) diff --git a/poetry.lock b/poetry.lock index 7da65d3b6e1..e75556a1c7d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Poetry and should not be changed by hand. + [[package]] name = "aiofiles" version = "22.1.0" @@ -5,6 +7,10 @@ description = "File support for asyncio." category = "main" optional = true python-versions = ">=3.7,<4.0" +files = [ + {file = "aiofiles-22.1.0-py3-none-any.whl", hash = "sha256:1142fa8e80dbae46bb6339573ad4c8c0841358f79c6eb50a493dceca14621bad"}, + {file = "aiofiles-22.1.0.tar.gz", hash = "sha256:9107f1ca0b2a5553987a94a3c9959fe5b491fdf731389aa5b7b1bd0733e32de6"}, +] [[package]] name = "altgraph" @@ -13,14 +19,10 @@ description = "Python graph (network) package" category = "dev" optional = false python-versions = "*" - -[[package]] -name = "asn1crypto" -version = "1.5.1" -description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" -category = "main" -optional = false -python-versions = "*" +files = [ + {file = "altgraph-0.17.3-py2.py3-none-any.whl", hash = "sha256:c8ac1ca6772207179ed8003ce7687757c04b0b71536f81e2ac5755c6226458fe"}, + {file = "altgraph-0.17.3.tar.gz", hash = "sha256:ad33358114df7c9416cdb8fa1eaa5852166c505118717021c6a8c7c7abbd03dd"}, +] [[package]] name = "async-exit-stack" @@ -29,6 +31,10 @@ description = "AsyncExitStack backport for Python 3.5+" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "async_exit_stack-1.0.1-py3-none-any.whl", hash = "sha256:9b43b17683b3438f428ef3bbec20689f5abbb052aa4b564c643397330adfaa99"}, + {file = "async_exit_stack-1.0.1.tar.gz", hash = "sha256:24de1ad6d0ff27be97c89d6709fa49bf20db179eaf1f4d2e6e9b4409b80e747d"}, +] [[package]] name = "async-generator" @@ -37,6 +43,10 @@ description = "Async generators and context managers for Python 3.5+" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, + {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, +] [[package]] name = "asyncpg" @@ -45,6 +55,34 @@ description = "An asyncio PostgreSQL driver" category = "main" optional = true python-versions = ">=3.6.0" +files = [ + {file = "asyncpg-0.26.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ed3880b3aec8bda90548218fe0914d251d641f798382eda39a17abfc4910af0"}, + {file = "asyncpg-0.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5bd99ee7a00e87df97b804f178f31086e88c8106aca9703b1d7be5078999e68"}, + {file = "asyncpg-0.26.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:868a71704262834065ca7113d80b1f679609e2df77d837747e3d92150dd5a39b"}, + {file = "asyncpg-0.26.0-cp310-cp310-win32.whl", hash = "sha256:838e4acd72da370ad07243898e886e93d3c0c9413f4444d600ba60a5cc206014"}, + {file = "asyncpg-0.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:a254d09a3a989cc1839ba2c34448b879cdd017b528a0cda142c92fbb6c13d957"}, + {file = "asyncpg-0.26.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3ecbe8ed3af4c739addbfbd78f7752866cce2c4e9cc3f953556e4960349ae360"}, + {file = "asyncpg-0.26.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ce7d8c0ab4639bbf872439eba86ef62dd030b245ad0e17c8c675d93d7a6b2d"}, + {file = "asyncpg-0.26.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7129bd809990fd119e8b2b9982e80be7712bb6041cd082be3e415e60e5e2e98f"}, + {file = "asyncpg-0.26.0-cp36-cp36m-win32.whl", hash = "sha256:03f44926fa7ff7ccd59e98f05c7e227e9de15332a7da5bbcef3654bf468ee597"}, + {file = "asyncpg-0.26.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b1f7b173af649b85126429e11a628d01a5b75973d2a55d64dba19ad8f0e9f904"}, + {file = "asyncpg-0.26.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efe056fd22fc6ed5c1ab353b6510808409566daac4e6f105e2043797f17b8dad"}, + {file = "asyncpg-0.26.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d96cf93e01df9fb03cef5f62346587805e6c0ca6f654c23b8d35315bdc69af59"}, + {file = "asyncpg-0.26.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:235205b60d4d014921f7b1cdca0e19669a9a8978f7606b3eb8237ca95f8e716e"}, + {file = "asyncpg-0.26.0-cp37-cp37m-win32.whl", hash = "sha256:0de408626cfc811ef04f372debfcdd5e4ab5aeb358f2ff14d1bdc246ed6272b5"}, + {file = "asyncpg-0.26.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f92d501bf213b16fabad4fbb0061398d2bceae30ddc228e7314c28dcc6641b79"}, + {file = "asyncpg-0.26.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9acb22a7b6bcca0d80982dce3d67f267d43e960544fb5dd934fd3abe20c48014"}, + {file = "asyncpg-0.26.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e550d8185f2c4725c1e8d3c555fe668b41bd092143012ddcc5343889e1c2a13d"}, + {file = "asyncpg-0.26.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:050e339694f8c5d9aebcf326ca26f6622ef23963a6a3a4f97aeefc743954afd5"}, + {file = "asyncpg-0.26.0-cp38-cp38-win32.whl", hash = "sha256:b0c3f39ebfac06848ba3f1e280cb1fada7cc1229538e3dad3146e8d1f9deb92a"}, + {file = "asyncpg-0.26.0-cp38-cp38-win_amd64.whl", hash = "sha256:49fc7220334cc31d14866a0b77a575d6a5945c0fa3bb67f17304e8b838e2a02b"}, + {file = "asyncpg-0.26.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d156e53b329e187e2dbfca8c28c999210045c45ef22a200b50de9b9e520c2694"}, + {file = "asyncpg-0.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b4051012ca75defa9a1dc6b78185ca58cdc3a247187eb76a6bcf55dfaa2fad4"}, + {file = "asyncpg-0.26.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d60f15a0ac18c54a6ca6507c28599c06e2e87a0901e7b548f15243d71905b18"}, + {file = "asyncpg-0.26.0-cp39-cp39-win32.whl", hash = "sha256:ede1a3a2c377fe12a3930f4b4dd5340e8b32929541d5db027a21816852723438"}, + {file = "asyncpg-0.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:8e1e79f0253cbd51fc43c4d0ce8804e46ee71f6c173fdc75606662ad18756b52"}, + {file = "asyncpg-0.26.0.tar.gz", hash = "sha256:77e684a24fee17ba3e487ca982d0259ed17bae1af68006f4cf284b23ba20ea2c"}, +] [package.extras] dev = ["Cython (>=0.29.24,<0.30.0)", "Sphinx (>=4.1.2,<4.2.0)", "flake8 (>=3.9.2,<3.10.0)", "pycodestyle (>=2.7.0,<2.8.0)", "pytest (>=6.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "uvloop (>=0.15.3)"] @@ -58,6 +96,10 @@ description = "Classes Without Boilerplate" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, +] [package.extras] dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] @@ -72,6 +114,10 @@ description = "Internationalization utilities" category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "Babel-2.10.3-py3-none-any.whl", hash = "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"}, + {file = "Babel-2.10.3.tar.gz", hash = "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51"}, +] [package.dependencies] pytz = ">=2015.7" @@ -83,6 +129,10 @@ description = "Python parser for bash" category = "dev" optional = false python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4" +files = [ + {file = "bashlex-0.16-py2.py3-none-any.whl", hash = "sha256:ff89fc743ccdef978792784d74d698a9236a862939bb4af471c0c3faf92c21bb"}, + {file = "bashlex-0.16.tar.gz", hash = "sha256:dc6f017e49ce2d0fe30ad9f5206da9cd13ded073d365688c9fda525354e8c373"}, +] [[package]] name = "black" @@ -91,6 +141,29 @@ description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, +] [package.dependencies] click = ">=8.0.0" @@ -113,6 +186,10 @@ description = "Fast, simple object-to-object and broadcast signaling" category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "blinker-1.5-py2.py3-none-any.whl", hash = "sha256:1eb563df6fdbc39eeddc177d953203f99f097e9bf0e2b8f9f3cf18b6ca425e36"}, + {file = "blinker-1.5.tar.gz", hash = "sha256:923e5e2f69c155f2cc42dafbbd70e16e3fde24d2d4aa2ab72fbe386238892462"}, +] [[package]] name = "boto3" @@ -121,6 +198,10 @@ description = "The AWS SDK for Python" category = "main" optional = true python-versions = ">= 3.7" +files = [ + {file = "boto3-1.25.1-py3-none-any.whl", hash = "sha256:5684030fb1fa742c9bec33bee1a0829ff4b4bb2cdef40d9465969fdb55b501bc"}, + {file = "boto3-1.25.1.tar.gz", hash = "sha256:9517b1d517b024a259a116a0206ae4a471e2ffab57db1b41a3ce6e3f8042001a"}, +] [package.dependencies] botocore = ">=1.28.1,<1.29.0" @@ -137,6 +218,10 @@ description = "Type annotations for boto3 1.26.21 generated with mypy-boto3-buil category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "boto3-stubs-1.26.21.tar.gz", hash = "sha256:98c706c79d9690ffd96cb2a92d6fe9ae7938c0376859234b3a09dec779fb75c9"}, + {file = "boto3_stubs-1.26.21-py3-none-any.whl", hash = "sha256:39d4cb0947b62bff4bdbe1c67158fd05799b8544bb4aa2ac9eaea88c857f7da8"}, +] [package.dependencies] botocore-stubs = "*" @@ -487,6 +572,10 @@ description = "Low-level, data-driven core of boto 3." category = "main" optional = true python-versions = ">= 3.7" +files = [ + {file = "botocore-1.28.1-py3-none-any.whl", hash = "sha256:e751045bee771d99d1baa06775df38511a5025cab6ceb2219a2a27cc2abd3ee5"}, + {file = "botocore-1.28.1.tar.gz", hash = "sha256:2ebaf48c9cd61ad5532ac639569837bce3e0470991c5f1bee9fe3ef7d0362c42"}, +] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" @@ -503,6 +592,10 @@ description = "Type annotations and code completion for botocore" category = "dev" optional = false python-versions = ">=3.7,<4.0" +files = [ + {file = "botocore_stubs-1.29.12-py3-none-any.whl", hash = "sha256:9e2e0e1357d95617b3471a2c2ab07a05bb564907f6b44300aed444a734d82a5a"}, + {file = "botocore_stubs-1.29.12.tar.gz", hash = "sha256:e050ae81d7f9db3880db5062bbc827c897c9f24486fe24f64f33d02ebad6ed84"}, +] [package.dependencies] types-awscrt = "*" @@ -514,6 +607,10 @@ description = "Bash style brace expander." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "bracex-2.3.post1-py3-none-any.whl", hash = "sha256:351b7f20d56fb9ea91f9b9e9e7664db466eb234188c175fd943f8f755c807e73"}, + {file = "bracex-2.3.post1.tar.gz", hash = "sha256:e7b23fc8b2cd06d3dec0692baabecb249dda94e06a617901ff03a6c56fd71693"}, +] [[package]] name = "certifi" @@ -522,6 +619,10 @@ description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, + {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, +] [[package]] name = "cffi" @@ -530,6 +631,72 @@ description = "Foreign Function Interface for Python calling C code." category = "main" optional = false python-versions = "*" +files = [ + {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, + {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, + {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, + {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, + {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, + {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, + {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, + {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, + {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, + {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, + {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, + {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, + {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, + {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, + {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, + {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, + {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, + {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, + {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, + {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, + {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, + {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, + {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, + {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, + {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, + {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, + {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, + {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, + {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, + {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, + {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, + {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, + {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, +] [package.dependencies] pycparser = "*" @@ -541,6 +708,10 @@ description = "The Real First Universal Charset Detector. Open, modern and activ category = "main" optional = true python-versions = ">=3.6.0" +files = [ + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, +] [package.extras] unicode-backport = ["unicodedata2"] @@ -552,6 +723,10 @@ description = "Build Python wheels on CI with minimal configuration." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "cibuildwheel-2.10.0-py3-none-any.whl", hash = "sha256:8946086aaac43b7885ebbf11166acdafb5275612f20428e99488fef594b0ed6e"}, + {file = "cibuildwheel-2.10.0.tar.gz", hash = "sha256:3375f1f0cfb24a5b20941fc46059a7bdc983c28d725f7e0a255746544a8a4e44"}, +] [package.dependencies] bashlex = "!=0.13" @@ -577,6 +752,10 @@ description = "Composable command line interface toolkit" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, + {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -588,6 +767,10 @@ description = "Cross-platform colored terminal text." category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] [[package]] name = "coverage" @@ -596,6 +779,58 @@ description = "Code coverage measurement for Python" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, + {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, + {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, + {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, + {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, + {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, + {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, + {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, + {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, + {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, + {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, + {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, + {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, + {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, + {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, + {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, + {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, + {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, + {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, + {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, + {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, + {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, + {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, + {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, + {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, + {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, + {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, + {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, +] [package.dependencies] tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} @@ -610,6 +845,34 @@ description = "cryptography is a package which provides cryptographic recipes an category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "cryptography-38.0.3-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:984fe150f350a3c91e84de405fe49e688aa6092b3525f407a18b9646f6612320"}, + {file = "cryptography-38.0.3-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722"}, + {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bbf203f1a814007ce24bd4d51362991d5cb90ba0c177a9c08825f2cc304d871f"}, + {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554bec92ee7d1e9d10ded2f7e92a5d70c1f74ba9524947c0ba0c850c7b011828"}, + {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959"}, + {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:728f2694fa743a996d7784a6194da430f197d5c58e2f4e278612b359f455e4a2"}, + {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c"}, + {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5419a127426084933076132d317911e3c6eb77568a1ce23c3ac1e12d111e61e0"}, + {file = "cryptography-38.0.3-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9b24bcff7853ed18a63cfb0c2b008936a9554af24af2fb146e16d8e1aed75748"}, + {file = "cryptography-38.0.3-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:25c1d1f19729fb09d42e06b4bf9895212292cb27bb50229f5aa64d039ab29146"}, + {file = "cryptography-38.0.3-cp36-abi3-win32.whl", hash = "sha256:7f836217000342d448e1c9a342e9163149e45d5b5eca76a30e84503a5a96cab0"}, + {file = "cryptography-38.0.3-cp36-abi3-win_amd64.whl", hash = "sha256:c46837ea467ed1efea562bbeb543994c2d1f6e800785bd5a2c98bc096f5cb220"}, + {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06fc3cc7b6f6cca87bd56ec80a580c88f1da5306f505876a71c8cfa7050257dd"}, + {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:65535bc550b70bd6271984d9863a37741352b4aad6fb1b3344a54e6950249b55"}, + {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5e89468fbd2fcd733b5899333bc54d0d06c80e04cd23d8c6f3e0542358c6060b"}, + {file = "cryptography-38.0.3-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6ab9516b85bebe7aa83f309bacc5f44a61eeb90d0b4ec125d2d003ce41932d36"}, + {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:068147f32fa662c81aebab95c74679b401b12b57494872886eb5c1139250ec5d"}, + {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:402852a0aea73833d982cabb6d0c3bb582c15483d29fb7085ef2c42bfa7e38d7"}, + {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b1b35d9d3a65542ed2e9d90115dfd16bbc027b3f07ee3304fc83580f26e43249"}, + {file = "cryptography-38.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6addc3b6d593cd980989261dc1cce38263c76954d758c3c94de51f1e010c9a50"}, + {file = "cryptography-38.0.3-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:be243c7e2bfcf6cc4cb350c0d5cdf15ca6383bbcb2a8ef51d3c9411a9d4386f0"}, + {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78cf5eefac2b52c10398a42765bfa981ce2372cbc0457e6bf9658f41ec3c41d8"}, + {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:4e269dcd9b102c5a3d72be3c45d8ce20377b8076a43cbed6f660a1afe365e436"}, + {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8d41a46251bf0634e21fac50ffd643216ccecfaf3701a063257fe0b2be1b6548"}, + {file = "cryptography-38.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:785e4056b5a8b28f05a533fab69febf5004458e20dad7e2e13a3120d8ecec75a"}, + {file = "cryptography-38.0.3.tar.gz", hash = "sha256:bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd"}, +] [package.dependencies] cffi = ">=1.12" @@ -629,6 +892,10 @@ description = "Decorators for Humans" category = "main" optional = true python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] [[package]] name = "docutils" @@ -637,6 +904,10 @@ description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, + {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, +] [[package]] name = "dukpy" @@ -645,6 +916,31 @@ description = "Simple JavaScript interpreter for Python" category = "main" optional = true python-versions = "*" +files = [ + {file = "dukpy-0.2.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:edd0862c34f085b60f17fc214c19ab6e38166fd08c85506aeaf370449b3ca20f"}, + {file = "dukpy-0.2.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99e5a90e01cf60a52bafed04d2099ab91b853279429c39a6010fcb264615679a"}, + {file = "dukpy-0.2.3-cp27-cp27m-win32.whl", hash = "sha256:267ddd5e4e88903467d3b0940b26e248739f2c870dde1365749fe39f24b76ebe"}, + {file = "dukpy-0.2.3-cp27-cp27m-win_amd64.whl", hash = "sha256:26af4776043578cd5a90b723f97c862172dd0c03be90db462c4a50526b370b70"}, + {file = "dukpy-0.2.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9a89548ff0bd15e415755bc034f76eb6220e8e0d5b9f9d476e6c7b7edc9470b7"}, + {file = "dukpy-0.2.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:906ec0fa1933fdb0df49e2de286ea8d64f14f7a1ed23705057b2f8eb73c5a036"}, + {file = "dukpy-0.2.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0658ecda9e85499c2a3236f59837aab27fbef19b75544f1d1f33704fa43e52e7"}, + {file = "dukpy-0.2.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:39739d135786d14b430c1d0a82b821d731dfec31369d4a315e1929ca37c48d72"}, + {file = "dukpy-0.2.3-cp35-cp35m-win32.whl", hash = "sha256:f90e133688e2d2d010c909b7a0e8d2dff73b7c08622480dcb6f8d81169a48235"}, + {file = "dukpy-0.2.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e9512519d39d048e64c89a876e3d4b569862e9bacdb9294046b13385b92fe657"}, + {file = "dukpy-0.2.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9aa761142872407d39da88fdbfcc0cc77c6a91b25c9cb9547b564c3e699137b6"}, + {file = "dukpy-0.2.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5b3589426d20dc46d6758754a42f359ad265f02a508de9978065de60626249dd"}, + {file = "dukpy-0.2.3-cp36-cp36m-win32.whl", hash = "sha256:cf8f702599f3abb42a1bc64df2d7a63115226042feff57b89d8f0fd3d5cb2592"}, + {file = "dukpy-0.2.3-cp36-cp36m-win_amd64.whl", hash = "sha256:494bccfe65c0db95c498584a99052b4039c28f171c901cf609dadf303c097d62"}, + {file = "dukpy-0.2.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:061f84e9786f18e7bc63c78afcddec7287ebacae35b4a95c4c49fac0146b6f0d"}, + {file = "dukpy-0.2.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:79f1dfe1276b3b2cef6f353df8889da45cab4cbae88c1b0c2f8895bc68efb345"}, + {file = "dukpy-0.2.3-cp37-cp37m-win32.whl", hash = "sha256:123c39095d5b282f2fdebe08088572688c67ce7d876129eb4bb7e1262650a4af"}, + {file = "dukpy-0.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:929c5fe7fc4c0aff25c8bf6284e9fb3a3ac74430104c2d260858b76e290013fe"}, + {file = "dukpy-0.2.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3395f84d793f1be55f250705fd1f4562c58718dde0304ae21b001dc0332e020a"}, + {file = "dukpy-0.2.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9499ec53247cc0e2453d2be0586d9fa6803b751961d05bc947946341ecea6560"}, + {file = "dukpy-0.2.3-cp38-cp38-win32.whl", hash = "sha256:ff245b01239fbb25b4a0b9bf30d3b4499648ce52bba981fe2cbac868052354fe"}, + {file = "dukpy-0.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:770c0795cbe5c41b604b12f372d2905587035f2f83489d2e1c36b88d50f9b175"}, + {file = "dukpy-0.2.3.tar.gz", hash = "sha256:cc8dd158326f95231d320da80be6e6a1d72bbaad9de2569eaffb6af736f45e6b"}, +] [package.extras] testing = ["mock", "pytest", "pytest-cov"] @@ -657,6 +953,9 @@ description = "Python wrapper around invoking editorconfig-checker (https://gith category = "dev" optional = false python-versions = ">=2.7" +files = [ + {file = "editorconfig-checker-2.4.0.tar.gz", hash = "sha256:1f7839df7d967d95f0cf2ed6a42a0f456c65072d2ffcff1fedc0eac62ed236ea"}, +] [[package]] name = "exceptiongroup" @@ -665,6 +964,10 @@ description = "Backport of PEP 654 (exception groups)" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.0.0rc9-py3-none-any.whl", hash = "sha256:2e3c3fc1538a094aab74fad52d6c33fc94de3dfee3ee01f187c0e0c72aec5337"}, + {file = "exceptiongroup-1.0.0rc9.tar.gz", hash = "sha256:9086a4a21ef9b31c72181c77c040a074ba0889ee56a7b289ff0afb0d97655f96"}, +] [package.extras] test = ["pytest (>=6)"] @@ -676,6 +979,10 @@ description = "execnet: rapid multi-Python deployment" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, + {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, +] [package.extras] testing = ["pre-commit"] @@ -687,6 +994,10 @@ description = "A platform independent file lock." category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, + {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, +] [package.extras] docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] @@ -699,6 +1010,9 @@ description = "Simple ctypes bindings for FUSE" category = "main" optional = true python-versions = "*" +files = [ + {file = "fusepy-3.0.1.tar.gz", hash = "sha256:72ff783ec2f43de3ab394e3f7457605bf04c8cf288a2f4068b4cde141d4ee6bd"}, +] [[package]] name = "future" @@ -707,6 +1021,9 @@ description = "Clean single-source support for Python 3 and 2" category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, +] [[package]] name = "h11" @@ -715,6 +1032,10 @@ description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "h11-0.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"}, + {file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"}, +] [[package]] name = "h2" @@ -723,6 +1044,10 @@ description = "HTTP/2 State-Machine based protocol implementation" category = "main" optional = true python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] [package.dependencies] hpack = ">=4.0,<5" @@ -735,6 +1060,10 @@ description = "Pure-Python HPACK header compression" category = "main" optional = true python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] [[package]] name = "hypercorn" @@ -743,6 +1072,10 @@ description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "Hypercorn-0.13.2-py3-none-any.whl", hash = "sha256:ca18f91ab3fa823cbe9e949738f9f2cc07027cd647c80d8f93e4b1a2a175f112"}, + {file = "Hypercorn-0.13.2.tar.gz", hash = "sha256:6307be5cbdf6ba411967d4661202dc4f79bd511b5d318bc4eed88b09418427f8"}, +] [package.dependencies] h11 = "*" @@ -764,6 +1097,10 @@ description = "HTTP/2 framing layer for Python" category = "main" optional = true python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] [[package]] name = "hypothesis" @@ -772,6 +1109,10 @@ description = "A library for property-based testing" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "hypothesis-6.56.3-py3-none-any.whl", hash = "sha256:802d236d03dbd54e0e1c55c0daa2ec41aeaadc87a4dcbb41421b78bf3f7a7789"}, + {file = "hypothesis-6.56.3.tar.gz", hash = "sha256:15dae5d993339aefa57e00f5cb5a5817ff300eeb661d96d1c9d094eb62b04c9a"}, +] [package.dependencies] attrs = ">=19.2.0" @@ -801,6 +1142,10 @@ description = "Hypothesis plugin for trio" category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "hypothesis-trio-0.6.0.tar.gz", hash = "sha256:d7ab108ac99758011b20f2448f1b1269375c68c1ffda9e4468600a4975ff955c"}, + {file = "hypothesis_trio-0.6.0-py3-none-any.whl", hash = "sha256:3ac261dc6fcf3862d7d57ffa52d294539f8d807ac9483d58a8060df3c9e856fc"}, +] [package.dependencies] hypothesis = ">=6.7.0" @@ -813,6 +1158,10 @@ description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] [[package]] name = "importlib-metadata" @@ -821,6 +1170,10 @@ description = "Read metadata from Python packages" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"}, + {file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"}, +] [package.dependencies] zipp = ">=0.5" @@ -837,6 +1190,10 @@ description = "iniconfig: brain-dead simple config-ini parsing" category = "dev" optional = false python-versions = "*" +files = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] [[package]] name = "itsdangerous" @@ -845,6 +1202,10 @@ description = "Safely pass data to untrusted environments and back." category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, + {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, +] [[package]] name = "jinja2" @@ -853,6 +1214,10 @@ description = "A very fast and expressive template engine." category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] [package.dependencies] MarkupSafe = ">=2.0" @@ -867,6 +1232,10 @@ description = "JSON Matching Expressions" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] [[package]] name = "macholib" @@ -875,6 +1244,10 @@ description = "Mach-O header analysis and editing" category = "dev" optional = false python-versions = "*" +files = [ + {file = "macholib-1.16.2-py2.py3-none-any.whl", hash = "sha256:44c40f2cd7d6726af8fa6fe22549178d3a4dfecc35a9cd15ea916d9c83a688e0"}, + {file = "macholib-1.16.2.tar.gz", hash = "sha256:557bbfa1bb255c20e9abafe7ed6cd8046b48d9525db2f9b77d3122a63a2a8bf8"}, +] [package.dependencies] altgraph = ">=0.17" @@ -886,6 +1259,48 @@ description = "Safely add untrusted strings to HTML/XML markup." category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, +] [[package]] name = "maturin" @@ -894,6 +1309,20 @@ description = "Build and publish crates with pyo3, rust-cpython and cffi binding category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "maturin-0.13.7-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:bc58b0266a4c124f9afd69a987ac324ff35c0d963b41073ed64a32f94c226d5a"}, + {file = "maturin-0.13.7-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:424d53adc9684167cf89829275fe5072331a197de0ac08e7a893f9283c7df213"}, + {file = "maturin-0.13.7-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:3137876c338eb7e551ba44a609b5f02d02454d1b3a8677ad6bf2121c5a92b2b7"}, + {file = "maturin-0.13.7-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:a96f1b3ede71c0f76b8c7cfac18a9eec90174bdf434fa9aeff491be9a7ca5179"}, + {file = "maturin-0.13.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:0b6ac1219a809155057fd1f358f7ece03c3abd2e2991832ce5146825a9fa4160"}, + {file = "maturin-0.13.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:3c36f429adc3a8af8de9838399750742a86053f0031a953b48ee92932120dc0c"}, + {file = "maturin-0.13.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:bb3a2830d64ae6a324571f694475b91111e827bc0ccc60a0c47f4fb596a46bd8"}, + {file = "maturin-0.13.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:794f58d3103449f8cd8ab5f36fd05c31b8d8de3643cd0e3720fd5dc3c328dd5c"}, + {file = "maturin-0.13.7-py3-none-win32.whl", hash = "sha256:63586eb286866264ec62d29df6ab955360de6226128f67d14623ffe1a12d4963"}, + {file = "maturin-0.13.7-py3-none-win_amd64.whl", hash = "sha256:f50d62aca567fdbbb929771794f3c5c78048ef0efa4af7d83ed472a8b8d26454"}, + {file = "maturin-0.13.7-py3-none-win_arm64.whl", hash = "sha256:8c6225e7eba2885a0cd82a6cf898e74bb720796a5744e0450f3b1340d1ca97af"}, + {file = "maturin-0.13.7.tar.gz", hash = "sha256:c0a77aa0c57f945649ca711c806203a1b6888ad49c2b8b85196ffdcf0421db77"}, +] [package.dependencies] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} @@ -909,6 +1338,60 @@ description = "MessagePack serializer" category = "main" optional = false python-versions = "*" +files = [ + {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250"}, + {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88"}, + {file = "msgpack-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467"}, + {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6"}, + {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa"}, + {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6"}, + {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba"}, + {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e"}, + {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db"}, + {file = "msgpack-1.0.4-cp310-cp310-win32.whl", hash = "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef"}, + {file = "msgpack-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075"}, + {file = "msgpack-1.0.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52"}, + {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9"}, + {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9"}, + {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08"}, + {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8"}, + {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6"}, + {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae"}, + {file = "msgpack-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6"}, + {file = "msgpack-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661"}, + {file = "msgpack-1.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c"}, + {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0"}, + {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227"}, + {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff"}, + {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd"}, + {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e"}, + {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236"}, + {file = "msgpack-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44"}, + {file = "msgpack-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1"}, + {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d"}, + {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab"}, + {file = "msgpack-1.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb"}, + {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9"}, + {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e"}, + {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1"}, + {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e"}, + {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43"}, + {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243"}, + {file = "msgpack-1.0.4-cp38-cp38-win32.whl", hash = "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2"}, + {file = "msgpack-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6"}, + {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae"}, + {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55"}, + {file = "msgpack-1.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da"}, + {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f"}, + {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92"}, + {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f"}, + {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624"}, + {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8"}, + {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae"}, + {file = "msgpack-1.0.4-cp39-cp39-win32.whl", hash = "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c"}, + {file = "msgpack-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce"}, + {file = "msgpack-1.0.4.tar.gz", hash = "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f"}, +] [[package]] name = "mypy" @@ -917,6 +1400,32 @@ description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, + {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, + {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, + {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, + {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, + {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, + {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, + {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, + {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, + {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, + {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, + {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, + {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, + {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, + {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, + {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, + {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, + {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, + {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, + {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, + {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, + {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, +] [package.dependencies] mypy-extensions = ">=0.4.3" @@ -935,17 +1444,10 @@ description = "Experimental type system extensions for programs checked with the category = "main" optional = false python-versions = "*" - -[[package]] -name = "oscrypto" -version = "1.3.0" -description = "TLS (SSL) sockets, key generation, encryption, decryption, signing, verification and KDFs using the OS crypto libraries. Does not require a compiler, and relies on the OS for patching. Works on Windows, OS X and Linux/BSD." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -asn1crypto = ">=1.5.1" +files = [ + {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, + {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, +] [[package]] name = "outcome" @@ -954,6 +1456,10 @@ description = "Capture the outcome of Python function calls." category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "outcome-1.2.0-py2.py3-none-any.whl", hash = "sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"}, + {file = "outcome-1.2.0.tar.gz", hash = "sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672"}, +] [package.dependencies] attrs = ">=19.2.0" @@ -965,6 +1471,10 @@ description = "Core utilities for Python packages" category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] [package.dependencies] pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" @@ -976,6 +1486,10 @@ description = "Utility library for gitignore style pattern matching of file path category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, + {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, +] [[package]] name = "pbr" @@ -984,6 +1498,10 @@ description = "Python Build Reasonableness" category = "main" optional = true python-versions = ">=2.6" +files = [ + {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, + {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, +] [[package]] name = "pefile" @@ -992,6 +1510,9 @@ description = "Python PE parsing module" category = "dev" optional = false python-versions = ">=3.6.0" +files = [ + {file = "pefile-2022.5.30.tar.gz", hash = "sha256:a5488a3dd1fd021ce33f969780b88fe0f7eebb76eb20996d7318f307612a045b"}, +] [package.dependencies] future = "*" @@ -1003,6 +1524,10 @@ description = "A small Python module for determining appropriate platform-specif category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, + {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, +] [package.extras] docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] @@ -1015,6 +1540,10 @@ description = "plugin and hook calling mechanisms for python" category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] [package.extras] dev = ["pre-commit", "tox"] @@ -1027,6 +1556,10 @@ description = "Poetry lock package generator" category = "dev" optional = false python-versions = ">=3.6.2,<4.0.0" +files = [ + {file = "poetry-lock-package-0.4.5.tar.gz", hash = "sha256:a74a4916cc53ebbfd3b3575b73d0e93bac74b75ff2d74f92a24e7a8938fc20f2"}, + {file = "poetry_lock_package-0.4.5-py3-none-any.whl", hash = "sha256:5b8ae966ec8c760a69d38bde6887501d594b467e00902dd341328cd8079ccaee"}, +] [package.dependencies] toml = ">=0.10.1,<0.11.0" @@ -1038,6 +1571,10 @@ description = "A pure-Python implementation of the HTTP/2 priority tree" category = "main" optional = true python-versions = ">=3.6.1" +files = [ + {file = "priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa"}, + {file = "priority-2.0.0.tar.gz", hash = "sha256:c965d54f1b8d0d0b19479db3924c7c36cf672dbf2aec92d43fbdaf4492ba18c0"}, +] [[package]] name = "psutil" @@ -1046,9 +1583,25 @@ description = "Cross-platform lib for process and system monitoring in Python." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] +files = [ + {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, + {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, + {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"}, + {file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"}, + {file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"}, + {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"}, + {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"}, + {file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"}, + {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"}, + {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"}, + {file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"}, + {file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"}, + {file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"}, + {file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] [[package]] name = "pycparser" @@ -1057,6 +1610,10 @@ description = "C parser in Python" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] [[package]] name = "pyinstaller" @@ -1065,6 +1622,19 @@ description = "PyInstaller bundles a Python application and all its dependencies category = "dev" optional = false python-versions = "<3.12,>=3.7" +files = [ + {file = "pyinstaller-5.6.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:0465edb7a5b2bc74ac983d419fd980fd2e4c7d49f4c013edd4befb6ca70d3c2b"}, + {file = "pyinstaller-5.6.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:556750250bba85cf7ede168994fe70fcdeeba8d22f51eaedfd94b3efb6faa6ce"}, + {file = "pyinstaller-5.6.1-py3-none-manylinux2014_i686.whl", hash = "sha256:2abb74b008f01a8d9b54c27ea51aa6d59ea6137d507de9d580f79b934e0ca7b8"}, + {file = "pyinstaller-5.6.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:bb3faba1a29686e1c2d71a939bc6d1a57ca218d6968f43620591df42058635e0"}, + {file = "pyinstaller-5.6.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:b8dc59b00bc09053ed0476b47423373fafb8f4d57618e9eff7047cda8942e1c4"}, + {file = "pyinstaller-5.6.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:14a0bb008966ba074e173f94b5bffd78a4d84e4a21fafc63c1b72851a40a918d"}, + {file = "pyinstaller-5.6.1-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:8c423556f0aac7651cda813db0d215c36c51717c4079e407136a4d9f730d38b0"}, + {file = "pyinstaller-5.6.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a64a5472ee36f63e773be63535817b6d8aea1c1cf9acd18858c22c66fe575043"}, + {file = "pyinstaller-5.6.1-py3-none-win32.whl", hash = "sha256:fc734eb91e08c75fc7505170d765a49d781dad9e49dd641ebe4f8a82782f0be2"}, + {file = "pyinstaller-5.6.1-py3-none-win_amd64.whl", hash = "sha256:ec9d9491681ac55e369a5226833694bf299ddeaeab6df4ef9d44758d4342f10a"}, + {file = "pyinstaller-5.6.1.tar.gz", hash = "sha256:a7fac3fa8f75bce2839e0ab910baf0e935ff2b5f327c32aedade563e1b610967"}, +] [package.dependencies] altgraph = "*" @@ -1085,21 +1655,10 @@ description = "Community maintained hooks for PyInstaller" category = "dev" optional = false python-versions = ">=3.7" - -[[package]] -name = "pynacl" -version = "1.5.0" -description = "Python binding to the Networking and Cryptography (NaCl) library" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -cffi = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5)", "sphinx_rtd_theme"] -tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] +files = [ + {file = "pyinstaller-hooks-contrib-2022.10.tar.gz", hash = "sha256:e5edd4094175e78c178ef987b61be19efff6caa23d266ade456fc753e847f62e"}, + {file = "pyinstaller_hooks_contrib-2022.10-py2.py3-none-any.whl", hash = "sha256:d1dd6ea059dc30e77813cc12a5efa8b1d228e7da8f5b884fe11775f946db1784"}, +] [[package]] name = "pyobjc-core" @@ -1108,6 +1667,16 @@ description = "Python<->ObjC Interoperability Module" category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "pyobjc-core-8.5.1.tar.gz", hash = "sha256:f8592a12de076c27006700c4a46164478564fa33d7da41e7cbdd0a3bf9ddbccf"}, + {file = "pyobjc_core-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b62dcf987cc511188fc2aa5b4d3b9fd895361ea4984380463497ce4b0752ddf4"}, + {file = "pyobjc_core-8.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0accc653501a655f66c13f149a1d3d30e6cb65824edf852f7960a00c4f930d5b"}, + {file = "pyobjc_core-8.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f82b32affc898e9e5af041c1cecde2c99f2ce160b87df77f678c99f1550a4655"}, + {file = "pyobjc_core-8.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f7b2f6b6f3caeb882c658fe0c7098be2e8b79893d84daa8e636cb3e58a07df00"}, + {file = "pyobjc_core-8.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:872c0202c911a5a2f1269261c168e36569f6ddac17e5d854ac19e581726570cc"}, + {file = "pyobjc_core-8.5.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:21f92e231a4bae7f2d160d065f5afbf5e859a1e37f29d34ac12592205fc8c108"}, + {file = "pyobjc_core-8.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:315334dd09781129af6a39641248891c4caa57043901750b0139c6614ce84ec0"}, +] [[package]] name = "pyobjc-framework-cocoa" @@ -1116,6 +1685,16 @@ description = "Wrappers for the Cocoa frameworks on macOS" category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "pyobjc-framework-Cocoa-8.5.1.tar.gz", hash = "sha256:9a3de5cdb4644e85daf53f2ed912ef6c16ea5804a9e65552eafe62c2e139eb8c"}, + {file = "pyobjc_framework_Cocoa-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa572acc2628488a47be8d19f4701fc96fce7377cc4da18316e1e08c3918521a"}, + {file = "pyobjc_framework_Cocoa-8.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cb3ae21c8d81b7f02a891088c623cef61bca89bd671eff58c632d2f926b649f3"}, + {file = "pyobjc_framework_Cocoa-8.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:88f08f5bd94c66d373d8413c1d08218aff4cff0b586e0cc4249b2284023e7577"}, + {file = "pyobjc_framework_Cocoa-8.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:063683b57e4bd88cb0f9631ae65d25ec4eecf427d2fe8d0c578f88da9c896f3f"}, + {file = "pyobjc_framework_Cocoa-8.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f8806ddfac40620fb27f185d0f8937e69e330617319ecc2eccf6b9c8451bdd1"}, + {file = "pyobjc_framework_Cocoa-8.5.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:7733a9a201df9e0cc2a0cf7bf54d76bd7981cba9b599353b243e3e0c9eefec10"}, + {file = "pyobjc_framework_Cocoa-8.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f0ab227f99d3e25dd3db73f8cde0999914a5f0dd6a08600349d25f95eaa0da63"}, +] [package.dependencies] pyobjc-core = ">=8.5.1" @@ -1127,6 +1706,12 @@ description = "Wrappers for the framework SystemConfiguration on macOS" category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "pyobjc-framework-SystemConfiguration-8.5.1.tar.gz", hash = "sha256:f0c75fda3498d296e10a673700032ae0562e4c24b1f41c6290751edb939f84b5"}, + {file = "pyobjc_framework_SystemConfiguration-8.5.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:e499ddcdf02b8cb9cdf207ea4c09c4bde2cc891c01f11ffd4fc040d658a1fd4d"}, + {file = "pyobjc_framework_SystemConfiguration-8.5.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:bbd56a3a6534ae3de62ecbc3551c8e4d6861406369c2e7d96fb6ff2158491f08"}, + {file = "pyobjc_framework_SystemConfiguration-8.5.1-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:4a373c010df56cdf4b620c7f706fb7807a50d60ae12f2547ee0e8dae0616986b"}, +] [package.dependencies] pyobjc-core = ">=8.5.1" @@ -1139,6 +1724,9 @@ description = "Proxy auto-config and auto-discovery for Python." category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "PyPAC-0.16.0-py2.py3-none-any.whl", hash = "sha256:921630e95e596050844e299d525df030bb39430ced18001f3960409e4e0cb3b1"}, +] [package.dependencies] dukpy = ">=0.2.2" @@ -1157,6 +1745,10 @@ description = "pyparsing module - Classes and methods to define and execute pars category = "main" optional = false python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, + {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, +] [package.extras] diagrams = ["jinja2", "railroad-diagrams"] @@ -1168,6 +1760,13 @@ description = "Python bindings for the Qt cross platform application toolkit" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "PyQt5-5.15.7-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:1a793748c60d5aff3850b7abf84d47c1d41edb11231b7d7c16bef602c36be643"}, + {file = "PyQt5-5.15.7-cp37-abi3-manylinux1_x86_64.whl", hash = "sha256:e319c9d8639e0729235c1b09c99afdadad96fa3dbd8392ab561b5ab5946ee6ef"}, + {file = "PyQt5-5.15.7-cp37-abi3-win32.whl", hash = "sha256:08694f0a4c7d4f3d36b2311b1920e6283240ad3b7c09b515e08262e195dcdf37"}, + {file = "PyQt5-5.15.7-cp37-abi3-win_amd64.whl", hash = "sha256:232fe5b135a095cbd024cf341d928fc672c963f88e6a52b0c605be8177c2fdb5"}, + {file = "PyQt5-5.15.7.tar.gz", hash = "sha256:755121a52b3a08cb07275c10ebb96576d36e320e572591db16cfdbc558101594"}, +] [package.dependencies] PyQt5-Qt5 = ">=5.15.0" @@ -1180,6 +1779,12 @@ description = "The subset of a Qt installation needed by PyQt5." category = "main" optional = true python-versions = "*" +files = [ + {file = "PyQt5_Qt5-5.15.2-py3-none-macosx_10_13_intel.whl", hash = "sha256:76980cd3d7ae87e3c7a33bfebfaee84448fd650bad6840471d6cae199b56e154"}, + {file = "PyQt5_Qt5-5.15.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:1988f364ec8caf87a6ee5d5a3a5210d57539988bf8e84714c7d60972692e2f4a"}, + {file = "PyQt5_Qt5-5.15.2-py3-none-win32.whl", hash = "sha256:9cc7a768b1921f4b982ebc00a318ccb38578e44e45316c7a4a850e953e1dd327"}, + {file = "PyQt5_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:750b78e4dba6bdf1607febedc08738e318ea09e9b10aea9ff0d73073f11f6962"}, +] [[package]] name = "pyqt5-sip" @@ -1188,6 +1793,25 @@ description = "The sip module support for PyQt5" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "PyQt5_sip-12.11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f1f9e312ff8284d6dfebc5366f6f7d103f84eec23a4da0be0482403933e68660"}, + {file = "PyQt5_sip-12.11.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:4031547dfb679be309094bfa79254f5badc5ddbe66b9ad38e319d84a7d612443"}, + {file = "PyQt5_sip-12.11.0-cp310-cp310-win32.whl", hash = "sha256:ad21ca0ee8cae2a41b61fc04949dccfab6fe008749627d94e8c7078cb7a73af1"}, + {file = "PyQt5_sip-12.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:3126c84568ab341c12e46ded2230f62a9a78752a70fdab13713f89a71cd44f73"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0f77655c62ec91d47c2c99143f248624d44dd2d8a12d016e7c020508ad418aca"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ec5e9ef78852e1f96f86d7e15c9215878422b83dde36d44f1539a3062942f19c"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-win32.whl", hash = "sha256:d12b81c3a08abf7657a2ebc7d3649852a1f327eb2146ebadf45930486d32e920"}, + {file = "PyQt5_sip-12.11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b69a1911f768b489846335e31e49eb34795c6b5a038ca24d894d751e3b0b44da"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51e377789d59196213eddf458e6927f33ba9d217b614d17d20df16c9a8b2c41c"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4e5c1559311515291ea0ab0635529f14536954e3b973a7c7890ab7e4de1c2c23"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-win32.whl", hash = "sha256:9bca450c5306890cb002fe36bbca18f979dd9e5b810b766dce8e3ce5e66ba795"}, + {file = "PyQt5_sip-12.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:f6b72035da4e8fecbb0bc4a972e30a5674a9ad5608dbddaa517e983782dbf3bf"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9356260d4feb60dbac0ab66f8a791a0d2cda1bf98c9dec8e575904a045fbf7c5"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:205f3e1b3eea3597d8e878936c1a06e04bd23a59e8b179ee806465d72eea3071"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-win32.whl", hash = "sha256:686071be054e5be6ca5aaaef7960931d4ba917277e839e2e978c7cbe3f43bb6e"}, + {file = "PyQt5_sip-12.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:42320e7a94b1085ed85d49794ed4ccfe86f1cae80b44a894db908a8aba2bc60e"}, + {file = "PyQt5_sip-12.11.0.tar.gz", hash = "sha256:b4710fd85b57edef716cc55fae45bfd5bfac6fc7ba91036f1dcc3f331ca0eb39"}, +] [[package]] name = "pyqt5-stubs" @@ -1196,6 +1820,10 @@ description = "PEP561 stub files for the PyQt5 framework" category = "dev" optional = false python-versions = ">= 3.5" +files = [ + {file = "PyQt5-stubs-5.15.6.0.tar.gz", hash = "sha256:91270ac23ebf38a1dc04cd97aa852cd08af82dc839100e5395af1447e3e99707"}, + {file = "PyQt5_stubs-5.15.6.0-py3-none-any.whl", hash = "sha256:7fb8177c72489a8911f021b7bd7c33f12c87f6dba92dcef3fdcdb5d9400f0f3f"}, +] [package.extras] dev = ["mypy (==0.930)", "pytest", "pytest-xvfb"] @@ -1207,6 +1835,10 @@ description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, + {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, +] [package.dependencies] attrs = ">=19.2.0" @@ -1227,6 +1859,10 @@ description = "Pytest plugin for measuring coverage." category = "dev" optional = false python-versions = ">=3.6" +files = [ + {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, + {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, +] [package.dependencies] coverage = {version = ">=5.2.1", extras = ["toml"]} @@ -1242,6 +1878,10 @@ description = "pytest support for PyQt and PySide applications" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-qt-4.2.0.tar.gz", hash = "sha256:00a17b586dd530b6d7a9399923a40489ca4a9a309719011175f55dc6b5dc8f41"}, + {file = "pytest_qt-4.2.0-py2.py3-none-any.whl", hash = "sha256:a7659960a1ab2af8fc944655a157ff45d714b80ed7a6af96a4b5bb99ecf40a22"}, +] [package.dependencies] pytest = ">=3.0.0" @@ -1257,6 +1897,10 @@ description = "pytest plugin to re-run tests to eliminate flaky failures" category = "dev" optional = false python-versions = ">= 3.6" +files = [ + {file = "pytest-rerunfailures-10.2.tar.gz", hash = "sha256:9e1e1bad51e07642c5bbab809fc1d4ec8eebcb7de86f90f1a26e6ef9de446697"}, + {file = "pytest_rerunfailures-10.2-py3-none-any.whl", hash = "sha256:d31d8e828dfd39363ad99cd390187bf506c7a433a89f15c3126c7d16ab723fe2"}, +] [package.dependencies] pytest = ">=5.3" @@ -1269,6 +1913,10 @@ description = "Pytest plugin for trio" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-trio-0.8.0.tar.gz", hash = "sha256:8363db6336a79e6c53375a2123a41ddbeccc4aa93f93788651641789a56fb52e"}, + {file = "pytest_trio-0.8.0-py3-none-any.whl", hash = "sha256:e6a7e7351ae3e8ec3f4564d30ee77d1ec66e1df611226e5618dbb32f9545c841"}, +] [package.dependencies] outcome = ">=1.1.0" @@ -1282,6 +1930,10 @@ description = "pytest xdist plugin for distributed testing, most importantly acr category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "pytest-xdist-3.1.0.tar.gz", hash = "sha256:40fdb8f3544921c5dfcd486ac080ce22870e71d82ced6d2e78fa97c2addd480c"}, + {file = "pytest_xdist-3.1.0-py3-none-any.whl", hash = "sha256:70a76f191d8a1d2d6be69fc440cdf85f3e4c03c08b520fd5dc5d338d6cf07d89"}, +] [package.dependencies] execnet = ">=1.1" @@ -1299,6 +1951,10 @@ description = "Extensions to the standard Python datetime module" category = "main" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] [package.dependencies] six = ">=1.5" @@ -1310,6 +1966,10 @@ description = "OpenStack Object Storage API Client Library" category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "python-swiftclient-4.1.0.tar.gz", hash = "sha256:f82298e4a48f7cbdd680f2638c85d1ca7ae1a76edbe30036d21b4cd7a29c09eb"}, + {file = "python_swiftclient-4.1.0-py3-none-any.whl", hash = "sha256:4268219e158cd72c0b0751a6f27240da4eea7827485db765f5df9542da4cf144"}, +] [package.dependencies] requests = ">=2.4.0" @@ -1325,6 +1985,10 @@ description = "World timezone definitions, modern and historical" category = "dev" optional = false python-versions = "*" +files = [ + {file = "pytz-2022.5-py2.py3-none-any.whl", hash = "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22"}, + {file = "pytz-2022.5.tar.gz", hash = "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"}, +] [[package]] name = "pywin32" @@ -1333,6 +1997,22 @@ description = "Python for Window Extensions" category = "dev" optional = false python-versions = "*" +files = [ + {file = "pywin32-304-cp310-cp310-win32.whl", hash = "sha256:3c7bacf5e24298c86314f03fa20e16558a4e4138fc34615d7de4070c23e65af3"}, + {file = "pywin32-304-cp310-cp310-win_amd64.whl", hash = "sha256:4f32145913a2447736dad62495199a8e280a77a0ca662daa2332acf849f0be48"}, + {file = "pywin32-304-cp310-cp310-win_arm64.whl", hash = "sha256:d3ee45adff48e0551d1aa60d2ec066fec006083b791f5c3527c40cd8aefac71f"}, + {file = "pywin32-304-cp311-cp311-win32.whl", hash = "sha256:30c53d6ce44c12a316a06c153ea74152d3b1342610f1b99d40ba2795e5af0269"}, + {file = "pywin32-304-cp311-cp311-win_amd64.whl", hash = "sha256:7ffa0c0fa4ae4077e8b8aa73800540ef8c24530057768c3ac57c609f99a14fd4"}, + {file = "pywin32-304-cp311-cp311-win_arm64.whl", hash = "sha256:cbbe34dad39bdbaa2889a424d28752f1b4971939b14b1bb48cbf0182a3bcfc43"}, + {file = "pywin32-304-cp36-cp36m-win32.whl", hash = "sha256:be253e7b14bc601718f014d2832e4c18a5b023cbe72db826da63df76b77507a1"}, + {file = "pywin32-304-cp36-cp36m-win_amd64.whl", hash = "sha256:de9827c23321dcf43d2f288f09f3b6d772fee11e809015bdae9e69fe13213988"}, + {file = "pywin32-304-cp37-cp37m-win32.whl", hash = "sha256:f64c0377cf01b61bd5e76c25e1480ca8ab3b73f0c4add50538d332afdf8f69c5"}, + {file = "pywin32-304-cp37-cp37m-win_amd64.whl", hash = "sha256:bb2ea2aa81e96eee6a6b79d87e1d1648d3f8b87f9a64499e0b92b30d141e76df"}, + {file = "pywin32-304-cp38-cp38-win32.whl", hash = "sha256:94037b5259701988954931333aafd39cf897e990852115656b014ce72e052e96"}, + {file = "pywin32-304-cp38-cp38-win_amd64.whl", hash = "sha256:ead865a2e179b30fb717831f73cf4373401fc62fbc3455a0889a7ddac848f83e"}, + {file = "pywin32-304-cp39-cp39-win32.whl", hash = "sha256:25746d841201fd9f96b648a248f731c1dec851c9a08b8e33da8b56148e4c65cc"}, + {file = "pywin32-304-cp39-cp39-win_amd64.whl", hash = "sha256:d24a3382f013b21aa24a5cfbfad5a2cd9926610c0affde3e8ab5b3d7dbcf4ac9"}, +] [[package]] name = "pywin32-ctypes" @@ -1341,6 +2021,10 @@ description = "" category = "dev" optional = false python-versions = "*" +files = [ + {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, + {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, +] [[package]] name = "qrcode" @@ -1349,6 +2033,9 @@ description = "QR Code image generator" category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "qrcode-7.3.1.tar.gz", hash = "sha256:375a6ff240ca9bd41adc070428b5dfc1dcfbb0f2507f1ac848f6cded38956578"}, +] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} @@ -1367,6 +2054,10 @@ description = "a library bringing Qt GUIs together with ``async`` and ``await`` category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "qtrio-0.6.0-py3-none-any.whl", hash = "sha256:25f48b1debc1ad44ada6269f10dcffabb9e699d56064b443f36d428c83cccdcb"}, + {file = "qtrio-0.6.0.tar.gz", hash = "sha256:1435eb11fb8e06fed28815aad0cd614f22f9a5c94855d82fa7a4abb69a5b54e4"}, +] [package.dependencies] async-generator = "*" @@ -1398,6 +2089,10 @@ description = "a thin compatibility layer for Python code to use Qt through vari category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "qts-0.3-py3-none-any.whl", hash = "sha256:4e041b91daeb02fce0a156889ea3e48fc5e3e3ba8f594cd72b6bd5765720b702"}, + {file = "qts-0.3.tar.gz", hash = "sha256:84c62a445824cab252b64cff66b244f6d130fd2df88cf495c23c77df00024345"}, +] [package.dependencies] attrs = ">=20.1.0" @@ -1422,6 +2117,10 @@ description = "A Python ASGI web microframework with the same API as Flask" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "Quart-0.18.3-py3-none-any.whl", hash = "sha256:c221a7deb83a014dee040108d654b6141fe37f59e249c5caa0fdcf6506caf50b"}, + {file = "Quart-0.18.3.tar.gz", hash = "sha256:dc4de597d5d4693627c90904b233d729531f6b27c1164f760476d3967aee2a4a"}, +] [package.dependencies] aiofiles = "*" @@ -1445,6 +2144,10 @@ description = "A Quart extension to provide trio support" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "quart-trio-0.10.0.tar.gz", hash = "sha256:66d4a2f8c3c417741d0e9709e0270edcedfdc26a9daac9e348b374f51c6decf8"}, + {file = "quart_trio-0.10.0-py3-none-any.whl", hash = "sha256:e22759a5e237f47dfff10a8dad3064d1cb11515c6550bf00f988695a068f7249"}, +] [package.dependencies] hypercorn = {version = ">=0.12.0", extras = ["trio"]} @@ -1461,6 +2164,10 @@ description = "Python HTTP for Humans." category = "main" optional = true python-versions = ">=3.7, <4" +files = [ + {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, + {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, +] [package.dependencies] certifi = ">=2017.4.17" @@ -1479,6 +2186,10 @@ description = "File transport adapter for Requests" category = "main" optional = true python-versions = "*" +files = [ + {file = "requests-file-1.5.1.tar.gz", hash = "sha256:07d74208d3389d01c38ab89ef403af0cfec63957d53a0081d8eca738d0247d8e"}, + {file = "requests_file-1.5.1-py2.py3-none-any.whl", hash = "sha256:dfe5dae75c12481f68ba353183c53a65e6044c923e64c24b2209f6c7570ca953"}, +] [package.dependencies] requests = ">=1.0.0" @@ -1491,6 +2202,24 @@ description = "An extremely fast Python linter, written in Rust." category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.149-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:e56d77e2a33067e480d6e9ecc328b066c9f8a96ec0f049f7c6107ff1d7106f7f"}, + {file = "ruff-0.0.149-py3-none-macosx_10_9_x86_64.macosx_10_9_arm64.macosx_10_9_universal2.whl", hash = "sha256:ad6e65923abbc59cb677c6d3bbfd778f87a95942c5499eb595afd6803999bf80"}, + {file = "ruff-0.0.149-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eab933a922721930fd6fd02b1001355ee8b81e8810796d7e5d16d2e72a14dc88"}, + {file = "ruff-0.0.149-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:89c5bbc74e2a79f853c3477f1b87846a77b489029d49e4ff53cfcb3d41217b8c"}, + {file = "ruff-0.0.149-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afa90ff653ef1354ffeaca92c8fb57a8aac16019a702c1c1cf50625b580eb421"}, + {file = "ruff-0.0.149-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9dc2710115b3006231ab6843d5dc1719618cd7972fa69fcd30e8b3496f380cd9"}, + {file = "ruff-0.0.149-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d79584f96f133f5856d846a162a9f083ac116b890707ef32b4446f4a5b15ccec"}, + {file = "ruff-0.0.149-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8efb6b2f96b127239ee17de9eb9f858b01c72483a9a2c100126ec54d4313f63d"}, + {file = "ruff-0.0.149-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f198fc1cb6cf66e864156449079921a846abe8b6488674f646ea09bccd81457"}, + {file = "ruff-0.0.149-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7e7bde713fd6a6305078dbf54c61e403d120b29093a3e365ec71607574ad1caa"}, + {file = "ruff-0.0.149-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5437e96025dc4427e77e8cf2b49c5ac04b2f3c9e9c62799d60f5f0d5bfc20be8"}, + {file = "ruff-0.0.149-py3-none-musllinux_1_2_i686.whl", hash = "sha256:481b5093db3dd59cf31c192bfe8c1594cebd46e28a36f86d9a1683802a73e9a7"}, + {file = "ruff-0.0.149-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a02c571dbb09c3ee0a17be507ddeec5cdbca2ab098f26aeead2fe691843a837a"}, + {file = "ruff-0.0.149-py3-none-win32.whl", hash = "sha256:58605add6c6f4b5d8306290c66965609da386c5b686a30c535a319dfba3c9af7"}, + {file = "ruff-0.0.149-py3-none-win_amd64.whl", hash = "sha256:58f640e94d5473db4cde84211659576aeccb88ae459e273f204683596b5ec205"}, + {file = "ruff-0.0.149.tar.gz", hash = "sha256:b6707c1ecc9730900138eb92dd0e7cd9123364ae9b33ba2cc9d623990129a29e"}, +] [[package]] name = "s3transfer" @@ -1499,6 +2228,10 @@ description = "An Amazon S3 Transfer Manager" category = "main" optional = true python-versions = ">= 3.7" +files = [ + {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, + {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, +] [package.dependencies] botocore = ">=1.12.36,<2.0a.0" @@ -1513,6 +2246,10 @@ description = "Python client for Sentry (https://sentry.io)" category = "main" optional = false python-versions = "*" +files = [ + {file = "sentry-sdk-1.10.1.tar.gz", hash = "sha256:105faf7bd7b7fa25653404619ee261527266b14103fe1389e0ce077bd23a9691"}, + {file = "sentry_sdk-1.10.1-py2.py3-none-any.whl", hash = "sha256:06c0fa9ccfdc80d7e3b5d2021978d6eb9351fa49db9b5847cf4d1f2a473414ad"}, +] [package.dependencies] certifi = "*" @@ -1545,6 +2282,10 @@ description = "Easily download, build, install, upgrade, and uninstall Python pa category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "setuptools-63.4.3-py3-none-any.whl", hash = "sha256:7f61f7e82647f77d4118eeaf43d64cbcd4d87e38af9611694d4866eb070cd10d"}, + {file = "setuptools-63.4.3.tar.gz", hash = "sha256:521c833d1e5e1ef0869940e7f486a83de7773b9f029010ad0c2fe35453a9dad9"}, +] [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] @@ -1558,6 +2299,10 @@ description = "Python 2 and 3 compatibility utilities" category = "main" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] [[package]] name = "sniffio" @@ -1566,6 +2311,10 @@ description = "Sniff out which async library your code is running under" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] [[package]] name = "sortedcontainers" @@ -1574,6 +2323,10 @@ description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" category = "main" optional = false python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] [[package]] name = "structlog" @@ -1582,6 +2335,10 @@ description = "Structured Logging for Python" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "structlog-22.1.0-py3-none-any.whl", hash = "sha256:760d37b8839bd4fe1747bed7b80f7f4de160078405f4b6a1db9270ccbfce6c30"}, + {file = "structlog-22.1.0.tar.gz", hash = "sha256:94b29b1d62b2659db154f67a9379ec1770183933d6115d21f21aa25cfc9a7393"}, +] [package.extras] dev = ["cogapp", "coverage[toml]", "freezegun (>=0.2.8)", "furo", "myst-parser", "pre-commit", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "rich", "simplejson", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "tomli", "twisted"] @@ -1595,6 +2352,10 @@ description = "Accurately separates a URL's subdomain, domain, and public suffix category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "tldextract-3.4.0-py3-none-any.whl", hash = "sha256:47aa4d8f1a4da79a44529c9a2ddc518663b25d371b805194ec5ce2a5f615ccd2"}, + {file = "tldextract-3.4.0.tar.gz", hash = "sha256:78aef13ac1459d519b457a03f1f74c1bf1c2808122a6bcc0e6840f81ba55ad73"}, +] [package.dependencies] filelock = ">=3.0.8" @@ -1609,6 +2370,10 @@ description = "A JIT implementation for Marshmallow to speed up dumping and load category = "main" optional = false python-versions = "*" +files = [ + {file = "toastedmarshmallow-0.2.6-py2.py3-none-any.whl", hash = "sha256:6f8ecbf287e9745a9b6804a69f001804c98547be9425f06281162b742c8bfd68"}, + {file = "toastedmarshmallow-0.2.6.tar.gz", hash = "sha256:15dee79cac691c0a1dc9df694b6e014d00d465b588f49b893c9ece27d09856a0"}, +] [package.dependencies] attrs = ">=17.1.0" @@ -1623,6 +2388,10 @@ description = "Python Library for Tom's Obvious, Minimal Language" category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] [[package]] name = "tomli" @@ -1631,6 +2400,10 @@ description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] [[package]] name = "trio" @@ -1639,6 +2412,10 @@ description = "A friendly Python library for async concurrency and I/O" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "trio-0.22.0-py3-none-any.whl", hash = "sha256:f1dd0780a89bfc880c7c7994519cb53f62aacb2c25ff487001c0052bd721cdf0"}, + {file = "trio-0.22.0.tar.gz", hash = "sha256:ce68f1c5400a47b137c5a4de72c7c901bd4e7a24fbdebfe9b41de8c6c04eaacf"}, +] [package.dependencies] async-generator = ">=1.9" @@ -1657,6 +2434,10 @@ description = "A re-implementation of the asyncio mainloop on top of Trio" category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "trio_asyncio-0.12.0-py3-none-any.whl", hash = "sha256:9bf678f83204ba33c395783681c69af563a84145fad2110a152a81a4a18ae7e4"}, + {file = "trio_asyncio-0.12.0.tar.gz", hash = "sha256:824be23b0c678c0df942816cdb57b92a8b94f264fffa89f04626b0ba2d009768"}, +] [package.dependencies] attrs = "*" @@ -1670,6 +2451,10 @@ description = "Static type checking support for Trio and related projects" category = "main" optional = false python-versions = "*" +files = [ + {file = "trio-typing-0.7.0.tar.gz", hash = "sha256:5bb2184de144c15f2cc252bba4fd167125758df7339c4f7bc40538940aefa3b9"}, + {file = "trio_typing-0.7.0-py3-none-any.whl", hash = "sha256:156ba760f444aa2f8af43f4459d462415fc297234feb27018e4e902bb62a122b"}, +] [package.dependencies] mypy-extensions = ">=0.4.2" @@ -1686,6 +2471,10 @@ description = "PostgreSQL client for Trio based on asyncpg" category = "main" optional = true python-versions = ">=3.6" +files = [ + {file = "triopg-0.6.0-py3-none-any.whl", hash = "sha256:a65147183c0992d0902f6acdeb2b177bb23efbff1ca971ee4f480d02c9cd5442"}, + {file = "triopg-0.6.0.tar.gz", hash = "sha256:ead3505aa702da02e4ec78710385cfa3c216747279d0ab4e6c37fff4236ff162"}, +] [package.dependencies] asyncpg = ">=0.15.0" @@ -1699,6 +2488,10 @@ description = "#1 quality TLS certs while you wait, for the discerning tester" category = "dev" optional = false python-versions = "*" +files = [ + {file = "trustme-0.9.0-py2.py3-none-any.whl", hash = "sha256:a6e53039cc43e70548ebd9a42ec1af5cba803a16d14321cd96352d2b4e010e04"}, + {file = "trustme-0.9.0.tar.gz", hash = "sha256:5e07b23d70ceed64f3bb36ae4b9abc52354c16c98d45ab037bee2b5fbffe586c"}, +] [package.dependencies] cryptography = "*" @@ -1711,6 +2504,10 @@ description = "Type annotations and code completion for awscrt" category = "dev" optional = false python-versions = ">=3.7,<4.0" +files = [ + {file = "types_awscrt-0.15.3-py3-none-any.whl", hash = "sha256:faa90585ef8f4e6e85fde17ad2c04604717a7978840416c92b7adddbf6fe5793"}, + {file = "types_awscrt-0.15.3.tar.gz", hash = "sha256:ff24dcbed0d1d27bc2565702af0a2ae5eb73223de87dfe3e4e1bf2eaf00a57ec"}, +] [[package]] name = "types-requests" @@ -1719,6 +2516,10 @@ description = "Typing stubs for requests" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-requests-2.28.11.5.tar.gz", hash = "sha256:a7df37cc6fb6187a84097da951f8e21d335448aa2501a6b0a39cbd1d7ca9ee2a"}, + {file = "types_requests-2.28.11.5-py3-none-any.whl", hash = "sha256:091d4a5a33c1b4f20d8b1b952aa8fa27a6e767c44c3cf65e56580df0b05fd8a9"}, +] [package.dependencies] types-urllib3 = "<1.27" @@ -1730,6 +2531,10 @@ description = "Type annotations and code completion for s3transfer" category = "dev" optional = false python-versions = ">=3.7,<4.0" +files = [ + {file = "types_s3transfer-0.6.0.post5-py3-none-any.whl", hash = "sha256:cfcbee11c16d60af3feb3dbffea3a85b32129235b562912dece310a45ae83a2c"}, + {file = "types_s3transfer-0.6.0.post5.tar.gz", hash = "sha256:2cf1e07cf4d1a5a2a68d89c654f45d9c3b678d39f7fe03a6f36903b6dbd3bcbc"}, +] [package.dependencies] types-awscrt = "*" @@ -1741,6 +2546,10 @@ description = "Typing stubs for urllib3" category = "dev" optional = false python-versions = "*" +files = [ + {file = "types-urllib3-1.26.25.1.tar.gz", hash = "sha256:a948584944b2412c9a74b9cf64f6c48caf8652cb88b38361316f6d15d8a184cd"}, + {file = "types_urllib3-1.26.25.1-py3-none-any.whl", hash = "sha256:f6422596cc9ee5fdf68f9d547f541096a20c2dcfd587e37c804c9ea720bf5cb2"}, +] [[package]] name = "typing-extensions" @@ -1749,6 +2558,10 @@ description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, +] [[package]] name = "urllib3" @@ -1757,6 +2570,10 @@ description = "HTTP library with thread-safe connection pooling, file post, and category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" +files = [ + {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, + {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, +] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] @@ -1770,6 +2587,10 @@ description = "The comprehensive WSGI web application library." category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "Werkzeug-2.2.2-py3-none-any.whl", hash = "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"}, + {file = "Werkzeug-2.2.2.tar.gz", hash = "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f"}, +] [package.dependencies] MarkupSafe = ">=2.1.1" @@ -1784,6 +2605,19 @@ description = "CFFI bindings for WinFSP" category = "main" optional = false python-versions = "*" +files = [ + {file = "winfspy-0.8.3-cp310-cp310-win32.whl", hash = "sha256:7c57fed1e537fb740dff0e4d0ddc11c650b68c22b3ebfe9e2640a03cd12f908c"}, + {file = "winfspy-0.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:ae87957ff05feaae0d35f4734c0176b815dd5c5e3e93f5961fcf5183c24ea6d3"}, + {file = "winfspy-0.8.3-cp36-cp36m-win32.whl", hash = "sha256:44674057f3e8d8488ee5f46f267c60b8784c02f3cbbffb2074a0b17da0a53351"}, + {file = "winfspy-0.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:b50ed00f4d1590d0a72b395e17ee68e1b6faa9c435fd905803d7236f45cb1717"}, + {file = "winfspy-0.8.3-cp37-cp37m-win32.whl", hash = "sha256:d6da076aa3192753e6b0782fe40e14683caab6da687c853d635737d7eed706d3"}, + {file = "winfspy-0.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:abce008b613f01a67bb0a792d89666391cb7c3f908998e32ed059d9538c83c5c"}, + {file = "winfspy-0.8.3-cp38-cp38-win32.whl", hash = "sha256:218d04705c1b67db546736cbd97cb77195be4c9ffc903f85b8eba2ecdd82a37d"}, + {file = "winfspy-0.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:9d5b83403ff1cb4591757ecebcfcd46a4a091784cda37e16546f38b01a4e63bb"}, + {file = "winfspy-0.8.3-cp39-cp39-win32.whl", hash = "sha256:fb472211e576c56e6f685fdaa15b3e19209fef91263f9257795e38e232c77291"}, + {file = "winfspy-0.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:0c42649860435cde704cda367f0775acc72cd1549f14b0fb14d73a242ae9e69e"}, + {file = "winfspy-0.8.3.tar.gz", hash = "sha256:836338c35a8810986ad66be88f592edd2960c6e50f58becb0b77256ce5e565ba"}, +] [package.dependencies] cffi = ">=1.0.0" @@ -1802,6 +2636,10 @@ description = "WebSockets state-machine based protocol implementation" category = "main" optional = false python-versions = ">=3.7.0" +files = [ + {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, + {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, +] [package.dependencies] h11 = ">=0.9.0,<1" @@ -1813,6 +2651,10 @@ description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = true python-versions = ">=3.7" +files = [ + {file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"}, + {file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"}, +] [package.extras] docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] @@ -1825,915 +2667,15 @@ description = "" category = "main" optional = true python-versions = "*" +files = [ + {file = "zxcvbn-4.4.28.tar.gz", hash = "sha256:151bd816817e645e9064c354b13544f85137ea3320ca3be1fb6873ea75ef7dc1"}, +] [extras] backend = ["jinja2", "quart-trio", "quart", "hypercorn", "triopg", "trio-asyncio", "boto3", "botocore", "python-swiftclient", "pbr"] core = ["packaging", "PyQt5", "pyqt5-sip", "qtrio", "qrcode", "fusepy", "winfspy", "zxcvbn", "psutil", "pypac"] [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "~3.9.0" -content-hash = "3c506ea3c58bc27b3b31e0d2de8e5c58b4cbc50826448133a75454e75889e9c3" - -[metadata.files] -aiofiles = [ - {file = "aiofiles-22.1.0-py3-none-any.whl", hash = "sha256:1142fa8e80dbae46bb6339573ad4c8c0841358f79c6eb50a493dceca14621bad"}, - {file = "aiofiles-22.1.0.tar.gz", hash = "sha256:9107f1ca0b2a5553987a94a3c9959fe5b491fdf731389aa5b7b1bd0733e32de6"}, -] -altgraph = [ - {file = "altgraph-0.17.3-py2.py3-none-any.whl", hash = "sha256:c8ac1ca6772207179ed8003ce7687757c04b0b71536f81e2ac5755c6226458fe"}, - {file = "altgraph-0.17.3.tar.gz", hash = "sha256:ad33358114df7c9416cdb8fa1eaa5852166c505118717021c6a8c7c7abbd03dd"}, -] -asn1crypto = [ - {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, - {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, -] -async-exit-stack = [ - {file = "async_exit_stack-1.0.1-py3-none-any.whl", hash = "sha256:9b43b17683b3438f428ef3bbec20689f5abbb052aa4b564c643397330adfaa99"}, - {file = "async_exit_stack-1.0.1.tar.gz", hash = "sha256:24de1ad6d0ff27be97c89d6709fa49bf20db179eaf1f4d2e6e9b4409b80e747d"}, -] -async-generator = [ - {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, - {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, -] -asyncpg = [ - {file = "asyncpg-0.26.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ed3880b3aec8bda90548218fe0914d251d641f798382eda39a17abfc4910af0"}, - {file = "asyncpg-0.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5bd99ee7a00e87df97b804f178f31086e88c8106aca9703b1d7be5078999e68"}, - {file = "asyncpg-0.26.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:868a71704262834065ca7113d80b1f679609e2df77d837747e3d92150dd5a39b"}, - {file = "asyncpg-0.26.0-cp310-cp310-win32.whl", hash = "sha256:838e4acd72da370ad07243898e886e93d3c0c9413f4444d600ba60a5cc206014"}, - {file = "asyncpg-0.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:a254d09a3a989cc1839ba2c34448b879cdd017b528a0cda142c92fbb6c13d957"}, - {file = "asyncpg-0.26.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3ecbe8ed3af4c739addbfbd78f7752866cce2c4e9cc3f953556e4960349ae360"}, - {file = "asyncpg-0.26.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ce7d8c0ab4639bbf872439eba86ef62dd030b245ad0e17c8c675d93d7a6b2d"}, - {file = "asyncpg-0.26.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7129bd809990fd119e8b2b9982e80be7712bb6041cd082be3e415e60e5e2e98f"}, - {file = "asyncpg-0.26.0-cp36-cp36m-win32.whl", hash = "sha256:03f44926fa7ff7ccd59e98f05c7e227e9de15332a7da5bbcef3654bf468ee597"}, - {file = "asyncpg-0.26.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b1f7b173af649b85126429e11a628d01a5b75973d2a55d64dba19ad8f0e9f904"}, - {file = "asyncpg-0.26.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efe056fd22fc6ed5c1ab353b6510808409566daac4e6f105e2043797f17b8dad"}, - {file = "asyncpg-0.26.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d96cf93e01df9fb03cef5f62346587805e6c0ca6f654c23b8d35315bdc69af59"}, - {file = "asyncpg-0.26.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:235205b60d4d014921f7b1cdca0e19669a9a8978f7606b3eb8237ca95f8e716e"}, - {file = "asyncpg-0.26.0-cp37-cp37m-win32.whl", hash = "sha256:0de408626cfc811ef04f372debfcdd5e4ab5aeb358f2ff14d1bdc246ed6272b5"}, - {file = "asyncpg-0.26.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f92d501bf213b16fabad4fbb0061398d2bceae30ddc228e7314c28dcc6641b79"}, - {file = "asyncpg-0.26.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9acb22a7b6bcca0d80982dce3d67f267d43e960544fb5dd934fd3abe20c48014"}, - {file = "asyncpg-0.26.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e550d8185f2c4725c1e8d3c555fe668b41bd092143012ddcc5343889e1c2a13d"}, - {file = "asyncpg-0.26.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:050e339694f8c5d9aebcf326ca26f6622ef23963a6a3a4f97aeefc743954afd5"}, - {file = "asyncpg-0.26.0-cp38-cp38-win32.whl", hash = "sha256:b0c3f39ebfac06848ba3f1e280cb1fada7cc1229538e3dad3146e8d1f9deb92a"}, - {file = "asyncpg-0.26.0-cp38-cp38-win_amd64.whl", hash = "sha256:49fc7220334cc31d14866a0b77a575d6a5945c0fa3bb67f17304e8b838e2a02b"}, - {file = "asyncpg-0.26.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d156e53b329e187e2dbfca8c28c999210045c45ef22a200b50de9b9e520c2694"}, - {file = "asyncpg-0.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b4051012ca75defa9a1dc6b78185ca58cdc3a247187eb76a6bcf55dfaa2fad4"}, - {file = "asyncpg-0.26.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d60f15a0ac18c54a6ca6507c28599c06e2e87a0901e7b548f15243d71905b18"}, - {file = "asyncpg-0.26.0-cp39-cp39-win32.whl", hash = "sha256:ede1a3a2c377fe12a3930f4b4dd5340e8b32929541d5db027a21816852723438"}, - {file = "asyncpg-0.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:8e1e79f0253cbd51fc43c4d0ce8804e46ee71f6c173fdc75606662ad18756b52"}, - {file = "asyncpg-0.26.0.tar.gz", hash = "sha256:77e684a24fee17ba3e487ca982d0259ed17bae1af68006f4cf284b23ba20ea2c"}, -] -attrs = [ - {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, - {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, -] -babel = [ - {file = "Babel-2.10.3-py3-none-any.whl", hash = "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"}, - {file = "Babel-2.10.3.tar.gz", hash = "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51"}, -] -bashlex = [ - {file = "bashlex-0.16-py2.py3-none-any.whl", hash = "sha256:ff89fc743ccdef978792784d74d698a9236a862939bb4af471c0c3faf92c21bb"}, - {file = "bashlex-0.16.tar.gz", hash = "sha256:dc6f017e49ce2d0fe30ad9f5206da9cd13ded073d365688c9fda525354e8c373"}, -] -black = [ - {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, - {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, - {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, - {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, - {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, - {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, - {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, - {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, - {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, - {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, - {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, - {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, - {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, - {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, - {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, - {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, - {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, - {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, - {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, - {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, - {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, -] -blinker = [ - {file = "blinker-1.5-py2.py3-none-any.whl", hash = "sha256:1eb563df6fdbc39eeddc177d953203f99f097e9bf0e2b8f9f3cf18b6ca425e36"}, - {file = "blinker-1.5.tar.gz", hash = "sha256:923e5e2f69c155f2cc42dafbbd70e16e3fde24d2d4aa2ab72fbe386238892462"}, -] -boto3 = [ - {file = "boto3-1.25.1-py3-none-any.whl", hash = "sha256:5684030fb1fa742c9bec33bee1a0829ff4b4bb2cdef40d9465969fdb55b501bc"}, - {file = "boto3-1.25.1.tar.gz", hash = "sha256:9517b1d517b024a259a116a0206ae4a471e2ffab57db1b41a3ce6e3f8042001a"}, -] -boto3-stubs = [ - {file = "boto3-stubs-1.26.21.tar.gz", hash = "sha256:98c706c79d9690ffd96cb2a92d6fe9ae7938c0376859234b3a09dec779fb75c9"}, - {file = "boto3_stubs-1.26.21-py3-none-any.whl", hash = "sha256:39d4cb0947b62bff4bdbe1c67158fd05799b8544bb4aa2ac9eaea88c857f7da8"}, -] -botocore = [ - {file = "botocore-1.28.1-py3-none-any.whl", hash = "sha256:e751045bee771d99d1baa06775df38511a5025cab6ceb2219a2a27cc2abd3ee5"}, - {file = "botocore-1.28.1.tar.gz", hash = "sha256:2ebaf48c9cd61ad5532ac639569837bce3e0470991c5f1bee9fe3ef7d0362c42"}, -] -botocore-stubs = [ - {file = "botocore_stubs-1.29.12-py3-none-any.whl", hash = "sha256:9e2e0e1357d95617b3471a2c2ab07a05bb564907f6b44300aed444a734d82a5a"}, - {file = "botocore_stubs-1.29.12.tar.gz", hash = "sha256:e050ae81d7f9db3880db5062bbc827c897c9f24486fe24f64f33d02ebad6ed84"}, -] -bracex = [ - {file = "bracex-2.3.post1-py3-none-any.whl", hash = "sha256:351b7f20d56fb9ea91f9b9e9e7664db466eb234188c175fd943f8f755c807e73"}, - {file = "bracex-2.3.post1.tar.gz", hash = "sha256:e7b23fc8b2cd06d3dec0692baabecb249dda94e06a617901ff03a6c56fd71693"}, -] -certifi = [ - {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, - {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, -] -cffi = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, -] -cibuildwheel = [ - {file = "cibuildwheel-2.10.0-py3-none-any.whl", hash = "sha256:8946086aaac43b7885ebbf11166acdafb5275612f20428e99488fef594b0ed6e"}, - {file = "cibuildwheel-2.10.0.tar.gz", hash = "sha256:3375f1f0cfb24a5b20941fc46059a7bdc983c28d725f7e0a255746544a8a4e44"}, -] -click = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] -colorama = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -coverage = [ - {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, - {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"}, - {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"}, - {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"}, - {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"}, - {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"}, - {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"}, - {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"}, - {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"}, - {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"}, - {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"}, - {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"}, - {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"}, - {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"}, - {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"}, - {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"}, - {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"}, - {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"}, - {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"}, - {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"}, - {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"}, - {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"}, - {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"}, - {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"}, - {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"}, - {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"}, - {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"}, - {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"}, -] -cryptography = [ - {file = "cryptography-38.0.3-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:984fe150f350a3c91e84de405fe49e688aa6092b3525f407a18b9646f6612320"}, - {file = "cryptography-38.0.3-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:ed7b00096790213e09eb11c97cc6e2b757f15f3d2f85833cd2d3ec3fe37c1722"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:bbf203f1a814007ce24bd4d51362991d5cb90ba0c177a9c08825f2cc304d871f"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554bec92ee7d1e9d10ded2f7e92a5d70c1f74ba9524947c0ba0c850c7b011828"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1b52c9e5f8aa2b802d48bd693190341fae201ea51c7a167d69fc48b60e8a959"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:728f2694fa743a996d7784a6194da430f197d5c58e2f4e278612b359f455e4a2"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dfb4f4dd568de1b6af9f4cda334adf7d72cf5bc052516e1b2608b683375dd95c"}, - {file = "cryptography-38.0.3-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5419a127426084933076132d317911e3c6eb77568a1ce23c3ac1e12d111e61e0"}, - {file = "cryptography-38.0.3-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:9b24bcff7853ed18a63cfb0c2b008936a9554af24af2fb146e16d8e1aed75748"}, - {file = "cryptography-38.0.3-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:25c1d1f19729fb09d42e06b4bf9895212292cb27bb50229f5aa64d039ab29146"}, - {file = "cryptography-38.0.3-cp36-abi3-win32.whl", hash = "sha256:7f836217000342d448e1c9a342e9163149e45d5b5eca76a30e84503a5a96cab0"}, - {file = "cryptography-38.0.3-cp36-abi3-win_amd64.whl", hash = "sha256:c46837ea467ed1efea562bbeb543994c2d1f6e800785bd5a2c98bc096f5cb220"}, - {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06fc3cc7b6f6cca87bd56ec80a580c88f1da5306f505876a71c8cfa7050257dd"}, - {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:65535bc550b70bd6271984d9863a37741352b4aad6fb1b3344a54e6950249b55"}, - {file = "cryptography-38.0.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5e89468fbd2fcd733b5899333bc54d0d06c80e04cd23d8c6f3e0542358c6060b"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6ab9516b85bebe7aa83f309bacc5f44a61eeb90d0b4ec125d2d003ce41932d36"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:068147f32fa662c81aebab95c74679b401b12b57494872886eb5c1139250ec5d"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:402852a0aea73833d982cabb6d0c3bb582c15483d29fb7085ef2c42bfa7e38d7"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b1b35d9d3a65542ed2e9d90115dfd16bbc027b3f07ee3304fc83580f26e43249"}, - {file = "cryptography-38.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:6addc3b6d593cd980989261dc1cce38263c76954d758c3c94de51f1e010c9a50"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:be243c7e2bfcf6cc4cb350c0d5cdf15ca6383bbcb2a8ef51d3c9411a9d4386f0"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78cf5eefac2b52c10398a42765bfa981ce2372cbc0457e6bf9658f41ec3c41d8"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:4e269dcd9b102c5a3d72be3c45d8ce20377b8076a43cbed6f660a1afe365e436"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8d41a46251bf0634e21fac50ffd643216ccecfaf3701a063257fe0b2be1b6548"}, - {file = "cryptography-38.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:785e4056b5a8b28f05a533fab69febf5004458e20dad7e2e13a3120d8ecec75a"}, - {file = "cryptography-38.0.3.tar.gz", hash = "sha256:bfbe6ee19615b07a98b1d2287d6a6073f734735b49ee45b11324d85efc4d5cbd"}, -] -decorator = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, -] -docutils = [ - {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, - {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, -] -dukpy = [ - {file = "dukpy-0.2.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:edd0862c34f085b60f17fc214c19ab6e38166fd08c85506aeaf370449b3ca20f"}, - {file = "dukpy-0.2.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99e5a90e01cf60a52bafed04d2099ab91b853279429c39a6010fcb264615679a"}, - {file = "dukpy-0.2.3-cp27-cp27m-win32.whl", hash = "sha256:267ddd5e4e88903467d3b0940b26e248739f2c870dde1365749fe39f24b76ebe"}, - {file = "dukpy-0.2.3-cp27-cp27m-win_amd64.whl", hash = "sha256:26af4776043578cd5a90b723f97c862172dd0c03be90db462c4a50526b370b70"}, - {file = "dukpy-0.2.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9a89548ff0bd15e415755bc034f76eb6220e8e0d5b9f9d476e6c7b7edc9470b7"}, - {file = "dukpy-0.2.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:906ec0fa1933fdb0df49e2de286ea8d64f14f7a1ed23705057b2f8eb73c5a036"}, - {file = "dukpy-0.2.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0658ecda9e85499c2a3236f59837aab27fbef19b75544f1d1f33704fa43e52e7"}, - {file = "dukpy-0.2.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:39739d135786d14b430c1d0a82b821d731dfec31369d4a315e1929ca37c48d72"}, - {file = "dukpy-0.2.3-cp35-cp35m-win32.whl", hash = "sha256:f90e133688e2d2d010c909b7a0e8d2dff73b7c08622480dcb6f8d81169a48235"}, - {file = "dukpy-0.2.3-cp35-cp35m-win_amd64.whl", hash = "sha256:e9512519d39d048e64c89a876e3d4b569862e9bacdb9294046b13385b92fe657"}, - {file = "dukpy-0.2.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9aa761142872407d39da88fdbfcc0cc77c6a91b25c9cb9547b564c3e699137b6"}, - {file = "dukpy-0.2.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5b3589426d20dc46d6758754a42f359ad265f02a508de9978065de60626249dd"}, - {file = "dukpy-0.2.3-cp36-cp36m-win32.whl", hash = "sha256:cf8f702599f3abb42a1bc64df2d7a63115226042feff57b89d8f0fd3d5cb2592"}, - {file = "dukpy-0.2.3-cp36-cp36m-win_amd64.whl", hash = "sha256:494bccfe65c0db95c498584a99052b4039c28f171c901cf609dadf303c097d62"}, - {file = "dukpy-0.2.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:061f84e9786f18e7bc63c78afcddec7287ebacae35b4a95c4c49fac0146b6f0d"}, - {file = "dukpy-0.2.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:79f1dfe1276b3b2cef6f353df8889da45cab4cbae88c1b0c2f8895bc68efb345"}, - {file = "dukpy-0.2.3-cp37-cp37m-win32.whl", hash = "sha256:123c39095d5b282f2fdebe08088572688c67ce7d876129eb4bb7e1262650a4af"}, - {file = "dukpy-0.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:929c5fe7fc4c0aff25c8bf6284e9fb3a3ac74430104c2d260858b76e290013fe"}, - {file = "dukpy-0.2.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3395f84d793f1be55f250705fd1f4562c58718dde0304ae21b001dc0332e020a"}, - {file = "dukpy-0.2.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9499ec53247cc0e2453d2be0586d9fa6803b751961d05bc947946341ecea6560"}, - {file = "dukpy-0.2.3-cp38-cp38-win32.whl", hash = "sha256:ff245b01239fbb25b4a0b9bf30d3b4499648ce52bba981fe2cbac868052354fe"}, - {file = "dukpy-0.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:770c0795cbe5c41b604b12f372d2905587035f2f83489d2e1c36b88d50f9b175"}, - {file = "dukpy-0.2.3.tar.gz", hash = "sha256:cc8dd158326f95231d320da80be6e6a1d72bbaad9de2569eaffb6af736f45e6b"}, -] -editorconfig-checker = [ - {file = "editorconfig-checker-2.4.0.tar.gz", hash = "sha256:1f7839df7d967d95f0cf2ed6a42a0f456c65072d2ffcff1fedc0eac62ed236ea"}, -] -exceptiongroup = [ - {file = "exceptiongroup-1.0.0rc9-py3-none-any.whl", hash = "sha256:2e3c3fc1538a094aab74fad52d6c33fc94de3dfee3ee01f187c0e0c72aec5337"}, - {file = "exceptiongroup-1.0.0rc9.tar.gz", hash = "sha256:9086a4a21ef9b31c72181c77c040a074ba0889ee56a7b289ff0afb0d97655f96"}, -] -execnet = [ - {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, - {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, -] -filelock = [ - {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, - {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, -] -fusepy = [ - {file = "fusepy-3.0.1.tar.gz", hash = "sha256:72ff783ec2f43de3ab394e3f7457605bf04c8cf288a2f4068b4cde141d4ee6bd"}, -] -future = [ - {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, -] -h11 = [ - {file = "h11-0.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"}, - {file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"}, -] -h2 = [ - {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, - {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, -] -hpack = [ - {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, - {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, -] -hypercorn = [ - {file = "Hypercorn-0.13.2-py3-none-any.whl", hash = "sha256:ca18f91ab3fa823cbe9e949738f9f2cc07027cd647c80d8f93e4b1a2a175f112"}, - {file = "Hypercorn-0.13.2.tar.gz", hash = "sha256:6307be5cbdf6ba411967d4661202dc4f79bd511b5d318bc4eed88b09418427f8"}, -] -hyperframe = [ - {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, - {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, -] -hypothesis = [ - {file = "hypothesis-6.56.3-py3-none-any.whl", hash = "sha256:802d236d03dbd54e0e1c55c0daa2ec41aeaadc87a4dcbb41421b78bf3f7a7789"}, - {file = "hypothesis-6.56.3.tar.gz", hash = "sha256:15dae5d993339aefa57e00f5cb5a5817ff300eeb661d96d1c9d094eb62b04c9a"}, -] -hypothesis-trio = [ - {file = "hypothesis-trio-0.6.0.tar.gz", hash = "sha256:d7ab108ac99758011b20f2448f1b1269375c68c1ffda9e4468600a4975ff955c"}, - {file = "hypothesis_trio-0.6.0-py3-none-any.whl", hash = "sha256:3ac261dc6fcf3862d7d57ffa52d294539f8d807ac9483d58a8060df3c9e856fc"}, -] -idna = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] -importlib-metadata = [ - {file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"}, - {file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"}, -] -iniconfig = [ - {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, - {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, -] -itsdangerous = [ - {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, - {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, -] -jinja2 = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, -] -jmespath = [ - {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, - {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, -] -macholib = [ - {file = "macholib-1.16.2-py2.py3-none-any.whl", hash = "sha256:44c40f2cd7d6726af8fa6fe22549178d3a4dfecc35a9cd15ea916d9c83a688e0"}, - {file = "macholib-1.16.2.tar.gz", hash = "sha256:557bbfa1bb255c20e9abafe7ed6cd8046b48d9525db2f9b77d3122a63a2a8bf8"}, -] -markupsafe = [ - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, - {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, -] -maturin = [ - {file = "maturin-0.13.7-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:bc58b0266a4c124f9afd69a987ac324ff35c0d963b41073ed64a32f94c226d5a"}, - {file = "maturin-0.13.7-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:424d53adc9684167cf89829275fe5072331a197de0ac08e7a893f9283c7df213"}, - {file = "maturin-0.13.7-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:3137876c338eb7e551ba44a609b5f02d02454d1b3a8677ad6bf2121c5a92b2b7"}, - {file = "maturin-0.13.7-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:a96f1b3ede71c0f76b8c7cfac18a9eec90174bdf434fa9aeff491be9a7ca5179"}, - {file = "maturin-0.13.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:0b6ac1219a809155057fd1f358f7ece03c3abd2e2991832ce5146825a9fa4160"}, - {file = "maturin-0.13.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:3c36f429adc3a8af8de9838399750742a86053f0031a953b48ee92932120dc0c"}, - {file = "maturin-0.13.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:bb3a2830d64ae6a324571f694475b91111e827bc0ccc60a0c47f4fb596a46bd8"}, - {file = "maturin-0.13.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:794f58d3103449f8cd8ab5f36fd05c31b8d8de3643cd0e3720fd5dc3c328dd5c"}, - {file = "maturin-0.13.7-py3-none-win32.whl", hash = "sha256:63586eb286866264ec62d29df6ab955360de6226128f67d14623ffe1a12d4963"}, - {file = "maturin-0.13.7-py3-none-win_amd64.whl", hash = "sha256:f50d62aca567fdbbb929771794f3c5c78048ef0efa4af7d83ed472a8b8d26454"}, - {file = "maturin-0.13.7-py3-none-win_arm64.whl", hash = "sha256:8c6225e7eba2885a0cd82a6cf898e74bb720796a5744e0450f3b1340d1ca97af"}, - {file = "maturin-0.13.7.tar.gz", hash = "sha256:c0a77aa0c57f945649ca711c806203a1b6888ad49c2b8b85196ffdcf0421db77"}, -] -msgpack = [ - {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250"}, - {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88"}, - {file = "msgpack-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467"}, - {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6"}, - {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa"}, - {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6"}, - {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba"}, - {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e"}, - {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db"}, - {file = "msgpack-1.0.4-cp310-cp310-win32.whl", hash = "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef"}, - {file = "msgpack-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075"}, - {file = "msgpack-1.0.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52"}, - {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9"}, - {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9"}, - {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08"}, - {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8"}, - {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6"}, - {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae"}, - {file = "msgpack-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6"}, - {file = "msgpack-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661"}, - {file = "msgpack-1.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c"}, - {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0"}, - {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227"}, - {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff"}, - {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd"}, - {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e"}, - {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236"}, - {file = "msgpack-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44"}, - {file = "msgpack-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1"}, - {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d"}, - {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab"}, - {file = "msgpack-1.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb"}, - {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9"}, - {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e"}, - {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1"}, - {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e"}, - {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43"}, - {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243"}, - {file = "msgpack-1.0.4-cp38-cp38-win32.whl", hash = "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2"}, - {file = "msgpack-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6"}, - {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae"}, - {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55"}, - {file = "msgpack-1.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da"}, - {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f"}, - {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92"}, - {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f"}, - {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624"}, - {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8"}, - {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae"}, - {file = "msgpack-1.0.4-cp39-cp39-win32.whl", hash = "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c"}, - {file = "msgpack-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce"}, - {file = "msgpack-1.0.4.tar.gz", hash = "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f"}, -] -mypy = [ - {file = "mypy-0.982-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5085e6f442003fa915aeb0a46d4da58128da69325d8213b4b35cc7054090aed5"}, - {file = "mypy-0.982-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:41fd1cf9bc0e1c19b9af13a6580ccb66c381a5ee2cf63ee5ebab747a4badeba3"}, - {file = "mypy-0.982-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f793e3dd95e166b66d50e7b63e69e58e88643d80a3dcc3bcd81368e0478b089c"}, - {file = "mypy-0.982-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86ebe67adf4d021b28c3f547da6aa2cce660b57f0432617af2cca932d4d378a6"}, - {file = "mypy-0.982-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:175f292f649a3af7082fe36620369ffc4661a71005aa9f8297ea473df5772046"}, - {file = "mypy-0.982-cp310-cp310-win_amd64.whl", hash = "sha256:8ee8c2472e96beb1045e9081de8e92f295b89ac10c4109afdf3a23ad6e644f3e"}, - {file = "mypy-0.982-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58f27ebafe726a8e5ccb58d896451dd9a662a511a3188ff6a8a6a919142ecc20"}, - {file = "mypy-0.982-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6af646bd46f10d53834a8e8983e130e47d8ab2d4b7a97363e35b24e1d588947"}, - {file = "mypy-0.982-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7aeaa763c7ab86d5b66ff27f68493d672e44c8099af636d433a7f3fa5596d40"}, - {file = "mypy-0.982-cp37-cp37m-win_amd64.whl", hash = "sha256:724d36be56444f569c20a629d1d4ee0cb0ad666078d59bb84f8f887952511ca1"}, - {file = "mypy-0.982-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:14d53cdd4cf93765aa747a7399f0961a365bcddf7855d9cef6306fa41de01c24"}, - {file = "mypy-0.982-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26ae64555d480ad4b32a267d10cab7aec92ff44de35a7cd95b2b7cb8e64ebe3e"}, - {file = "mypy-0.982-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6389af3e204975d6658de4fb8ac16f58c14e1bacc6142fee86d1b5b26aa52bda"}, - {file = "mypy-0.982-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b35ce03a289480d6544aac85fa3674f493f323d80ea7226410ed065cd46f206"}, - {file = "mypy-0.982-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c6e564f035d25c99fd2b863e13049744d96bd1947e3d3d2f16f5828864506763"}, - {file = "mypy-0.982-cp38-cp38-win_amd64.whl", hash = "sha256:cebca7fd333f90b61b3ef7f217ff75ce2e287482206ef4a8b18f32b49927b1a2"}, - {file = "mypy-0.982-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a705a93670c8b74769496280d2fe6cd59961506c64f329bb179970ff1d24f9f8"}, - {file = "mypy-0.982-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75838c649290d83a2b83a88288c1eb60fe7a05b36d46cbea9d22efc790002146"}, - {file = "mypy-0.982-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:91781eff1f3f2607519c8b0e8518aad8498af1419e8442d5d0afb108059881fc"}, - {file = "mypy-0.982-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa97b9ddd1dd9901a22a879491dbb951b5dec75c3b90032e2baa7336777363b"}, - {file = "mypy-0.982-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a692a8e7d07abe5f4b2dd32d731812a0175626a90a223d4b58f10f458747dd8a"}, - {file = "mypy-0.982-cp39-cp39-win_amd64.whl", hash = "sha256:eb7a068e503be3543c4bd329c994103874fa543c1727ba5288393c21d912d795"}, - {file = "mypy-0.982-py3-none-any.whl", hash = "sha256:1021c241e8b6e1ca5a47e4d52601274ac078a89845cfde66c6d5f769819ffa1d"}, - {file = "mypy-0.982.tar.gz", hash = "sha256:85f7a343542dc8b1ed0a888cdd34dca56462654ef23aa673907305b260b3d746"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -oscrypto = [ - {file = "oscrypto-1.3.0-py2.py3-none-any.whl", hash = "sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085"}, - {file = "oscrypto-1.3.0.tar.gz", hash = "sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4"}, -] -outcome = [ - {file = "outcome-1.2.0-py2.py3-none-any.whl", hash = "sha256:c4ab89a56575d6d38a05aa16daeaa333109c1f96167aba8901ab18b6b5e0f7f5"}, - {file = "outcome-1.2.0.tar.gz", hash = "sha256:6f82bd3de45da303cf1f771ecafa1633750a358436a8bb60e06a1ceb745d2672"}, -] -packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, -] -pathspec = [ - {file = "pathspec-0.10.1-py3-none-any.whl", hash = "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93"}, - {file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"}, -] -pbr = [ - {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, - {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, -] -pefile = [ - {file = "pefile-2022.5.30.tar.gz", hash = "sha256:a5488a3dd1fd021ce33f969780b88fe0f7eebb76eb20996d7318f307612a045b"}, -] -platformdirs = [ - {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, - {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, -] -pluggy = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, -] -poetry-lock-package = [ - {file = "poetry-lock-package-0.4.5.tar.gz", hash = "sha256:a74a4916cc53ebbfd3b3575b73d0e93bac74b75ff2d74f92a24e7a8938fc20f2"}, - {file = "poetry_lock_package-0.4.5-py3-none-any.whl", hash = "sha256:5b8ae966ec8c760a69d38bde6887501d594b467e00902dd341328cd8079ccaee"}, -] -priority = [ - {file = "priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa"}, - {file = "priority-2.0.0.tar.gz", hash = "sha256:c965d54f1b8d0d0b19479db3924c7c36cf672dbf2aec92d43fbdaf4492ba18c0"}, -] -psutil = [ - {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, - {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, - {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"}, - {file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"}, - {file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"}, - {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"}, - {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"}, - {file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"}, - {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"}, - {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"}, - {file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"}, - {file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"}, - {file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"}, - {file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"}, -] -pycparser = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] -pyinstaller = [ - {file = "pyinstaller-5.6.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:0465edb7a5b2bc74ac983d419fd980fd2e4c7d49f4c013edd4befb6ca70d3c2b"}, - {file = "pyinstaller-5.6.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:556750250bba85cf7ede168994fe70fcdeeba8d22f51eaedfd94b3efb6faa6ce"}, - {file = "pyinstaller-5.6.1-py3-none-manylinux2014_i686.whl", hash = "sha256:2abb74b008f01a8d9b54c27ea51aa6d59ea6137d507de9d580f79b934e0ca7b8"}, - {file = "pyinstaller-5.6.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:bb3faba1a29686e1c2d71a939bc6d1a57ca218d6968f43620591df42058635e0"}, - {file = "pyinstaller-5.6.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:b8dc59b00bc09053ed0476b47423373fafb8f4d57618e9eff7047cda8942e1c4"}, - {file = "pyinstaller-5.6.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:14a0bb008966ba074e173f94b5bffd78a4d84e4a21fafc63c1b72851a40a918d"}, - {file = "pyinstaller-5.6.1-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:8c423556f0aac7651cda813db0d215c36c51717c4079e407136a4d9f730d38b0"}, - {file = "pyinstaller-5.6.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a64a5472ee36f63e773be63535817b6d8aea1c1cf9acd18858c22c66fe575043"}, - {file = "pyinstaller-5.6.1-py3-none-win32.whl", hash = "sha256:fc734eb91e08c75fc7505170d765a49d781dad9e49dd641ebe4f8a82782f0be2"}, - {file = "pyinstaller-5.6.1-py3-none-win_amd64.whl", hash = "sha256:ec9d9491681ac55e369a5226833694bf299ddeaeab6df4ef9d44758d4342f10a"}, - {file = "pyinstaller-5.6.1.tar.gz", hash = "sha256:a7fac3fa8f75bce2839e0ab910baf0e935ff2b5f327c32aedade563e1b610967"}, -] -pyinstaller-hooks-contrib = [ - {file = "pyinstaller-hooks-contrib-2022.10.tar.gz", hash = "sha256:e5edd4094175e78c178ef987b61be19efff6caa23d266ade456fc753e847f62e"}, - {file = "pyinstaller_hooks_contrib-2022.10-py2.py3-none-any.whl", hash = "sha256:d1dd6ea059dc30e77813cc12a5efa8b1d228e7da8f5b884fe11775f946db1784"}, -] -pynacl = [ - {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, - {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, - {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, - {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, - {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, -] -pyobjc-core = [ - {file = "pyobjc-core-8.5.1.tar.gz", hash = "sha256:f8592a12de076c27006700c4a46164478564fa33d7da41e7cbdd0a3bf9ddbccf"}, - {file = "pyobjc_core-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b62dcf987cc511188fc2aa5b4d3b9fd895361ea4984380463497ce4b0752ddf4"}, - {file = "pyobjc_core-8.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0accc653501a655f66c13f149a1d3d30e6cb65824edf852f7960a00c4f930d5b"}, - {file = "pyobjc_core-8.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f82b32affc898e9e5af041c1cecde2c99f2ce160b87df77f678c99f1550a4655"}, - {file = "pyobjc_core-8.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f7b2f6b6f3caeb882c658fe0c7098be2e8b79893d84daa8e636cb3e58a07df00"}, - {file = "pyobjc_core-8.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:872c0202c911a5a2f1269261c168e36569f6ddac17e5d854ac19e581726570cc"}, - {file = "pyobjc_core-8.5.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:21f92e231a4bae7f2d160d065f5afbf5e859a1e37f29d34ac12592205fc8c108"}, - {file = "pyobjc_core-8.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:315334dd09781129af6a39641248891c4caa57043901750b0139c6614ce84ec0"}, -] -pyobjc-framework-cocoa = [ - {file = "pyobjc-framework-Cocoa-8.5.1.tar.gz", hash = "sha256:9a3de5cdb4644e85daf53f2ed912ef6c16ea5804a9e65552eafe62c2e139eb8c"}, - {file = "pyobjc_framework_Cocoa-8.5.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa572acc2628488a47be8d19f4701fc96fce7377cc4da18316e1e08c3918521a"}, - {file = "pyobjc_framework_Cocoa-8.5.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cb3ae21c8d81b7f02a891088c623cef61bca89bd671eff58c632d2f926b649f3"}, - {file = "pyobjc_framework_Cocoa-8.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:88f08f5bd94c66d373d8413c1d08218aff4cff0b586e0cc4249b2284023e7577"}, - {file = "pyobjc_framework_Cocoa-8.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:063683b57e4bd88cb0f9631ae65d25ec4eecf427d2fe8d0c578f88da9c896f3f"}, - {file = "pyobjc_framework_Cocoa-8.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f8806ddfac40620fb27f185d0f8937e69e330617319ecc2eccf6b9c8451bdd1"}, - {file = "pyobjc_framework_Cocoa-8.5.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:7733a9a201df9e0cc2a0cf7bf54d76bd7981cba9b599353b243e3e0c9eefec10"}, - {file = "pyobjc_framework_Cocoa-8.5.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f0ab227f99d3e25dd3db73f8cde0999914a5f0dd6a08600349d25f95eaa0da63"}, -] -pyobjc-framework-systemconfiguration = [ - {file = "pyobjc-framework-SystemConfiguration-8.5.1.tar.gz", hash = "sha256:f0c75fda3498d296e10a673700032ae0562e4c24b1f41c6290751edb939f84b5"}, - {file = "pyobjc_framework_SystemConfiguration-8.5.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:e499ddcdf02b8cb9cdf207ea4c09c4bde2cc891c01f11ffd4fc040d658a1fd4d"}, - {file = "pyobjc_framework_SystemConfiguration-8.5.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:bbd56a3a6534ae3de62ecbc3551c8e4d6861406369c2e7d96fb6ff2158491f08"}, - {file = "pyobjc_framework_SystemConfiguration-8.5.1-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:4a373c010df56cdf4b620c7f706fb7807a50d60ae12f2547ee0e8dae0616986b"}, -] -pypac = [ - {file = "PyPAC-0.16.0-py2.py3-none-any.whl", hash = "sha256:921630e95e596050844e299d525df030bb39430ced18001f3960409e4e0cb3b1"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -pyqt5 = [ - {file = "PyQt5-5.15.7-cp37-abi3-macosx_10_13_x86_64.whl", hash = "sha256:1a793748c60d5aff3850b7abf84d47c1d41edb11231b7d7c16bef602c36be643"}, - {file = "PyQt5-5.15.7-cp37-abi3-manylinux1_x86_64.whl", hash = "sha256:e319c9d8639e0729235c1b09c99afdadad96fa3dbd8392ab561b5ab5946ee6ef"}, - {file = "PyQt5-5.15.7-cp37-abi3-win32.whl", hash = "sha256:08694f0a4c7d4f3d36b2311b1920e6283240ad3b7c09b515e08262e195dcdf37"}, - {file = "PyQt5-5.15.7-cp37-abi3-win_amd64.whl", hash = "sha256:232fe5b135a095cbd024cf341d928fc672c963f88e6a52b0c605be8177c2fdb5"}, - {file = "PyQt5-5.15.7.tar.gz", hash = "sha256:755121a52b3a08cb07275c10ebb96576d36e320e572591db16cfdbc558101594"}, -] -pyqt5-qt5 = [ - {file = "PyQt5_Qt5-5.15.2-py3-none-macosx_10_13_intel.whl", hash = "sha256:76980cd3d7ae87e3c7a33bfebfaee84448fd650bad6840471d6cae199b56e154"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:1988f364ec8caf87a6ee5d5a3a5210d57539988bf8e84714c7d60972692e2f4a"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-win32.whl", hash = "sha256:9cc7a768b1921f4b982ebc00a318ccb38578e44e45316c7a4a850e953e1dd327"}, - {file = "PyQt5_Qt5-5.15.2-py3-none-win_amd64.whl", hash = "sha256:750b78e4dba6bdf1607febedc08738e318ea09e9b10aea9ff0d73073f11f6962"}, -] -pyqt5-sip = [ - {file = "PyQt5_sip-12.11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f1f9e312ff8284d6dfebc5366f6f7d103f84eec23a4da0be0482403933e68660"}, - {file = "PyQt5_sip-12.11.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:4031547dfb679be309094bfa79254f5badc5ddbe66b9ad38e319d84a7d612443"}, - {file = "PyQt5_sip-12.11.0-cp310-cp310-win32.whl", hash = "sha256:ad21ca0ee8cae2a41b61fc04949dccfab6fe008749627d94e8c7078cb7a73af1"}, - {file = "PyQt5_sip-12.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:3126c84568ab341c12e46ded2230f62a9a78752a70fdab13713f89a71cd44f73"}, - {file = "PyQt5_sip-12.11.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bd733667098cac70e89279d9c239106d543fb480def62a44e6366ccb8f68510b"}, - {file = "PyQt5_sip-12.11.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec1d8ce50be76c5c1d1c86c6dc0ccacc2446172dde98b663a17871f532f9bd44"}, - {file = "PyQt5_sip-12.11.0-cp311-cp311-win32.whl", hash = "sha256:43dfe6dd409e713edeb67019b85419a7a0dc9923bfc451d6cf3778471c122532"}, - {file = "PyQt5_sip-12.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:afa4ffffc54e306669bf2b66ea37abbc56c5cdda4f3f474d20324e3634302b12"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0f77655c62ec91d47c2c99143f248624d44dd2d8a12d016e7c020508ad418aca"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ec5e9ef78852e1f96f86d7e15c9215878422b83dde36d44f1539a3062942f19c"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-win32.whl", hash = "sha256:d12b81c3a08abf7657a2ebc7d3649852a1f327eb2146ebadf45930486d32e920"}, - {file = "PyQt5_sip-12.11.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b69a1911f768b489846335e31e49eb34795c6b5a038ca24d894d751e3b0b44da"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51e377789d59196213eddf458e6927f33ba9d217b614d17d20df16c9a8b2c41c"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4e5c1559311515291ea0ab0635529f14536954e3b973a7c7890ab7e4de1c2c23"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-win32.whl", hash = "sha256:9bca450c5306890cb002fe36bbca18f979dd9e5b810b766dce8e3ce5e66ba795"}, - {file = "PyQt5_sip-12.11.0-cp38-cp38-win_amd64.whl", hash = "sha256:f6b72035da4e8fecbb0bc4a972e30a5674a9ad5608dbddaa517e983782dbf3bf"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9356260d4feb60dbac0ab66f8a791a0d2cda1bf98c9dec8e575904a045fbf7c5"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:205f3e1b3eea3597d8e878936c1a06e04bd23a59e8b179ee806465d72eea3071"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-win32.whl", hash = "sha256:686071be054e5be6ca5aaaef7960931d4ba917277e839e2e978c7cbe3f43bb6e"}, - {file = "PyQt5_sip-12.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:42320e7a94b1085ed85d49794ed4ccfe86f1cae80b44a894db908a8aba2bc60e"}, - {file = "PyQt5_sip-12.11.0.tar.gz", hash = "sha256:b4710fd85b57edef716cc55fae45bfd5bfac6fc7ba91036f1dcc3f331ca0eb39"}, -] -pyqt5-stubs = [ - {file = "PyQt5-stubs-5.15.6.0.tar.gz", hash = "sha256:91270ac23ebf38a1dc04cd97aa852cd08af82dc839100e5395af1447e3e99707"}, - {file = "PyQt5_stubs-5.15.6.0-py3-none-any.whl", hash = "sha256:7fb8177c72489a8911f021b7bd7c33f12c87f6dba92dcef3fdcdb5d9400f0f3f"}, -] -pytest = [ - {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, - {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, -] -pytest-cov = [ - {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"}, - {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"}, -] -pytest-qt = [ - {file = "pytest-qt-4.2.0.tar.gz", hash = "sha256:00a17b586dd530b6d7a9399923a40489ca4a9a309719011175f55dc6b5dc8f41"}, - {file = "pytest_qt-4.2.0-py2.py3-none-any.whl", hash = "sha256:a7659960a1ab2af8fc944655a157ff45d714b80ed7a6af96a4b5bb99ecf40a22"}, -] -pytest-rerunfailures = [ - {file = "pytest-rerunfailures-10.2.tar.gz", hash = "sha256:9e1e1bad51e07642c5bbab809fc1d4ec8eebcb7de86f90f1a26e6ef9de446697"}, - {file = "pytest_rerunfailures-10.2-py3-none-any.whl", hash = "sha256:d31d8e828dfd39363ad99cd390187bf506c7a433a89f15c3126c7d16ab723fe2"}, -] -pytest-trio = [ - {file = "pytest-trio-0.8.0.tar.gz", hash = "sha256:8363db6336a79e6c53375a2123a41ddbeccc4aa93f93788651641789a56fb52e"}, - {file = "pytest_trio-0.8.0-py3-none-any.whl", hash = "sha256:e6a7e7351ae3e8ec3f4564d30ee77d1ec66e1df611226e5618dbb32f9545c841"}, -] -pytest-xdist = [ - {file = "pytest-xdist-3.1.0.tar.gz", hash = "sha256:40fdb8f3544921c5dfcd486ac080ce22870e71d82ced6d2e78fa97c2addd480c"}, - {file = "pytest_xdist-3.1.0-py3-none-any.whl", hash = "sha256:70a76f191d8a1d2d6be69fc440cdf85f3e4c03c08b520fd5dc5d338d6cf07d89"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] -python-swiftclient = [ - {file = "python-swiftclient-4.1.0.tar.gz", hash = "sha256:f82298e4a48f7cbdd680f2638c85d1ca7ae1a76edbe30036d21b4cd7a29c09eb"}, - {file = "python_swiftclient-4.1.0-py3-none-any.whl", hash = "sha256:4268219e158cd72c0b0751a6f27240da4eea7827485db765f5df9542da4cf144"}, -] -pytz = [ - {file = "pytz-2022.5-py2.py3-none-any.whl", hash = "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22"}, - {file = "pytz-2022.5.tar.gz", hash = "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914"}, -] -pywin32 = [ - {file = "pywin32-304-cp310-cp310-win32.whl", hash = "sha256:3c7bacf5e24298c86314f03fa20e16558a4e4138fc34615d7de4070c23e65af3"}, - {file = "pywin32-304-cp310-cp310-win_amd64.whl", hash = "sha256:4f32145913a2447736dad62495199a8e280a77a0ca662daa2332acf849f0be48"}, - {file = "pywin32-304-cp310-cp310-win_arm64.whl", hash = "sha256:d3ee45adff48e0551d1aa60d2ec066fec006083b791f5c3527c40cd8aefac71f"}, - {file = "pywin32-304-cp311-cp311-win32.whl", hash = "sha256:30c53d6ce44c12a316a06c153ea74152d3b1342610f1b99d40ba2795e5af0269"}, - {file = "pywin32-304-cp311-cp311-win_amd64.whl", hash = "sha256:7ffa0c0fa4ae4077e8b8aa73800540ef8c24530057768c3ac57c609f99a14fd4"}, - {file = "pywin32-304-cp311-cp311-win_arm64.whl", hash = "sha256:cbbe34dad39bdbaa2889a424d28752f1b4971939b14b1bb48cbf0182a3bcfc43"}, - {file = "pywin32-304-cp36-cp36m-win32.whl", hash = "sha256:be253e7b14bc601718f014d2832e4c18a5b023cbe72db826da63df76b77507a1"}, - {file = "pywin32-304-cp36-cp36m-win_amd64.whl", hash = "sha256:de9827c23321dcf43d2f288f09f3b6d772fee11e809015bdae9e69fe13213988"}, - {file = "pywin32-304-cp37-cp37m-win32.whl", hash = "sha256:f64c0377cf01b61bd5e76c25e1480ca8ab3b73f0c4add50538d332afdf8f69c5"}, - {file = "pywin32-304-cp37-cp37m-win_amd64.whl", hash = "sha256:bb2ea2aa81e96eee6a6b79d87e1d1648d3f8b87f9a64499e0b92b30d141e76df"}, - {file = "pywin32-304-cp38-cp38-win32.whl", hash = "sha256:94037b5259701988954931333aafd39cf897e990852115656b014ce72e052e96"}, - {file = "pywin32-304-cp38-cp38-win_amd64.whl", hash = "sha256:ead865a2e179b30fb717831f73cf4373401fc62fbc3455a0889a7ddac848f83e"}, - {file = "pywin32-304-cp39-cp39-win32.whl", hash = "sha256:25746d841201fd9f96b648a248f731c1dec851c9a08b8e33da8b56148e4c65cc"}, - {file = "pywin32-304-cp39-cp39-win_amd64.whl", hash = "sha256:d24a3382f013b21aa24a5cfbfad5a2cd9926610c0affde3e8ab5b3d7dbcf4ac9"}, -] -pywin32-ctypes = [ - {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, - {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, -] -qrcode = [ - {file = "qrcode-7.3.1.tar.gz", hash = "sha256:375a6ff240ca9bd41adc070428b5dfc1dcfbb0f2507f1ac848f6cded38956578"}, -] -qtrio = [ - {file = "qtrio-0.6.0-py3-none-any.whl", hash = "sha256:25f48b1debc1ad44ada6269f10dcffabb9e699d56064b443f36d428c83cccdcb"}, - {file = "qtrio-0.6.0.tar.gz", hash = "sha256:1435eb11fb8e06fed28815aad0cd614f22f9a5c94855d82fa7a4abb69a5b54e4"}, -] -qts = [ - {file = "qts-0.3-py3-none-any.whl", hash = "sha256:4e041b91daeb02fce0a156889ea3e48fc5e3e3ba8f594cd72b6bd5765720b702"}, - {file = "qts-0.3.tar.gz", hash = "sha256:84c62a445824cab252b64cff66b244f6d130fd2df88cf495c23c77df00024345"}, -] -quart = [ - {file = "Quart-0.18.3-py3-none-any.whl", hash = "sha256:c221a7deb83a014dee040108d654b6141fe37f59e249c5caa0fdcf6506caf50b"}, - {file = "Quart-0.18.3.tar.gz", hash = "sha256:dc4de597d5d4693627c90904b233d729531f6b27c1164f760476d3967aee2a4a"}, -] -quart-trio = [ - {file = "quart-trio-0.10.0.tar.gz", hash = "sha256:66d4a2f8c3c417741d0e9709e0270edcedfdc26a9daac9e348b374f51c6decf8"}, - {file = "quart_trio-0.10.0-py3-none-any.whl", hash = "sha256:e22759a5e237f47dfff10a8dad3064d1cb11515c6550bf00f988695a068f7249"}, -] -requests = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, -] -requests-file = [ - {file = "requests-file-1.5.1.tar.gz", hash = "sha256:07d74208d3389d01c38ab89ef403af0cfec63957d53a0081d8eca738d0247d8e"}, - {file = "requests_file-1.5.1-py2.py3-none-any.whl", hash = "sha256:dfe5dae75c12481f68ba353183c53a65e6044c923e64c24b2209f6c7570ca953"}, -] -ruff = [ - {file = "ruff-0.0.149-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:e56d77e2a33067e480d6e9ecc328b066c9f8a96ec0f049f7c6107ff1d7106f7f"}, - {file = "ruff-0.0.149-py3-none-macosx_10_9_x86_64.macosx_10_9_arm64.macosx_10_9_universal2.whl", hash = "sha256:ad6e65923abbc59cb677c6d3bbfd778f87a95942c5499eb595afd6803999bf80"}, - {file = "ruff-0.0.149-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eab933a922721930fd6fd02b1001355ee8b81e8810796d7e5d16d2e72a14dc88"}, - {file = "ruff-0.0.149-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:89c5bbc74e2a79f853c3477f1b87846a77b489029d49e4ff53cfcb3d41217b8c"}, - {file = "ruff-0.0.149-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:afa90ff653ef1354ffeaca92c8fb57a8aac16019a702c1c1cf50625b580eb421"}, - {file = "ruff-0.0.149-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:9dc2710115b3006231ab6843d5dc1719618cd7972fa69fcd30e8b3496f380cd9"}, - {file = "ruff-0.0.149-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d79584f96f133f5856d846a162a9f083ac116b890707ef32b4446f4a5b15ccec"}, - {file = "ruff-0.0.149-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8efb6b2f96b127239ee17de9eb9f858b01c72483a9a2c100126ec54d4313f63d"}, - {file = "ruff-0.0.149-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f198fc1cb6cf66e864156449079921a846abe8b6488674f646ea09bccd81457"}, - {file = "ruff-0.0.149-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7e7bde713fd6a6305078dbf54c61e403d120b29093a3e365ec71607574ad1caa"}, - {file = "ruff-0.0.149-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5437e96025dc4427e77e8cf2b49c5ac04b2f3c9e9c62799d60f5f0d5bfc20be8"}, - {file = "ruff-0.0.149-py3-none-musllinux_1_2_i686.whl", hash = "sha256:481b5093db3dd59cf31c192bfe8c1594cebd46e28a36f86d9a1683802a73e9a7"}, - {file = "ruff-0.0.149-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a02c571dbb09c3ee0a17be507ddeec5cdbca2ab098f26aeead2fe691843a837a"}, - {file = "ruff-0.0.149-py3-none-win32.whl", hash = "sha256:58605add6c6f4b5d8306290c66965609da386c5b686a30c535a319dfba3c9af7"}, - {file = "ruff-0.0.149-py3-none-win_amd64.whl", hash = "sha256:58f640e94d5473db4cde84211659576aeccb88ae459e273f204683596b5ec205"}, - {file = "ruff-0.0.149.tar.gz", hash = "sha256:b6707c1ecc9730900138eb92dd0e7cd9123364ae9b33ba2cc9d623990129a29e"}, -] -s3transfer = [ - {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, - {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, -] -sentry-sdk = [ - {file = "sentry-sdk-1.10.1.tar.gz", hash = "sha256:105faf7bd7b7fa25653404619ee261527266b14103fe1389e0ce077bd23a9691"}, - {file = "sentry_sdk-1.10.1-py2.py3-none-any.whl", hash = "sha256:06c0fa9ccfdc80d7e3b5d2021978d6eb9351fa49db9b5847cf4d1f2a473414ad"}, -] -setuptools = [ - {file = "setuptools-63.4.3-py3-none-any.whl", hash = "sha256:7f61f7e82647f77d4118eeaf43d64cbcd4d87e38af9611694d4866eb070cd10d"}, - {file = "setuptools-63.4.3.tar.gz", hash = "sha256:521c833d1e5e1ef0869940e7f486a83de7773b9f029010ad0c2fe35453a9dad9"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -sniffio = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, -] -sortedcontainers = [ - {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, - {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, -] -structlog = [ - {file = "structlog-22.1.0-py3-none-any.whl", hash = "sha256:760d37b8839bd4fe1747bed7b80f7f4de160078405f4b6a1db9270ccbfce6c30"}, - {file = "structlog-22.1.0.tar.gz", hash = "sha256:94b29b1d62b2659db154f67a9379ec1770183933d6115d21f21aa25cfc9a7393"}, -] -tldextract = [ - {file = "tldextract-3.4.0-py3-none-any.whl", hash = "sha256:47aa4d8f1a4da79a44529c9a2ddc518663b25d371b805194ec5ce2a5f615ccd2"}, - {file = "tldextract-3.4.0.tar.gz", hash = "sha256:78aef13ac1459d519b457a03f1f74c1bf1c2808122a6bcc0e6840f81ba55ad73"}, -] -toastedmarshmallow = [ - {file = "toastedmarshmallow-0.2.6-py2.py3-none-any.whl", hash = "sha256:6f8ecbf287e9745a9b6804a69f001804c98547be9425f06281162b742c8bfd68"}, - {file = "toastedmarshmallow-0.2.6.tar.gz", hash = "sha256:15dee79cac691c0a1dc9df694b6e014d00d465b588f49b893c9ece27d09856a0"}, -] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -trio = [ - {file = "trio-0.22.0-py3-none-any.whl", hash = "sha256:f1dd0780a89bfc880c7c7994519cb53f62aacb2c25ff487001c0052bd721cdf0"}, - {file = "trio-0.22.0.tar.gz", hash = "sha256:ce68f1c5400a47b137c5a4de72c7c901bd4e7a24fbdebfe9b41de8c6c04eaacf"}, -] -trio-asyncio = [ - {file = "trio_asyncio-0.12.0-py3-none-any.whl", hash = "sha256:9bf678f83204ba33c395783681c69af563a84145fad2110a152a81a4a18ae7e4"}, - {file = "trio_asyncio-0.12.0.tar.gz", hash = "sha256:824be23b0c678c0df942816cdb57b92a8b94f264fffa89f04626b0ba2d009768"}, -] -trio-typing = [ - {file = "trio-typing-0.7.0.tar.gz", hash = "sha256:5bb2184de144c15f2cc252bba4fd167125758df7339c4f7bc40538940aefa3b9"}, - {file = "trio_typing-0.7.0-py3-none-any.whl", hash = "sha256:156ba760f444aa2f8af43f4459d462415fc297234feb27018e4e902bb62a122b"}, -] -triopg = [ - {file = "triopg-0.6.0-py3-none-any.whl", hash = "sha256:a65147183c0992d0902f6acdeb2b177bb23efbff1ca971ee4f480d02c9cd5442"}, - {file = "triopg-0.6.0.tar.gz", hash = "sha256:ead3505aa702da02e4ec78710385cfa3c216747279d0ab4e6c37fff4236ff162"}, -] -trustme = [ - {file = "trustme-0.9.0-py2.py3-none-any.whl", hash = "sha256:a6e53039cc43e70548ebd9a42ec1af5cba803a16d14321cd96352d2b4e010e04"}, - {file = "trustme-0.9.0.tar.gz", hash = "sha256:5e07b23d70ceed64f3bb36ae4b9abc52354c16c98d45ab037bee2b5fbffe586c"}, -] -types-awscrt = [ - {file = "types_awscrt-0.15.3-py3-none-any.whl", hash = "sha256:faa90585ef8f4e6e85fde17ad2c04604717a7978840416c92b7adddbf6fe5793"}, - {file = "types_awscrt-0.15.3.tar.gz", hash = "sha256:ff24dcbed0d1d27bc2565702af0a2ae5eb73223de87dfe3e4e1bf2eaf00a57ec"}, -] -types-requests = [ - {file = "types-requests-2.28.11.5.tar.gz", hash = "sha256:a7df37cc6fb6187a84097da951f8e21d335448aa2501a6b0a39cbd1d7ca9ee2a"}, - {file = "types_requests-2.28.11.5-py3-none-any.whl", hash = "sha256:091d4a5a33c1b4f20d8b1b952aa8fa27a6e767c44c3cf65e56580df0b05fd8a9"}, -] -types-s3transfer = [ - {file = "types_s3transfer-0.6.0.post5-py3-none-any.whl", hash = "sha256:cfcbee11c16d60af3feb3dbffea3a85b32129235b562912dece310a45ae83a2c"}, - {file = "types_s3transfer-0.6.0.post5.tar.gz", hash = "sha256:2cf1e07cf4d1a5a2a68d89c654f45d9c3b678d39f7fe03a6f36903b6dbd3bcbc"}, -] -types-urllib3 = [ - {file = "types-urllib3-1.26.25.1.tar.gz", hash = "sha256:a948584944b2412c9a74b9cf64f6c48caf8652cb88b38361316f6d15d8a184cd"}, - {file = "types_urllib3-1.26.25.1-py3-none-any.whl", hash = "sha256:f6422596cc9ee5fdf68f9d547f541096a20c2dcfd587e37c804c9ea720bf5cb2"}, -] -typing-extensions = [ - {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, - {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, -] -urllib3 = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, -] -werkzeug = [ - {file = "Werkzeug-2.2.2-py3-none-any.whl", hash = "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"}, - {file = "Werkzeug-2.2.2.tar.gz", hash = "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f"}, -] -winfspy = [ - {file = "winfspy-0.8.3-cp310-cp310-win32.whl", hash = "sha256:7c57fed1e537fb740dff0e4d0ddc11c650b68c22b3ebfe9e2640a03cd12f908c"}, - {file = "winfspy-0.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:ae87957ff05feaae0d35f4734c0176b815dd5c5e3e93f5961fcf5183c24ea6d3"}, - {file = "winfspy-0.8.3-cp36-cp36m-win32.whl", hash = "sha256:44674057f3e8d8488ee5f46f267c60b8784c02f3cbbffb2074a0b17da0a53351"}, - {file = "winfspy-0.8.3-cp36-cp36m-win_amd64.whl", hash = "sha256:b50ed00f4d1590d0a72b395e17ee68e1b6faa9c435fd905803d7236f45cb1717"}, - {file = "winfspy-0.8.3-cp37-cp37m-win32.whl", hash = "sha256:d6da076aa3192753e6b0782fe40e14683caab6da687c853d635737d7eed706d3"}, - {file = "winfspy-0.8.3-cp37-cp37m-win_amd64.whl", hash = "sha256:abce008b613f01a67bb0a792d89666391cb7c3f908998e32ed059d9538c83c5c"}, - {file = "winfspy-0.8.3-cp38-cp38-win32.whl", hash = "sha256:218d04705c1b67db546736cbd97cb77195be4c9ffc903f85b8eba2ecdd82a37d"}, - {file = "winfspy-0.8.3-cp38-cp38-win_amd64.whl", hash = "sha256:9d5b83403ff1cb4591757ecebcfcd46a4a091784cda37e16546f38b01a4e63bb"}, - {file = "winfspy-0.8.3-cp39-cp39-win32.whl", hash = "sha256:fb472211e576c56e6f685fdaa15b3e19209fef91263f9257795e38e232c77291"}, - {file = "winfspy-0.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:0c42649860435cde704cda367f0775acc72cd1549f14b0fb14d73a242ae9e69e"}, - {file = "winfspy-0.8.3.tar.gz", hash = "sha256:836338c35a8810986ad66be88f592edd2960c6e50f58becb0b77256ce5e565ba"}, -] -wsproto = [ - {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, - {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, -] -zipp = [ - {file = "zipp-3.10.0-py3-none-any.whl", hash = "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1"}, - {file = "zipp-3.10.0.tar.gz", hash = "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8"}, -] -zxcvbn = [ - {file = "zxcvbn-4.4.28.tar.gz", hash = "sha256:151bd816817e645e9064c354b13544f85137ea3320ca3be1fb6873ea75ef7dc1"}, -] +content-hash = "3e97b99eac3967e1c18ebfcb3f8f8e3b8c5b7240076a47ae102fc4f012b61b34" diff --git a/pyproject.toml b/pyproject.toml index 9b045be96f7..513721ada9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,6 @@ h11 = "^0.13" # Can use marshmallow or the toasted flavour as you like ;-) # marshmallow = "2.14.0" toastedmarshmallow = "0.2.6" # updating causes consistency problem in test -PyNaCl = "^1.5" trio = "^0.22" trio_typing = "^0.7" sentry-sdk = "^1.5" @@ -58,7 +57,6 @@ structlog = ">=21.5,<23.0" # colorama = "^0.4.4 # structlog colored output" async_exit_stack = "^1.0" outcome = "^1.1" -oscrypto = "^1.2.1" # Backend-only requirements diff --git a/src/api_crypto.rs b/src/api_crypto.rs index 8a21d67d491..bf76f20e1d7 100644 --- a/src/api_crypto.rs +++ b/src/api_crypto.rs @@ -1,29 +1,48 @@ // Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 (eventually AGPL-3.0) 2016-present Scille SAS use pyo3::{ - exceptions::PyValueError, - import_exception, + create_exception, + exceptions::{PyException, PyValueError}, prelude::*, types::{PyByteArray, PyBytes, PyType}, }; -import_exception!(nacl.exceptions, CryptoError); +create_exception!(_parsec, CryptoError, PyException); + +pub(crate) fn add_mod(py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_class::()?; + m.add_function(wrap_pyfunction!(generate_nonce, m)?)?; + + m.add("CryptoError", py.get_type::())?; + + Ok(()) +} #[pyclass] #[derive(Clone)] pub(crate) struct HashDigest(pub libparsec::crypto::HashDigest); crate::binding_utils::gen_proto!(HashDigest, __repr__); +crate::binding_utils::gen_proto!(HashDigest, __copy__); +crate::binding_utils::gen_proto!(HashDigest, __deepcopy__); crate::binding_utils::gen_proto!(HashDigest, __richcmp__, eq); #[pymethods] impl HashDigest { #[new] - fn new(hash: &[u8]) -> PyResult { - match libparsec::crypto::HashDigest::try_from(hash) { - Ok(h) => Ok(Self(h)), - Err(err) => Err(PyValueError::new_err(err.to_string())), - } + fn new(data: &[u8]) -> PyResult { + libparsec::crypto::HashDigest::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) } #[staticmethod] @@ -39,12 +58,12 @@ impl HashDigest { } #[getter] - fn digest<'p>(&self, py: Python<'p>) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new(py, self.0.as_ref())) + fn digest<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, self.0.as_ref()) } - fn hexdigest(&self) -> PyResult { - Ok(self.0.hexdigest()) + fn hexdigest(&self) -> String { + self.0.hexdigest() } } @@ -53,43 +72,41 @@ impl HashDigest { pub(crate) struct SigningKey(pub libparsec::crypto::SigningKey); crate::binding_utils::gen_proto!(SigningKey, __repr__); +crate::binding_utils::gen_proto!(SigningKey, __copy__); +crate::binding_utils::gen_proto!(SigningKey, __deepcopy__); crate::binding_utils::gen_proto!(SigningKey, __richcmp__, eq); #[pymethods] impl SigningKey { #[new] fn new(data: &[u8]) -> PyResult { - match libparsec::crypto::SigningKey::try_from(data) { - Ok(h) => Ok(Self(h)), - Err(err) => Err(PyValueError::new_err(err.to_string())), - } + libparsec::crypto::SigningKey::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) } #[getter] - fn verify_key(&self) -> PyResult { - Ok(VerifyKey(self.0.verify_key())) + fn verify_key(&self) -> VerifyKey { + VerifyKey(self.0.verify_key()) } #[classmethod] - fn generate(_cls: &PyType) -> PyResult { - Ok(Self(libparsec::crypto::SigningKey::generate())) + fn generate(_cls: &PyType) -> Self { + Self(libparsec::crypto::SigningKey::generate()) } /// Return the signature + the signed data - fn sign<'p>(&self, py: Python<'p>, data: &[u8]) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new(py, self.0.sign(data).as_slice())) + fn sign<'py>(&self, py: Python<'py>, data: &[u8]) -> &'py PyBytes { + PyBytes::new(py, self.0.sign(data).as_slice()) } /// Return only the signature of the data - fn sign_only_signature<'p>(&self, py: Python<'p>, data: &[u8]) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new( - py, - self.0.sign_only_signature(data).as_slice(), - )) + fn sign_only_signature<'py>(&self, py: Python<'py>, data: &[u8]) -> &'py PyBytes { + PyBytes::new(py, self.0.sign_only_signature(data).as_slice()) } - fn encode<'p>(&self, py: Python<'p>) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new(py, self.0.as_ref())) + fn encode<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, self.0.as_ref()) } } @@ -98,21 +115,22 @@ impl SigningKey { pub(crate) struct VerifyKey(pub libparsec::crypto::VerifyKey); crate::binding_utils::gen_proto!(VerifyKey, __repr__); +crate::binding_utils::gen_proto!(VerifyKey, __copy__); +crate::binding_utils::gen_proto!(VerifyKey, __deepcopy__); crate::binding_utils::gen_proto!(VerifyKey, __richcmp__, eq); #[pymethods] impl VerifyKey { #[new] pub fn new(data: &[u8]) -> PyResult { - match libparsec::crypto::VerifyKey::try_from(data) { - Ok(h) => Ok(Self(h)), - Err(err) => Err(PyValueError::new_err(err.to_string())), - } + libparsec::crypto::VerifyKey::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) } /// Verify a message using the given `VerifyKey` and `signed` data /// `signed` data is the concatenation of the `signature` + `data` - fn verify<'p>(&self, py: Python<'p>, signed: &[u8]) -> PyResult<&'p PyBytes> { + fn verify<'py>(&self, py: Python<'py>, signed: &[u8]) -> PyResult<&'py PyBytes> { match self.0.verify(signed) { Ok(v) => Ok(PyBytes::new(py, &v)), Err(_) => Err(CryptoError::new_err("Signature was forged or corrupt")), @@ -120,36 +138,36 @@ impl VerifyKey { } /// Verify a message using the given `VerifyKey`, `Signature` and `message` - fn verify_with_signature<'p>( + fn verify_with_signature<'py>( &self, - py: Python<'p>, + py: Python<'py>, signature: &[u8], message: &[u8], - ) -> PyResult<&'p PyBytes> { - match self.0.verify_with_signature(signature, message) { - Ok(v) => Ok(PyBytes::new(py, &v)), - Err(_) => Err(CryptoError::new_err("Signature was forged or corrupt")), - } + ) -> PyResult<&'py PyBytes> { + self.0 + .verify_with_signature( + <[u8; libparsec::crypto::SigningKey::SIGNATURE_SIZE]>::try_from(signature) + .map_err(|_| CryptoError::new_err("Invalid signature size"))?, + message, + ) + .map(|v| PyBytes::new(py, &v)) + .map_err(|_| CryptoError::new_err("Signature was forged or corrupt")) } #[classmethod] - fn unsecure_unwrap<'p>( - _cls: &PyType, - py: Python<'p>, - signed: &[u8], - ) -> PyResult> { - match libparsec::crypto::VerifyKey::unsecure_unwrap(signed) { - Some(v) => Ok(Some(PyBytes::new(py, v))), - None => Ok(Some(PyBytes::new(py, &[]))), - } + fn unsecure_unwrap<'py>(_cls: &PyType, py: Python<'py>, signed: &[u8]) -> &'py PyBytes { + PyBytes::new( + py, + libparsec::crypto::VerifyKey::unsecure_unwrap(signed).unwrap_or_default(), + ) } - fn encode<'p>(&self, py: Python<'p>) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new(py, self.0.as_ref())) + fn encode<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, self.0.as_ref()) } - fn __bytes__<'p>(&self, py: Python<'p>) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new(py, self.0.as_ref())) + fn __bytes__<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, self.0.as_ref()) } } @@ -158,29 +176,30 @@ impl VerifyKey { pub(crate) struct SecretKey(pub libparsec::crypto::SecretKey); crate::binding_utils::gen_proto!(SecretKey, __repr__); +crate::binding_utils::gen_proto!(SecretKey, __copy__); +crate::binding_utils::gen_proto!(SecretKey, __deepcopy__); crate::binding_utils::gen_proto!(SecretKey, __richcmp__, eq); #[pymethods] impl SecretKey { #[new] fn new(data: &[u8]) -> PyResult { - match libparsec::crypto::SecretKey::try_from(data) { - Ok(h) => Ok(Self(h)), - Err(err) => Err(PyValueError::new_err(err.to_string())), - } + libparsec::crypto::SecretKey::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) } #[classmethod] - fn generate(_cls: &PyType) -> PyResult { - Ok(Self(libparsec::crypto::SecretKey::generate())) + fn generate(_cls: &PyType) -> Self { + Self(libparsec::crypto::SecretKey::generate()) } #[getter] - fn secret<'p>(&self, py: Python<'p>) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new(py, self.0.as_ref())) + fn secret<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, self.0.as_ref()) } - fn encrypt<'p>(&self, py: Python<'p>, data: PyObject) -> PyResult<&'p PyBytes> { + fn encrypt<'py>(&self, py: Python<'py>, data: PyObject) -> PyResult<&'py PyBytes> { let bytes = match data.extract::<&PyByteArray>(py) { // SAFETY: Using PyByteArray::as_bytes is safe as long as the corresponding memory is not modified. // Here, the GIL is held during the entire access to `bytes` so there is no risk of another @@ -191,15 +210,15 @@ impl SecretKey { Ok(PyBytes::new(py, &self.0.encrypt(bytes))) } - fn decrypt<'p>(&self, py: Python<'p>, ciphered: &[u8]) -> PyResult<&'p PyBytes> { + fn decrypt<'py>(&self, py: Python<'py>, ciphered: &[u8]) -> PyResult<&'py PyBytes> { match self.0.decrypt(ciphered) { Ok(v) => Ok(PyBytes::new(py, &v)), Err(err) => Err(CryptoError::new_err(err.to_string())), } } - fn hmac<'p>(&self, py: Python<'p>, data: &[u8], digest_size: usize) -> PyResult<&'p PyBytes> { - Ok(PyBytes::new(py, &self.0.hmac(data, digest_size))) + fn hmac<'py>(&self, py: Python<'py>, data: &[u8], digest_size: usize) -> &'py PyBytes { + PyBytes::new(py, &self.0.hmac(data, digest_size)) } #[classmethod] @@ -231,21 +250,22 @@ impl SecretKey { pub(crate) struct PrivateKey(pub libparsec::crypto::PrivateKey); crate::binding_utils::gen_proto!(PrivateKey, __repr__); +crate::binding_utils::gen_proto!(PrivateKey, __copy__); +crate::binding_utils::gen_proto!(PrivateKey, __deepcopy__); crate::binding_utils::gen_proto!(PrivateKey, __richcmp__, eq); #[pymethods] impl PrivateKey { #[new] fn new(data: &[u8]) -> PyResult { - match libparsec::crypto::PrivateKey::try_from(data) { - Ok(h) => Ok(Self(h)), - Err(err) => Err(PyValueError::new_err(err.to_string())), - } + libparsec::crypto::PrivateKey::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) } #[classmethod] - fn generate(_cls: &PyType) -> PyResult { - Ok(PrivateKey(libparsec::crypto::PrivateKey::generate())) + fn generate(_cls: &PyType) -> Self { + PrivateKey(libparsec::crypto::PrivateKey::generate()) } #[getter] @@ -253,7 +273,7 @@ impl PrivateKey { PublicKey(libparsec::crypto::PrivateKey::public_key(&self.0)) } - fn decrypt_from_self<'p>(&self, py: Python<'p>, ciphered: &[u8]) -> PyResult<&'p PyBytes> { + fn decrypt_from_self<'py>(&self, py: Python<'py>, ciphered: &[u8]) -> PyResult<&'py PyBytes> { match self.0.decrypt_from_self(ciphered) { Ok(v) => Ok(PyBytes::new(py, &v)), Err(err) => Err(CryptoError::new_err(err.to_string())), @@ -274,19 +294,20 @@ impl PrivateKey { pub(crate) struct PublicKey(pub libparsec::crypto::PublicKey); crate::binding_utils::gen_proto!(PublicKey, __repr__); +crate::binding_utils::gen_proto!(PublicKey, __copy__); +crate::binding_utils::gen_proto!(PublicKey, __deepcopy__); crate::binding_utils::gen_proto!(PublicKey, __richcmp__, eq); #[pymethods] impl PublicKey { #[new] fn new(data: &[u8]) -> PyResult { - match libparsec::crypto::PublicKey::try_from(data) { - Ok(h) => Ok(Self(h)), - Err(err) => Err(PyValueError::new_err(err.to_string())), - } + libparsec::crypto::PublicKey::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) } - fn encrypt_for_self<'p>(&self, py: Python<'p>, data: PyObject) -> PyResult<&'p PyBytes> { + fn encrypt_for_self<'py>(&self, py: Python<'py>, data: PyObject) -> PyResult<&'py PyBytes> { let bytes = match data.extract::<&PyByteArray>(py) { // SAFETY: Using PyByteArray::as_bytes is safe as long as the corresponding memory is not modified. // Here, the GIL is held during the entire access to `bytes` so there is no risk of another @@ -302,6 +323,203 @@ impl PublicKey { } } +#[pyclass] +#[derive(Clone)] +pub(crate) struct SequesterPrivateKeyDer(pub libparsec::crypto::SequesterPrivateKeyDer); + +crate::binding_utils::gen_proto!(SequesterPrivateKeyDer, __repr__); +crate::binding_utils::gen_proto!(SequesterPrivateKeyDer, __copy__); +crate::binding_utils::gen_proto!(SequesterPrivateKeyDer, __deepcopy__); + +#[pymethods] +impl SequesterPrivateKeyDer { + #[new] + pub fn new(data: &[u8]) -> PyResult { + libparsec::crypto::SequesterPrivateKeyDer::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + // TODO: Remove once it's no longer used in python test + #[classmethod] + fn generate_pair( + _cls: &PyType, + size_in_bits: usize, + ) -> PyResult<(Self, SequesterPublicKeyDer)> { + let (priv_key, pub_key) = + libparsec::crypto::SequesterPrivateKeyDer::generate_pair(match size_in_bits { + 1024 => libparsec::crypto::SequesterKeySize::_1024Bits, + 2048 => libparsec::crypto::SequesterKeySize::_2048Bits, + 3072 => libparsec::crypto::SequesterKeySize::_3072Bits, + 4096 => libparsec::crypto::SequesterKeySize::_4096Bits, + _ => { + return Err(PyValueError::new_err( + "Invalid argument: size_in_bits must be equal to 1024 | 2048 | 3072 | 4096", + )) + } + }); + Ok((Self(priv_key), SequesterPublicKeyDer(pub_key))) + } + + fn dump<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, &self.0.dump()) + } + + fn dump_pem(&self) -> String { + self.0.dump_pem().to_string() + } + + #[classmethod] + fn load_pem(_cls: &PyType, s: &str) -> PyResult { + libparsec::crypto::SequesterPrivateKeyDer::load_pem(s) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + fn decrypt<'py>(&self, py: Python<'py>, data: &[u8]) -> PyResult<&'py PyBytes> { + self.0 + .decrypt(data) + .map(|x| PyBytes::new(py, &x)) + .map_err(|err| CryptoError::new_err(err.to_string())) + } +} + +#[pyclass] +#[derive(Clone)] +pub(crate) struct SequesterPublicKeyDer(pub libparsec::crypto::SequesterPublicKeyDer); + +crate::binding_utils::gen_proto!(SequesterPublicKeyDer, __repr__); +crate::binding_utils::gen_proto!(SequesterPublicKeyDer, __copy__); +crate::binding_utils::gen_proto!(SequesterPublicKeyDer, __deepcopy__); +crate::binding_utils::gen_proto!(SequesterPublicKeyDer, __richcmp__, eq); + +#[pymethods] +impl SequesterPublicKeyDer { + #[new] + fn new(data: &[u8]) -> PyResult { + libparsec::crypto::SequesterPublicKeyDer::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + fn dump<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, &self.0.dump()) + } + + fn dump_pem(&self) -> String { + self.0.dump_pem() + } + + #[classmethod] + fn load_pem(_cls: &PyType, s: &str) -> PyResult { + libparsec::crypto::SequesterPublicKeyDer::load_pem(s) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + fn encrypt<'py>(&self, py: Python<'py>, data: &[u8]) -> &'py PyBytes { + PyBytes::new(py, &self.0.encrypt(data)) + } +} + +#[pyclass] +#[derive(Clone)] +pub(crate) struct SequesterSigningKeyDer(pub libparsec::crypto::SequesterSigningKeyDer); + +crate::binding_utils::gen_proto!(SequesterSigningKeyDer, __repr__); +crate::binding_utils::gen_proto!(SequesterSigningKeyDer, __copy__); +crate::binding_utils::gen_proto!(SequesterSigningKeyDer, __deepcopy__); + +#[pymethods] +impl SequesterSigningKeyDer { + #[new] + pub fn new(data: &[u8]) -> PyResult { + libparsec::crypto::SequesterSigningKeyDer::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + // TODO: Remove once it's no longer used in python test + #[classmethod] + fn generate_pair( + _cls: &PyType, + size_in_bits: usize, + ) -> PyResult<(Self, SequesterVerifyKeyDer)> { + let (priv_key, pub_key) = + libparsec::crypto::SequesterSigningKeyDer::generate_pair(match size_in_bits { + 1024 => libparsec::crypto::SequesterKeySize::_1024Bits, + 2048 => libparsec::crypto::SequesterKeySize::_2048Bits, + 3072 => libparsec::crypto::SequesterKeySize::_3072Bits, + 4096 => libparsec::crypto::SequesterKeySize::_4096Bits, + _ => { + return Err(PyValueError::new_err( + "Invalid argument: size_in_bits must be equal to 1024 | 2048 | 3072 | 4096", + )) + } + }); + Ok((Self(priv_key), SequesterVerifyKeyDer(pub_key))) + } + + fn dump<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, &self.0.dump()) + } + + fn dump_pem(&self) -> String { + self.0.dump_pem().to_string() + } + + #[classmethod] + fn load_pem(_cls: &PyType, s: &str) -> PyResult { + libparsec::crypto::SequesterSigningKeyDer::load_pem(s) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + fn sign<'py>(&self, py: Python<'py>, data: &[u8]) -> &'py PyBytes { + PyBytes::new(py, &self.0.sign(data)) + } +} + +#[pyclass] +#[derive(Clone)] +pub(crate) struct SequesterVerifyKeyDer(pub libparsec::crypto::SequesterVerifyKeyDer); + +crate::binding_utils::gen_proto!(SequesterVerifyKeyDer, __repr__); +crate::binding_utils::gen_proto!(SequesterVerifyKeyDer, __copy__); +crate::binding_utils::gen_proto!(SequesterVerifyKeyDer, __deepcopy__); + +#[pymethods] +impl SequesterVerifyKeyDer { + #[new] + fn new(data: &[u8]) -> PyResult { + libparsec::crypto::SequesterVerifyKeyDer::try_from(data) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + fn dump<'py>(&self, py: Python<'py>) -> &'py PyBytes { + PyBytes::new(py, &self.0.dump()) + } + + fn dump_pem(&self) -> String { + self.0.dump_pem() + } + + #[classmethod] + fn load_pem(_cls: &PyType, s: &str) -> PyResult { + libparsec::crypto::SequesterVerifyKeyDer::load_pem(s) + .map(Self) + .map_err(|err| PyValueError::new_err(err.to_string())) + } + + fn verify<'py>(&self, py: Python<'py>, data: &[u8]) -> PyResult<&'py PyBytes> { + self.0 + .verify(data) + .map(|x| PyBytes::new(py, &x)) + .map_err(|err| CryptoError::new_err(err.to_string())) + } +} + #[pyfunction] pub(crate) fn generate_nonce(py: Python<'_>) -> &PyBytes { PyBytes::new(py, &libparsec::crypto::generate_nonce()) diff --git a/src/binding_utils.rs b/src/binding_utils.rs index 8730c3bc357..6369737811f 100644 --- a/src/binding_utils.rs +++ b/src/binding_utils.rs @@ -144,6 +144,22 @@ macro_rules! gen_proto { } } }; + ($class: ident, __copy__) => { + #[pymethods] + impl $class { + fn __copy__(&self) -> Self { + Self(self.0.clone()) + } + } + }; + ($class: ident, __deepcopy__) => { + #[pymethods] + impl $class { + fn __deepcopy__(&self, _memo: ::pyo3::PyObject) -> Self { + Self(self.0.clone()) + } + } + }; } macro_rules! create_exception { diff --git a/src/lib.rs b/src/lib.rs index 603793ccbf4..0f00087e492 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,13 +30,7 @@ fn entrypoint(py: Python, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_function(wrap_pyfunction!(addrs::export_root_verify_key, m)?)?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_class::()?; - m.add_function(wrap_pyfunction!(api_crypto::generate_nonce, m)?)?; + api_crypto::add_mod(py, m)?; m.add_class::()?; m.add_class::()?; diff --git a/tests/conftest.py b/tests/conftest.py index 7311fa69007..75d21de69df 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,7 +7,6 @@ import sqlite3 import sys from contextlib import contextmanager -from unittest.mock import patch import attr import hypothesis @@ -310,20 +309,13 @@ def unmock(): yield unmock else: + # No longer supported by oxidized crypto - def unsecure_but_fast_argon2i_kdf(size, password, salt, *args, **kwargs): - data = password + salt - return data[:size] + b"\x00" * (size - len(data)) - - from parsec.crypto import argon2i - - vanilla_kdf = argon2i.kdf - + @contextmanager def unmock(): - return patch("parsec.crypto.argon2i.kdf", new=vanilla_kdf) + yield - with patch("parsec.crypto.argon2i.kdf", new=unsecure_but_fast_argon2i_kdf): - yield unmock + yield unmock # Other main fixtures From 551ddff57c57f797e49edeb6f192543f4a455d4d Mon Sep 17 00:00:00 2001 From: TimeEngineer Date: Fri, 31 Mar 2023 11:53:11 +0200 Subject: [PATCH 2/3] Oxidize SequesterCrypto --- .github/workflows/ci.yml | 8 ++ Cargo.lock | 38 ++++---- .../libparsec/crates/client_types/Cargo.toml | 2 +- .../crates/client_types/src/local_device.rs | 2 +- .../crates/client_types/src/local_manifest.rs | 2 +- .../libparsec/crates/protocol/Cargo.toml | 2 +- .../libparsec/crates/protocol/src/lib.rs | 2 +- .../crates/serialization_format/Cargo.toml | 2 +- .../src/old_parser/utils.rs | 2 + oxidation/libparsec/crates/types/Cargo.toml | 2 +- .../libparsec/crates/types/src/certif.rs | 2 +- .../libparsec/crates/types/src/invite.rs | 2 +- .../libparsec/crates/types/src/manifest.rs | 2 +- oxidation/libparsec/crates/types/src/pki.rs | 2 +- parsec/__init__.py | 16 ---- parsec/_parsec.pyi | 8 ++ parsec/api/data/certif.py | 7 +- parsec/backend/cli/sequester.py | 35 ++++--- parsec/backend/organization.py | 4 +- parsec/backend/postgresql/organization.py | 4 +- parsec/backend/postgresql/sequester.py | 3 +- parsec/core/cli/bootstrap_organization.py | 6 +- parsec/core/invite/organization.py | 3 +- parsec/sequester_crypto.py | 18 ---- parsec/sequester_export_reader.py | 26 +++--- parsec/serde/fields.py | 18 ++-- tests/backend/sequester/test_crypto.py | 91 ------------------- tests/backend/sequester/test_export.py | 12 +-- tests/common/sequester.py | 46 ++++------ tests/core/fs/test_sequester.py | 9 +- tests/core/test_bootstrap_organization.py | 13 +-- tests/schemas/api_data.json | 2 +- tests/test_cli.py | 11 +-- 33 files changed, 132 insertions(+), 270 deletions(-) delete mode 100644 parsec/sequester_crypto.py delete mode 100644 tests/backend/sequester/test_crypto.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fa2bbc068d..395b9a74c8c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -459,6 +459,14 @@ jobs: shell: bash run: cargo test --workspace --profile ${{ env.CARGO_PROFILE }} --no-run + # Building OpenSSL requires a perl interpreter. + # The default one does not provide windows-style filesystem + # paths so we have to switch to Strawberry. + - name: Use strawberry perl + if: startsWith(matrix.os, 'windows') + shell: bash + run: echo OPENSSL_SRC_PERL=C:/Strawberry/perl/bin/perl >> $GITHUB_ENV + - name: Test rust codebase if: steps.rust-changes.outputs.run == 'true' shell: bash diff --git a/Cargo.lock b/Cargo.lock index 7c43169d25f..078b16aca2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1479,6 +1479,7 @@ dependencies = [ "glob", "hex-literal", "libparsec_crypto", + "libparsec_serialization_format", "libparsec_types", "paste", "pretty_assertions", @@ -1490,7 +1491,6 @@ dependencies = [ "serde_bytes", "serde_test", "serde_with", - "serialization_format", "sha2 0.10.6", "tests_fixtures", "thiserror", @@ -1611,6 +1611,7 @@ dependencies = [ "glob", "hex-literal", "libparsec_crypto", + "libparsec_serialization_format", "libparsec_types", "paste", "rand 0.8.5", @@ -1619,11 +1620,26 @@ dependencies = [ "serde", "serde_json", "serde_with", - "serialization_format", "tests_fixtures", "thiserror", ] +[[package]] +name = "libparsec_serialization_format" +version = "0.0.0" +dependencies = [ + "anyhow", + "itertools", + "miniserde", + "pretty_assertions", + "proc-macro2", + "quote", + "rstest 0.15.0", + "serde", + "serde_json", + "syn", +] + [[package]] name = "libparsec_types" version = "0.0.0" @@ -1638,6 +1654,7 @@ dependencies = [ "lazy_static", "libparsec_crypto", "libparsec_platform_async", + "libparsec_serialization_format", "paste", "percent-encoding", "pretty_assertions", @@ -1651,7 +1668,6 @@ dependencies = [ "serde_json", "serde_test", "serde_with", - "serialization_format", "tests_fixtures", "thiserror", "unicode-normalization", @@ -2828,22 +2844,6 @@ dependencies = [ "syn", ] -[[package]] -name = "serialization_format" -version = "0.0.0" -dependencies = [ - "anyhow", - "itertools", - "miniserde", - "pretty_assertions", - "proc-macro2", - "quote", - "rstest 0.15.0", - "serde", - "serde_json", - "syn", -] - [[package]] name = "sha-1" version = "0.8.2" diff --git a/oxidation/libparsec/crates/client_types/Cargo.toml b/oxidation/libparsec/crates/client_types/Cargo.toml index a49b611e296..33983bf89b0 100644 --- a/oxidation/libparsec/crates/client_types/Cargo.toml +++ b/oxidation/libparsec/crates/client_types/Cargo.toml @@ -14,7 +14,7 @@ path = "tests/mod.rs" [dependencies] libparsec_crypto = { path = "../crypto" } libparsec_types = { path = "../types" } -serialization_format = { path = "../serialization_format" } +libparsec_serialization_format = { path = "../serialization_format" } flate2 = "1.0.24" serde = { version = "1.0.147", features = ["derive"] } diff --git a/oxidation/libparsec/crates/client_types/src/local_device.rs b/oxidation/libparsec/crates/client_types/src/local_device.rs index 7eec7170f96..0270ff95b40 100644 --- a/oxidation/libparsec/crates/client_types/src/local_device.rs +++ b/oxidation/libparsec/crates/client_types/src/local_device.rs @@ -2,10 +2,10 @@ use serde::{Deserialize, Serialize}; use serde_with::*; -use serialization_format::parsec_data; use sha2::Digest; use libparsec_crypto::prelude::*; +use libparsec_serialization_format::parsec_data; use libparsec_types::*; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] diff --git a/oxidation/libparsec/crates/client_types/src/local_manifest.rs b/oxidation/libparsec/crates/client_types/src/local_manifest.rs index 8c5435d3a50..a14881f9bd1 100644 --- a/oxidation/libparsec/crates/client_types/src/local_manifest.rs +++ b/oxidation/libparsec/crates/client_types/src/local_manifest.rs @@ -9,8 +9,8 @@ use std::{ }; use libparsec_crypto::{HashDigest, SecretKey}; +use libparsec_serialization_format::parsec_data; use libparsec_types::*; -use serialization_format::parsec_data; use crate as libparsec_client_types; diff --git a/oxidation/libparsec/crates/protocol/Cargo.toml b/oxidation/libparsec/crates/protocol/Cargo.toml index 082a905224f..ddaeb27be1f 100644 --- a/oxidation/libparsec/crates/protocol/Cargo.toml +++ b/oxidation/libparsec/crates/protocol/Cargo.toml @@ -14,7 +14,7 @@ path = "tests/mod.rs" [dependencies] libparsec_crypto = { path = "../crypto" } libparsec_types = { path = "../types" } -serialization_format = { path = "../serialization_format" } +libparsec_serialization_format = { path = "../serialization_format" } paste = "1.0.9" rand = "0.8.5" diff --git a/oxidation/libparsec/crates/protocol/src/lib.rs b/oxidation/libparsec/crates/protocol/src/lib.rs index 947f9c1a07b..6842381dd79 100644 --- a/oxidation/libparsec/crates/protocol/src/lib.rs +++ b/oxidation/libparsec/crates/protocol/src/lib.rs @@ -6,7 +6,7 @@ mod handshake; use serde::{Deserialize, Serialize}; use std::num::NonZeroU8; -use serialization_format::parsec_protocol; +use libparsec_serialization_format::parsec_protocol; pub use error::*; pub use handshake::*; diff --git a/oxidation/libparsec/crates/serialization_format/Cargo.toml b/oxidation/libparsec/crates/serialization_format/Cargo.toml index cdc547c62a6..1030e8eafbc 100644 --- a/oxidation/libparsec/crates/serialization_format/Cargo.toml +++ b/oxidation/libparsec/crates/serialization_format/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "serialization_format" +name = "libparsec_serialization_format" version = "0.0.0" edition = "2021" license = " BUSL-1.1" diff --git a/oxidation/libparsec/crates/serialization_format/src/old_parser/utils.rs b/oxidation/libparsec/crates/serialization_format/src/old_parser/utils.rs index 75546411b96..f8e6e7a25e3 100644 --- a/oxidation/libparsec/crates/serialization_format/src/old_parser/utils.rs +++ b/oxidation/libparsec/crates/serialization_format/src/old_parser/utils.rs @@ -35,6 +35,8 @@ pub(crate) fn _inspect_type(ty: &Type, types: &HashMap) -> Strin "PrivateKey" => "libparsec_crypto::PrivateKey", "SecretKey" => "libparsec_crypto::SecretKey", "HashDigest" => "libparsec_crypto::HashDigest", + "SequesterVerifyKeyDer" => "libparsec_crypto::SequesterVerifyKeyDer", + "SequesterPublicKeyDer" => "libparsec_crypto::SequesterPublicKeyDer", "DateTime" => "libparsec_types::DateTime", "BlockID" => "libparsec_types::BlockID", "DeviceID" => "libparsec_types::DeviceID", diff --git a/oxidation/libparsec/crates/types/Cargo.toml b/oxidation/libparsec/crates/types/Cargo.toml index e7aef7f7ad5..5fd0a59555f 100644 --- a/oxidation/libparsec/crates/types/Cargo.toml +++ b/oxidation/libparsec/crates/types/Cargo.toml @@ -12,7 +12,7 @@ path = "tests/mod.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serialization_format = { path = "../serialization_format" } +libparsec_serialization_format = { path = "../serialization_format" } libparsec_crypto = { path = "../crypto" } libparsec_platform_async = { path = "../platform_async" } diff --git a/oxidation/libparsec/crates/types/src/certif.rs b/oxidation/libparsec/crates/types/src/certif.rs index 87090c53c3d..ed322b4fb3e 100644 --- a/oxidation/libparsec/crates/types/src/certif.rs +++ b/oxidation/libparsec/crates/types/src/certif.rs @@ -7,7 +7,7 @@ use serde_with::*; use std::io::{Read, Write}; use libparsec_crypto::{PublicKey, SigningKey, VerifyKey}; -use serialization_format::parsec_data; +use libparsec_serialization_format::parsec_data; use crate as libparsec_types; use crate::data_macros::impl_transparent_data_format_conversion; diff --git a/oxidation/libparsec/crates/types/src/invite.rs b/oxidation/libparsec/crates/types/src/invite.rs index c2acb1d8d8a..ed61bbb81d5 100644 --- a/oxidation/libparsec/crates/types/src/invite.rs +++ b/oxidation/libparsec/crates/types/src/invite.rs @@ -7,7 +7,7 @@ use serde_with::*; use std::str::FromStr; use libparsec_crypto::{PrivateKey, PublicKey, SecretKey, VerifyKey}; -use serialization_format::parsec_data; +use libparsec_serialization_format::parsec_data; use crate::{ self as libparsec_types, data_macros::impl_transparent_data_format_conversion, DeviceID, diff --git a/oxidation/libparsec/crates/types/src/manifest.rs b/oxidation/libparsec/crates/types/src/manifest.rs index aec1b105040..f96fc838602 100644 --- a/oxidation/libparsec/crates/types/src/manifest.rs +++ b/oxidation/libparsec/crates/types/src/manifest.rs @@ -12,7 +12,7 @@ use std::{ use unicode_normalization::UnicodeNormalization; use libparsec_crypto::{HashDigest, SecretKey, SigningKey, VerifyKey}; -use serialization_format::parsec_data; +use libparsec_serialization_format::parsec_data; use crate::{ self as libparsec_types, data_macros::impl_transparent_data_format_conversion, BlockID, diff --git a/oxidation/libparsec/crates/types/src/pki.rs b/oxidation/libparsec/crates/types/src/pki.rs index f368e3d84f1..66612f621dd 100644 --- a/oxidation/libparsec/crates/types/src/pki.rs +++ b/oxidation/libparsec/crates/types/src/pki.rs @@ -6,7 +6,7 @@ use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use libparsec_crypto::{PublicKey, VerifyKey}; -use serialization_format::parsec_data; +use libparsec_serialization_format::parsec_data; use crate::{ self as libparsec_types, impl_transparent_data_format_conversion, DataError, DataResult, diff --git a/parsec/__init__.py b/parsec/__init__.py index 6da925f2a77..73bdf7b37e2 100644 --- a/parsec/__init__.py +++ b/parsec/__init__.py @@ -1,24 +1,8 @@ # Parsec Cloud (https://parsec.cloud) Copyright (c) AGPL-3.0 2016-present Scille SAS from __future__ import annotations -import os - from parsec._version import __version__ -# The oscrypto library relies on `ctypes.util.find_library`, -# which doesn't work for snap classic environments. -# Hence, we rely on env variables similar to `FUSE_LIBRARY_PATH` -# to configure oscrypto correctly if those variables are provided. -SSL_LIBRARY_PATH = os.environ.get("SSL_LIBRARY_PATH") -CRYPTO_LIBRARY_PATH = os.environ.get("CRYPTO_LIBRARY_PATH") -if SSL_LIBRARY_PATH and CRYPTO_LIBRARY_PATH: - import oscrypto - - oscrypto.use_openssl( - libcrypto_path=CRYPTO_LIBRARY_PATH, - libssl_path=SSL_LIBRARY_PATH, - ) - # The parsec.utils module includes a bit of patching, let's make sure it is imported __import__("parsec.utils") diff --git a/parsec/_parsec.pyi b/parsec/_parsec.pyi index d39d9b0482a..a00969dac7a 100644 --- a/parsec/_parsec.pyi +++ b/parsec/_parsec.pyi @@ -24,6 +24,10 @@ from parsec._parsec_pyi.crypto import ( PrivateKey, PublicKey, SecretKey, + SequesterPrivateKeyDer, + SequesterPublicKeyDer, + SequesterSigningKeyDer, + SequesterVerifyKeyDer, SigningKey, VerifyKey, generate_nonce, @@ -510,6 +514,10 @@ __all__ = [ "VerifyKey", "PrivateKey", "PublicKey", + "SequesterPrivateKeyDer", + "SequesterPublicKeyDer", + "SequesterSigningKeyDer", + "SequesterVerifyKeyDer", "generate_nonce", # Enumerate "ClientType", diff --git a/parsec/api/data/certif.py b/parsec/api/data/certif.py index 874d66f333b..aadc4e684b0 100644 --- a/parsec/api/data/certif.py +++ b/parsec/api/data/certif.py @@ -5,10 +5,9 @@ import attr -from parsec._parsec import DateTime +from parsec._parsec import DateTime, SequesterPublicKeyDer, SequesterVerifyKeyDer from parsec.api.data.base import BaseAPIData, BaseAPISignedData, BaseSignedDataSchema from parsec.api.protocol import SequesterServiceID, SequesterServiceIDField -from parsec.sequester_crypto import SequesterEncryptionKeyDer, SequesterVerifyKeyDer from parsec.serde import fields, post_load from parsec.serde.schema import BaseSchema @@ -41,7 +40,7 @@ class SCHEMA_CLS(BaseSchema): timestamp = fields.DateTime(required=True) service_id = SequesterServiceIDField(required=True) service_label = fields.String(required=True) - encryption_key_der = fields.SequesterEncryptionKeyDerField(required=True) + encryption_key_der = fields.SequesterPublicKeyDerField(required=True) @post_load def make_obj(self, data: Dict[str, Any]) -> "SequesterServiceCertificate": # type: ignore[misc] @@ -51,4 +50,4 @@ def make_obj(self, data: Dict[str, Any]) -> "SequesterServiceCertificate": # ty timestamp: DateTime service_id: SequesterServiceID service_label: str - encryption_key_der: SequesterEncryptionKeyDer + encryption_key_der: SequesterPublicKeyDer diff --git a/parsec/backend/cli/sequester.py b/parsec/backend/cli/sequester.py index cb36b96b6ec..5d3a2bc1f51 100644 --- a/parsec/backend/cli/sequester.py +++ b/parsec/backend/cli/sequester.py @@ -8,11 +8,15 @@ import attr import click -import oscrypto from async_generator import asynccontextmanager -from oscrypto.asymmetric import PrivateKey -from parsec._parsec import DateTime +from parsec._parsec import ( + DateTime, + SequesterPrivateKeyDer, + SequesterPublicKeyDer, + SequesterSigningKeyDer, + SequesterVerifyKeyDer, +) from parsec.api.data import DataError, SequesterServiceCertificate from parsec.api.protocol import HumanHandle, OrganizationID, RealmID, SequesterServiceID, UserID from parsec.backend.blockstore import blockstore_factory @@ -33,13 +37,8 @@ ) from parsec.backend.user import User from parsec.cli_utils import cli_exception_handler, debug_config_options, operation +from parsec.crypto import CryptoError from parsec.event_bus import EventBus -from parsec.sequester_crypto import ( - CryptoError, - SequesterEncryptionKeyDer, - SequesterVerifyKeyDer, - sequester_authority_sign, -) from parsec.sequester_export_reader import RealmExportProgress, extract_workspace from parsec.utils import open_service_nursery, trio_run @@ -50,11 +49,9 @@ def dump_sequester_service_certificate_pem( certificate_data: SequesterServiceCertificate, - authority_signing_key: PrivateKey, + authority_signing_key: SequesterSigningKeyDer, ) -> str: - certificate = sequester_authority_sign( - signing_key=authority_signing_key, data=certificate_data.dump() - ) + certificate = authority_signing_key.sign(certificate_data.dump()) return "\n".join( ( SEQUESTER_SERVICE_CERTIFICATE_PEM_HEADER, @@ -217,8 +214,8 @@ def generate_service_certificate( ) -> None: with cli_exception_handler(debug): # Load key files - service_key = SequesterEncryptionKeyDer(service_public_key.read_bytes()) - authority_key = oscrypto.asymmetric.load_private_key(authority_private_key.read_bytes()) + service_key = SequesterPublicKeyDer.load_pem(service_public_key.read_text()) + authority_key = SequesterSigningKeyDer.load_pem(authority_private_key.read_text()) # Generate data schema service_id = SequesterServiceID.new() @@ -427,8 +424,8 @@ def create_service( "Webhook sequester service requires webhook_url argument" ) # Load key files - service_key = SequesterEncryptionKeyDer(service_public_key.read_bytes()) - authority_key = oscrypto.asymmetric.load_private_key(authority_private_key.read_bytes()) + service_key = SequesterPublicKeyDer.load_pem(service_public_key.read_text()) + authority_key = SequesterSigningKeyDer.load_pem(authority_private_key.read_text()) # Generate data schema service_id = SequesterServiceID.new() now = DateTime.now() @@ -438,7 +435,7 @@ def create_service( service_label=service_label, encryption_key_der=service_key, ) - certificate = sequester_authority_sign(signing_key=authority_key, data=certif_data.dump()) + certificate = authority_key.sign(certif_data.dump()) sequester_service: BaseSequesterService if cooked_service_type == SequesterServiceType.STORAGE: @@ -797,7 +794,7 @@ def extract_realm_export( # Finally a command that is not async ! # This is because here we do only a single thing at a time and sqlite3 provide # a synchronous api anyway - decryption_key = oscrypto.asymmetric.load_private_key(service_decryption_key.read_bytes()) + decryption_key = SequesterPrivateKeyDer.load_pem(service_decryption_key.read_text()) # Convert filter_date from click.Datetime to parsec.Datetime date: DateTime diff --git a/parsec/backend/organization.py b/parsec/backend/organization.py index fe38827b736..cba805c313e 100644 --- a/parsec/backend/organization.py +++ b/parsec/backend/organization.py @@ -18,7 +18,9 @@ OrganizationStatsRepNotFound, OrganizationStatsRepOk, OrganizationStatsReq, + SequesterVerifyKeyDer, UsersPerProfileDetailItem, + VerifyKey, ) from parsec.api.data import ( DataError, @@ -41,8 +43,6 @@ from parsec.backend.user import Device, User from parsec.backend.utils import Unset, UnsetType, api, api_typed_msg_adapter, catch_protocol_errors from parsec.backend.webhooks import WebhooksComponent -from parsec.crypto import VerifyKey -from parsec.sequester_crypto import SequesterVerifyKeyDer from parsec.utils import timestamps_in_the_ballpark diff --git a/parsec/backend/postgresql/organization.py b/parsec/backend/postgresql/organization.py index 3380707fd1f..8bf8535054f 100644 --- a/parsec/backend/postgresql/organization.py +++ b/parsec/backend/postgresql/organization.py @@ -7,7 +7,7 @@ import triopg from triopg import UniqueViolationError -from parsec._parsec import DateTime +from parsec._parsec import DateTime, SequesterVerifyKeyDer, VerifyKey from parsec.api.protocol import OrganizationID, UserProfile from parsec.backend.events import BackendEvent from parsec.backend.organization import ( @@ -28,8 +28,6 @@ from parsec.backend.postgresql.utils import Q, q_organization_internal_id from parsec.backend.user import Device, User, UserError from parsec.backend.utils import Unset, UnsetType -from parsec.crypto import VerifyKey -from parsec.sequester_crypto import SequesterVerifyKeyDer _q_insert_organization = Q( diff --git a/parsec/backend/postgresql/sequester.py b/parsec/backend/postgresql/sequester.py index b2fb88d482a..becb1165ace 100644 --- a/parsec/backend/postgresql/sequester.py +++ b/parsec/backend/postgresql/sequester.py @@ -6,7 +6,7 @@ import triopg -from parsec._parsec import DateTime +from parsec._parsec import DateTime, SequesterVerifyKeyDer from parsec.api.data import DataError, SequesterServiceCertificate from parsec.api.protocol import OrganizationID, RealmID, SequesterServiceID, VlobID from parsec.backend.organization import SequesterAuthority @@ -29,7 +29,6 @@ WebhookSequesterService, ) from parsec.crypto import CryptoError -from parsec.sequester_crypto import SequesterVerifyKeyDer # Sequester authority never gets modified past organization bootstrap, hence no need diff --git a/parsec/core/cli/bootstrap_organization.py b/parsec/core/cli/bootstrap_organization.py index 90aebe5fff7..d89161879cf 100644 --- a/parsec/core/cli/bootstrap_organization.py +++ b/parsec/core/cli/bootstrap_organization.py @@ -7,15 +7,13 @@ import click -from parsec._parsec import LocalDevice -from parsec.api.protocol import DeviceLabel, HumanHandle +from parsec._parsec import DeviceLabel, HumanHandle, LocalDevice, SequesterVerifyKeyDer from parsec.cli_utils import async_confirm, async_prompt, cli_exception_handler, spinner from parsec.core.cli.utils import cli_command_base_options, core_config_options, save_device_options from parsec.core.config import CoreConfig from parsec.core.fs.storage.user_storage import user_storage_non_speculative_init from parsec.core.invite import bootstrap_organization as do_bootstrap_organization from parsec.core.types import BackendOrganizationBootstrapAddr -from parsec.sequester_crypto import SequesterVerifyKeyDer from parsec.utils import trio_run @@ -63,7 +61,7 @@ async def _bootstrap_organization( ) if not answer: raise SystemExit("Bootstrap aborted") - sequester_vrf_key = SequesterVerifyKeyDer(sequester_verify_key.read_bytes()) + sequester_vrf_key = SequesterVerifyKeyDer.load_pem(sequester_verify_key.read_text()) human_label: str = human_label or await async_prompt("User fullname") human_email: str = human_email or await async_prompt("User email") diff --git a/parsec/core/invite/organization.py b/parsec/core/invite/organization.py index 9cc21d56304..df97a8a622f 100644 --- a/parsec/core/invite/organization.py +++ b/parsec/core/invite/organization.py @@ -1,6 +1,7 @@ # Parsec Cloud (https://parsec.cloud) Copyright (c) AGPL-3.0 2016-present Scille SAS from __future__ import annotations +from parsec._parsec import SequesterVerifyKeyDer, SigningKey, VerifyKey from parsec.api.data import DeviceCertificate, SequesterAuthorityCertificate, UserCertificate from parsec.api.protocol import DeviceLabel, HumanHandle, UserProfile from parsec.core.backend_connection import apiv1_backend_anonymous_cmds_factory @@ -14,8 +15,6 @@ ) from parsec.core.local_device import generate_new_device from parsec.core.types import BackendOrganizationAddr, BackendOrganizationBootstrapAddr, LocalDevice -from parsec.crypto import SigningKey, VerifyKey -from parsec.sequester_crypto import SequesterVerifyKeyDer def _check_rep(rep: dict[str, object], step_name: str) -> None: diff --git a/parsec/sequester_crypto.py b/parsec/sequester_crypto.py deleted file mode 100644 index 814cbeb9a9d..00000000000 --- a/parsec/sequester_crypto.py +++ /dev/null @@ -1,18 +0,0 @@ -# Parsec Cloud (https://parsec.cloud) Copyright (c) AGPL-3.0 2016-present Scille SAS -from __future__ import annotations - -from parsec._parsec import ( - CryptoError, - SequesterEncryptionKeyDer, - SequesterVerifyKeyDer, - sequester_authority_sign, - sequester_service_decrypt, -) - -__all__ = ( - "CryptoError", - "SequesterVerifyKeyDer", - "SequesterEncryptionKeyDer", - "sequester_authority_sign", - "sequester_service_decrypt", -) diff --git a/parsec/sequester_export_reader.py b/parsec/sequester_export_reader.py index a0b5e029e04..b7992e0313d 100644 --- a/parsec/sequester_export_reader.py +++ b/parsec/sequester_export_reader.py @@ -8,25 +8,26 @@ from pathlib import Path, PurePath from typing import Dict, Iterator, List, Mapping, Tuple -from oscrypto.asymmetric import PrivateKey - -from parsec._parsec import DateTime -from parsec.api.data import ( +from parsec._parsec import ( DataError, + DateTime, DeviceCertificate, + DeviceID, EntryID, EntryName, FileManifest, FolderManifest, + RealmID, RealmRoleCertificate, RevokedUserCertificate, + SequesterPrivateKeyDer, UserCertificate, + VerifyKey, WorkspaceManifest, + manifest_verify_and_load, ) -from parsec.api.data.manifest import AnyRemoteManifest, manifest_verify_and_load -from parsec.api.protocol import DeviceID, RealmID -from parsec.crypto import CryptoError, VerifyKey -from parsec.sequester_crypto import sequester_service_decrypt +from parsec.api.data.manifest import AnyRemoteManifest +from parsec.crypto import CryptoError REALM_EXPORT_DB_MAGIC_NUMBER = 87947 REALM_EXPORT_DB_VERSION = 1 # Only supported version so far @@ -175,7 +176,7 @@ def load_role_certificates( @dataclass class WorkspaceExport: db: RealmExportDb - decryption_key: PrivateKey + decryption_key: SequesterPrivateKeyDer devices_form_internal_id: Dict[int, Tuple[DeviceID, VerifyKey]] filter_on_date: DateTime @@ -203,9 +204,8 @@ def load_manifest(self, manifest_id: EntryID) -> AnyRemoteManifest: raise InconsistentWorkspaceError(f"Missing device certificate for `{author}`") timestamp = DateTime.from_timestamp(raw_timestamp / 1000000) - decrypted_blob = sequester_service_decrypt( - decryption_key=self.decryption_key, data=blob - ) + decrypted_blob = self.decryption_key.decrypt(blob) + manifest = manifest_verify_and_load( signed=decrypted_blob, author_verify_key=author_verify_key, @@ -374,7 +374,7 @@ def extract_workspace( def extract_workspace( - output: Path, export_db: Path, decryption_key: PrivateKey, filter_on_date: DateTime + output: Path, export_db: Path, decryption_key: SequesterPrivateKeyDer, filter_on_date: DateTime ) -> Iterator[Tuple[PurePath | None, RealmExportProgress, str]]: with RealmExportDb.open(export_db) as db: out_certificates: list[Tuple[int, DeviceCertificate]] = [] diff --git a/parsec/serde/fields.py b/parsec/serde/fields.py index 57bd18e1863..273bdc7f804 100644 --- a/parsec/serde/fields.py +++ b/parsec/serde/fields.py @@ -26,10 +26,10 @@ from parsec._parsec import PrivateKey as _PrivateKey from parsec._parsec import PublicKey as _PublicKey from parsec._parsec import SecretKey as _SecretKey +from parsec._parsec import SequesterPublicKeyDer as _SequesterPublicKeyDer +from parsec._parsec import SequesterVerifyKeyDer as _SequesterVerifyKeyDer from parsec._parsec import SigningKey as _SigningKey from parsec._parsec import VerifyKey as _VerifyKey -from parsec.sequester_crypto import SequesterEncryptionKeyDer as _SequesterEncryptionKeyDer -from parsec.sequester_crypto import SequesterVerifyKeyDer as _SequesterVerifyKeyDer from parsec.types import FrozenDict as _FrozenDict __all__ = ( @@ -495,27 +495,25 @@ def _deserialize( SequesterVerifyKeyDer = SequesterVerifyKeyDerField -class SequesterEncryptionKeyDerField(Field[_SequesterEncryptionKeyDer]): - def _serialize( - self, value: _SequesterEncryptionKeyDer | None, attr: str, obj: Any - ) -> bytes | None: +class SequesterPublicKeyDerField(Field[_SequesterPublicKeyDer]): + def _serialize(self, value: _SequesterPublicKeyDer | None, attr: str, obj: Any) -> bytes | None: if value is None: return None - assert isinstance(value, _SequesterEncryptionKeyDer) + assert isinstance(value, _SequesterPublicKeyDer) return value.dump() def _deserialize( self, value: object, attr: str, data: dict[str, object] - ) -> _SequesterEncryptionKeyDer: + ) -> _SequesterPublicKeyDer: if not isinstance(value, bytes): raise ValidationError("Expecting bytes") try: - return _SequesterEncryptionKeyDer(value) + return _SequesterPublicKeyDer(value) except Exception as exc: raise ValidationError(str(exc)) from exc -SequesterEncryptionKeyDer = SequesterEncryptionKeyDerField +SequesterPublicKeyDer = SequesterPublicKeyDerField class PkiEnrollmentSubmitPayloadField(Field[_PkiEnrollmentSubmitPayload]): diff --git a/tests/backend/sequester/test_crypto.py b/tests/backend/sequester/test_crypto.py deleted file mode 100644 index d01abaa2a1c..00000000000 --- a/tests/backend/sequester/test_crypto.py +++ /dev/null @@ -1,91 +0,0 @@ -# Parsec Cloud (https://parsec.cloud) Copyright (c) AGPL-3.0 2016-present Scille SAS -from __future__ import annotations - -import oscrypto.asymmetric -import pytest - -from parsec.sequester_crypto import ( - SequesterEncryptionKeyDer, - SequesterVerifyKeyDer, - sequester_authority_sign, - sequester_service_decrypt, -) - - -def test_only_rsa_is_supported(): - # Unsupported format for service encryption key (only RSA is currently supported) - unsupported_public_key, _ = oscrypto.asymmetric.generate_pair("dsa", bit_size=1024) - with pytest.raises(ValueError): - SequesterEncryptionKeyDer(unsupported_public_key), - with pytest.raises(ValueError): - SequesterVerifyKeyDer(unsupported_public_key), - - -def test_encryption_output_has_key_size(monkeypatch): - key_bit_size = 1024 - key_byte_size = key_bit_size // 8 - patched_called = 0 - - def patched_rsa_oaep_encrypt(key, data): - nonlocal patched_called - patched_called += 1 - assert key.byte_size == key_byte_size - assert len(data) == 32 # Data here is a Salsa20 key - # Output is 64bytes so much smaller than the 128bytes key - return b"\x01" * 32 + data - - def patched_rsa_oaep_decrypt(key, encrypted): - nonlocal patched_called - patched_called += 1 - assert key.byte_size == key_byte_size - assert len(encrypted) == key_byte_size - assert encrypted[:64] == b"\x00" * 64 # Null bytes added to have the correct size - assert encrypted[64:96] == b"\x01" * 32 - return encrypted[96:] - - monkeypatch.setattr("oscrypto.asymmetric.rsa_oaep_encrypt", patched_rsa_oaep_encrypt) - monkeypatch.setattr("oscrypto.asymmetric.rsa_oaep_decrypt", patched_rsa_oaep_decrypt) - - public_key, private_key = oscrypto.asymmetric.generate_pair("rsa", bit_size=key_bit_size) - encryption_key = SequesterEncryptionKeyDer(public_key) - - encrypted = encryption_key.encrypt(b"foo") - decrypted = sequester_service_decrypt(private_key, encrypted) - assert decrypted == b"foo" - - assert patched_called == 2 # Make sure the mock has been used - - -def test_signature_output_has_key_size(monkeypatch): - key_bit_size = 1024 - key_byte_size = key_bit_size // 8 - patched_called = 0 - - def patched_rsa_pss_sign(key, data, hash_algorithm): - nonlocal patched_called - patched_called += 1 - assert hash_algorithm == "sha256" - assert key.byte_size == key_byte_size - # Output is 64bytes so much smaller than the 128bytes key - return b"\x01" * 64 - - def patched_rsa_pss_verify(key, signed, data, hash_algorithm): - nonlocal patched_called - patched_called += 1 - assert hash_algorithm == "sha256" - assert key.byte_size == key_byte_size - assert len(signed) == key_byte_size - assert signed[:64] == b"\x00" * 64 # Null bytes added to have the correct size - assert signed[64:] == b"\x01" * 64 - - monkeypatch.setattr("oscrypto.asymmetric.rsa_pss_sign", patched_rsa_pss_sign) - monkeypatch.setattr("oscrypto.asymmetric.rsa_pss_verify", patched_rsa_pss_verify) - - public_key, private_key = oscrypto.asymmetric.generate_pair("rsa", bit_size=key_bit_size) - verify_key = SequesterVerifyKeyDer(public_key) - - signed = sequester_authority_sign(private_key, b"foo") - verified = verify_key.verify(signed) - assert verified == b"foo" - - assert patched_called == 2 # Make sure the mock has been used diff --git a/tests/backend/sequester/test_export.py b/tests/backend/sequester/test_export.py index 171e99930ce..87f72d6c088 100644 --- a/tests/backend/sequester/test_export.py +++ b/tests/backend/sequester/test_export.py @@ -3,10 +3,9 @@ import sqlite3 -import oscrypto.asymmetric import pytest -from parsec._parsec import DateTime +from parsec._parsec import DateTime, HashDigest, SecretKey, SequesterPrivateKeyDer from parsec.api.data import ( BlockAccess, DeviceCertificate, @@ -35,8 +34,6 @@ RealmExporterOutputDbError, ) from parsec.backend.realm import RealmGrantedRole -from parsec.crypto import HashDigest, SecretKey -from parsec.sequester_crypto import SequesterEncryptionKeyDer from parsec.sequester_export_reader import extract_workspace from tests.common import OrganizationFullData, customize_fixtures, sequester_service_factory @@ -436,10 +433,9 @@ def _sqlite_timestamp(year: int, month: int, day: int) -> int: async def test_export_reader_full_run(tmp_path, coolorg: OrganizationFullData, alice, bob, adam): output_db_path = tmp_path / "export.sqlite" realm1 = RealmID.new() - service_encryption_key, service_decryption_key = oscrypto.asymmetric.generate_pair( - "rsa", bit_size=1024 - ) - service_encryption_key = SequesterEncryptionKeyDer(service_encryption_key) + # Don't use such a small key size in real world, this is only for test ! + # (RSA key generation gets ~10x slower between 1024 and 4096) + service_decryption_key, service_encryption_key = SequesterPrivateKeyDer.generate_pair(1024) # Generate the export db by hand here con = sqlite3.connect(output_db_path) diff --git a/tests/common/sequester.py b/tests/common/sequester.py index dc29a41f2ff..5bcc4021245 100644 --- a/tests/common/sequester.py +++ b/tests/common/sequester.py @@ -2,11 +2,15 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Optional -import oscrypto.asymmetric - -from parsec._parsec import DateTime +from parsec._parsec import ( + DateTime, + SequesterPrivateKeyDer, + SequesterPublicKeyDer, + SequesterSigningKeyDer, + SequesterVerifyKeyDer, + SigningKey, +) from parsec.api.data import SequesterAuthorityCertificate, SequesterServiceCertificate from parsec.api.protocol import SequesterServiceID from parsec.backend.sequester import ( @@ -15,35 +19,27 @@ StorageSequesterService, WebhookSequesterService, ) -from parsec.crypto import SigningKey -from parsec.sequester_crypto import ( - SequesterEncryptionKeyDer, - SequesterVerifyKeyDer, - sequester_authority_sign, -) @dataclass class SequesterAuthorityFullData: certif: bytes certif_data: SequesterAuthorityCertificate - signing_key: oscrypto.asymmetric.PrivateKey - verify_key: oscrypto.asymmetric.PublicKey + signing_key: SequesterSigningKeyDer + verify_key: SequesterVerifyKeyDer def sequester_authority_factory( - organization_root_signing_key: SigningKey, timestamp: Optional[DateTime] = None + organization_root_signing_key: SigningKey, timestamp: DateTime | None = None ) -> SequesterAuthorityFullData: timestamp = timestamp or DateTime.now() # Don't use such a small key size in real world, this is only for test ! # (RSA key generation gets ~10x slower between 1024 and 4096) - verify_key, signing_key = oscrypto.asymmetric.generate_pair("rsa", bit_size=1024) + signing_key, verify_key = SequesterSigningKeyDer.generate_pair(1024) certif = SequesterAuthorityCertificate( author=None, timestamp=timestamp, - verify_key_der=SequesterVerifyKeyDer( - oscrypto.asymmetric.dump_public_key(verify_key, encoding="der") - ), + verify_key_der=verify_key, ) return SequesterAuthorityFullData( certif=certif.dump_and_sign(organization_root_signing_key), @@ -57,8 +53,8 @@ def sequester_authority_factory( class SequesterServiceFullData: certif: bytes certif_data: SequesterServiceCertificate - decryption_key: oscrypto.asymmetric.PrivateKey - encryption_key: oscrypto.asymmetric.PublicKey + decryption_key: SequesterPrivateKeyDer + encryption_key: SequesterPublicKeyDer backend_service: BaseSequesterService @property @@ -69,23 +65,21 @@ def service_id(self) -> SequesterServiceID: def sequester_service_factory( label: str, authority: SequesterAuthorityFullData, - timestamp: Optional[DateTime] = None, + timestamp: DateTime | None = None, service_type: SequesterServiceType = SequesterServiceType.STORAGE, - webhook_url: Optional[str] = None, + webhook_url: str | None = None, ) -> SequesterServiceFullData: timestamp = timestamp or DateTime.now() # Don't use such a small key size in real world, this is only for test ! # (RSA key generation gets ~10x slower between 1024 and 4096) - encryption_key, decryption_key = oscrypto.asymmetric.generate_pair("rsa", bit_size=1024) + decryption_key, encryption_key = SequesterPrivateKeyDer.generate_pair(1024) certif_data = SequesterServiceCertificate( service_id=SequesterServiceID.new(), timestamp=timestamp, service_label=label, - encryption_key_der=SequesterEncryptionKeyDer( - oscrypto.asymmetric.dump_public_key(encryption_key, encoding="der") - ), + encryption_key_der=encryption_key, ) - certif = sequester_authority_sign(signing_key=authority.signing_key, data=certif_data.dump()) + certif = authority.signing_key.sign(certif_data.dump()) if service_type == SequesterServiceType.STORAGE: assert webhook_url is None backend_service = StorageSequesterService( diff --git a/tests/core/fs/test_sequester.py b/tests/core/fs/test_sequester.py index c0f4ebadd4c..53d07bc23ff 100644 --- a/tests/core/fs/test_sequester.py +++ b/tests/core/fs/test_sequester.py @@ -12,7 +12,6 @@ from parsec.core.core_events import CoreEvent from parsec.core.fs.exceptions import FSServerUploadTemporarilyUnavailableError from parsec.core.fs.path import FsPath -from parsec.sequester_crypto import sequester_service_decrypt from tests.common import customize_fixtures, sequester_service_factory @@ -49,9 +48,7 @@ async def _assert_sequester_dump(service, local_device, expected_versions): # Advanced check: make sure each item contain the valid data for _, version, sequestered_blob in realm_dump: - clear_blob_from_sequester = sequester_service_decrypt( - service.decryption_key, sequestered_blob - ) + clear_blob_from_sequester = service.decryption_key.decrypt(sequestered_blob) _, blob, _, _, _ = await backend.vlob.read( organization_id=coolorg.organization_id, author=local_device.device_id, @@ -121,9 +118,7 @@ async def _assert_sequester_dump(service, workspace, expected_items): # Advanced check: make sure each item contain the valid data for vlob_id, version, sequestered_blob in realm_dump: - clear_blob_from_sequester = sequester_service_decrypt( - service.decryption_key, sequestered_blob - ) + clear_blob_from_sequester = service.decryption_key.decrypt(sequestered_blob) _, blob, _, _, _ = await backend.vlob.read( organization_id=coolorg.organization_id, author=alice.device_id, diff --git a/tests/core/test_bootstrap_organization.py b/tests/core/test_bootstrap_organization.py index c4fa1ff0e71..1cc0d1f47df 100644 --- a/tests/core/test_bootstrap_organization.py +++ b/tests/core/test_bootstrap_organization.py @@ -1,16 +1,15 @@ # Parsec Cloud (https://parsec.cloud) Copyright (c) AGPL-3.0 2016-present Scille SAS from __future__ import annotations -import oscrypto import pytest from quart import Response +from parsec._parsec import SequesterSigningKeyDer from parsec.api.data import EntryName from parsec.api.protocol import DeviceLabel, HumanHandle, OrganizationID, UserProfile from parsec.core.fs.storage.user_storage import user_storage_non_speculative_init from parsec.core.invite import InviteAlreadyUsedError, InviteNotFoundError, bootstrap_organization from parsec.core.types import BackendOrganizationBootstrapAddr -from parsec.sequester_crypto import SequesterVerifyKeyDer, sequester_authority_sign from parsec.serde import packb @@ -115,16 +114,18 @@ async def test_bootstrap_sequester_verify_key(running_backend, backend): human_handle = HumanHandle(email="zack@example.com", label="Zack") device_label = DeviceLabel("PC1") - verify_key, signing_key = oscrypto.asymmetric.generate_pair("rsa", bit_size=1024) + # Don't use such a small key size in real world, this is only for test ! + # (RSA key generation gets ~10x slower between 1024 and 4096) + signing_key, verify_key = SequesterSigningKeyDer.generate_pair(1024) + ref_data = b"SomeData" - ref_data_sign = sequester_authority_sign(signing_key, ref_data) - der_verify_key = SequesterVerifyKeyDer(verify_key) + ref_data_sign = signing_key.sign(ref_data) await bootstrap_organization( organization_addr, human_handle=human_handle, device_label=device_label, - sequester_authority_verify_key=der_verify_key, + sequester_authority_verify_key=verify_key, ) organization = await backend.organization.get(org_id) diff --git a/tests/schemas/api_data.json b/tests/schemas/api_data.json index 11b68c7c322..deee7c93c92 100644 --- a/tests/schemas/api_data.json +++ b/tests/schemas/api_data.json @@ -31,7 +31,7 @@ "encryption_key_der": { "allow_none": false, "required": true, - "type": "SequesterEncryptionKeyDerField" + "type": "SequesterPublicKeyDerField" }, "service_id": { "allow_none": false, diff --git a/tests/test_cli.py b/tests/test_cli.py index 5791f9af04a..cab2de06d18 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -8,7 +8,6 @@ from uuid import UUID import click -import oscrypto.asymmetric import trio try: @@ -1067,13 +1066,9 @@ def _setup_sequester_key_paths(tmp_path, coolorg): service = sequester_service_factory("Test Service", coolorg.sequester_authority) service_key = service.encryption_key authority_key = coolorg.sequester_authority.signing_key - service_key_path.write_bytes(oscrypto.asymmetric.dump_public_key(service_key)) - authority_key_path.write_bytes( - oscrypto.asymmetric.dump_private_key(authority_key, passphrase=None) - ) - authority_pubkey_path.write_bytes( - oscrypto.asymmetric.dump_public_key(coolorg.sequester_authority.verify_key) - ) + service_key_path.write_text(service_key.dump_pem()) + authority_key_path.write_text(authority_key.dump_pem()) + authority_pubkey_path.write_text(coolorg.sequester_authority.verify_key.dump_pem()) return authority_key_path, authority_pubkey_path, service_key_path From 73424ebd2839ee2d76e9fb26ddcb520ea166e2b0 Mon Sep 17 00:00:00 2001 From: TimeEngineer Date: Fri, 31 Mar 2023 17:47:21 +0200 Subject: [PATCH 3/3] Fix sodiumoxide SequesterCrypto --- Cargo.lock | 8 +++---- oxidation/libparsec/crates/crypto/Cargo.toml | 4 ++-- .../crypto/src/sodiumoxide/sequester.rs | 20 ++++++++++------ .../crates/crypto/tests/sequester.rs | 23 +++++++++++++++++++ 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 078b16aca2d..c65304782c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1949,9 +1949,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2" dependencies = [ "bitflags", "cfg-if", @@ -1990,9 +1990,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b" dependencies = [ "autocfg", "cc", diff --git a/oxidation/libparsec/crates/crypto/Cargo.toml b/oxidation/libparsec/crates/crypto/Cargo.toml index e13189aefb4..25665a19f8d 100644 --- a/oxidation/libparsec/crates/crypto/Cargo.toml +++ b/oxidation/libparsec/crates/crypto/Cargo.toml @@ -47,8 +47,8 @@ base32 = "0.4.0" sodiumoxide = { version = "0.2.7", optional = true } libsodium-sys = { version = "0.2.7", optional = true } -openssl = { version = "0.10", optional = true, features = ["vendored"] } -zeroize = { version = "1", optional = true, features = ["alloc"]} +openssl = { version = "0.10.48", optional = true, features = ["vendored"] } +zeroize = { version = "1.6.0", optional = true, features = ["alloc"]} argon2 = { version = "0.4.1", optional = true } blake2 = { version = "0.10.6", optional = true } diff --git a/oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs b/oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs index 60713cb1c54..6841d1db327 100644 --- a/oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs +++ b/oxidation/libparsec/crates/crypto/src/sodiumoxide/sequester.rs @@ -5,7 +5,7 @@ use zeroize::Zeroizing; use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private, Public}; use openssl::rsa::{Padding, Rsa}; -use openssl::sign::{RsaPssSaltlen, Signer, Verifier}; +use openssl::sign::{Signer, Verifier}; use serde::{Deserialize, Serialize}; use serde_bytes::Bytes; @@ -283,15 +283,18 @@ impl SequesterSigningKeyDer { // Signature format: // : pub fn sign(&self, data: &[u8]) -> Vec { + // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_CTX_set_rsa_pss_saltlen.html + // EVP_PKEY_CTX_set_rsa_pss_saltlen() sets the RSA PSS salt length to saltlen. + // As its name implies it is only supported for PSS padding. If this function + // is not called then the maximum salt length is used when signing and auto + // detection when verifying. + // Rustcrypto uses maximum salt length, so we do the same, to not call `set_rsa_pss_saltlen()`. let mut signer = Signer::new(MessageDigest::sha256(), &self.0).expect("Unable to build a Signer"); signer .set_rsa_padding(Padding::PKCS1_PSS) .expect("OpenSSL error"); - signer - .set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH) - .expect("OpenSSL error"); signer.update(data).expect("Unreachable"); let signed_data = signer.sign_to_vec().expect("Unable to sign a message"); @@ -376,15 +379,18 @@ impl SequesterVerifyKeyDer { let (signature, contents) = deserialize_with_armor(data, self.size_in_bytes(), Self::ALGORITHM)?; + // https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_CTX_set_rsa_pss_saltlen.html + // EVP_PKEY_CTX_set_rsa_pss_saltlen() sets the RSA PSS salt length to saltlen. + // As its name implies it is only supported for PSS padding. If this function + // is not called then the maximum salt length is used when signing and auto + // detection when verifying. + // So we don't need to call `set_rsa_pss_saltlen()`. let mut verifier = Verifier::new(MessageDigest::sha256(), &self.0) .map_err(|_| CryptoError::SignatureVerification)?; verifier .set_rsa_padding(Padding::PKCS1_PSS) .expect("OpenSSL error"); - verifier - .set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH) - .expect("OpenSSL error"); verifier .update(contents) diff --git a/oxidation/libparsec/crates/crypto/tests/sequester.rs b/oxidation/libparsec/crates/crypto/tests/sequester.rs index e7c3df69333..2b859d4b871 100644 --- a/oxidation/libparsec/crates/crypto/tests/sequester.rs +++ b/oxidation/libparsec/crates/crypto/tests/sequester.rs @@ -305,3 +305,26 @@ fn test_encrypt_compat() { assert_eq!(priv_key.decrypt(&encrypted).unwrap(), b"Hello world"); } + +#[test] +fn verify_with_different_salt_len() { + let verify_key = SequesterVerifyKeyDer::try_from(&PUBLIC_KEY_DER_1024[..]).unwrap(); + let ciphered_salt32 = hex!( + "5253415353412d5053532d5348413235363a5533ef66fbd8249dcf2f813da9e381bde5d5d7" + "30231584e194e43b5a2cd2802a3a9f713939cf5398f7dd445a97ac9ae7aa3b871b296ff5de" + "fa1afe4ee8b1083df0c7c2631f0efb400202d5800c0540e87c4c9b94ecc50d99095212baf3" + "5e0ea79d3a56739867e31126b60d6f11b6448719b69562207a376ca5c5ccc0154318c94865" + "6c6c6f20576f726c640a" + ); + let ciphered_salt94 = hex!( + "5253415353412d5053532d5348413235363a320bb6b943bdf45fb39bc65b60f6353aa29f11" + "c5990f664b555723cc910a1b07e95fe82f1ac7c519088d03347461fa7d168686e431f0e466" + "6752ecbcd3d9c57698cc41b3280784c762effd2771ebc78e55351db499f0242a1e7067e275" + "493d513ac8c04fa8f26ca54633c75ec01a9a60eac2eedc74bbf2979a0140e24976e2874865" + "6c6c6f20576f726c640a" + ); + let data = b"Hello World\n"; + + assert_eq!(verify_key.verify(&ciphered_salt32).unwrap(), data); + assert_eq!(verify_key.verify(&ciphered_salt94).unwrap(), data); +}