commit 7b8035ff33aa4b5b209be2fefece78400716fc8b Author: Ivan Vazhenin Date: Thu Apr 25 20:32:28 2024 +0300 . diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a0e5cb2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/.idea +/venv +.pytest_cache/ +dist/ +build/ +__pycache__/ +*.pyc +*.egg-info/ \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..428e617 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,119 @@ +--- +image: $BUILDER_IMAGE + +variables: + project: "xmlrpcserver" + +stages: + - init +# - lint +# - test + - build + - pack + - upload + - deploy + - deploy_qa + +include: + - project: "ipd/infra" + file: ".version.yml" + - project: "ipd/infra" + file: ".python_lint.yml" + - project: "ipd/infra" + file: ".python_jobs.yml" + - project: "ipd/infra" + file: ".ansistrano-cd.yml" + +#lint: +# variables: +# project: "journal" +# extends: .python_lint +# allow_failure: false +# only: +# refs: +# - merge_requests +# changes: +# - "**/*.py" + +#pylint: +# variables: +# project: "journal" +# extends: .pylint +# allow_failure: false +# only: +# refs: +# - merge_requests +# changes: +# - "**/*.py" + +#pytest: +# stage: test +# tags: [docker] +# image: $REGISTRY_ADDRESS/ipd/$CI_PROJECT_NAME:builder +# services: +# - name: $DOCKER_postgis +# alias: postgres +# - name: $DOCKER_queue +# alias: rabbitmq +# variables: +# ENV_FOR_DYNACONF: testing +# POSTGRES_PASSWORD: postgres +# POSTGRES_HOST: postgres +# POSTGRES__PGBOUNCER: "" +# AMQP__LOGIN: user +# AMQP__PASSWORD: user +# before_script: +# - apt install python -y +# - pip3 install -i $PYPI_REGISTRY --force-reinstall "poetry==1.4.2" +# - export PATH=$(pwd)/.venv/bin:$PATH +# - rm poetry.lock || true +# - poetry config virtualenvs.in-project true +# - poetry config repositories.nexus $PYPI_REGISTRY +# - poetry source add nexus https://nexus.sitronics-kt.dev/repository/pypi/simple/ --default +# - poetry install +# script: +# - poetry env info +# - poetry run coverage run --concurrency=thread --source=. -m pytest tests --junitxml=report.xml +# - poetry run coverage report +# - poetry run genbadge tests -i - < report.xml -o - > badge.svg +# allow_failure: false +# coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' +# only: +# refs: +# - devel +# - merge_requests +# artifacts: +# when: always +# paths: +# - badge.svg +# reports: +# junit: report.xml + +docker_builder_build: + extends: .builder_docker_image_dnd + +make_dist: + extends: .dist_make_new + +docker_build: + extends: .docker_build + +get_version: + stage: upload + tags: [docker] + script: + - buildVersion=$(cat ./VERSION) + - echo "serviceVersion=$buildVersion" >> buildVersion.env + - echo $buildVersion + only: + refs: + - merge_requests + artifacts: + reports: + dotenv: buildVersion.env + +#deploy_qa_autotest: +# extends: .deploy_compose_qa +# variables: +# GEODATA_TAG: test +# serviceVersion: $serviceVersion diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..8acdd82 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.0.1 diff --git a/packaging/builder.Dockerfile b/packaging/builder.Dockerfile new file mode 100644 index 0000000..1492bd7 --- /dev/null +++ b/packaging/builder.Dockerfile @@ -0,0 +1,13 @@ +FROM harbor.sitronics-kt.dev/infra/python3.8.3:latest + +ARG PROJECT_NAME=project +ARG PYPI=https://nexus.sitronics-kt.dev/repository/pypi/simple + +LABEL GROUP="IPD" +LABEL VERSION="$VERSION" +LABEL NAME="$PROJECT_NAME" + +RUN echo "deb http://nexus.centr.m:8081/repository/ipd-products/ stable contrib main non-free" >> /etc/apt/sources.list &&\ + apt update && apt install -y tnt-openssl tnt-boost tnt-python3=3.8.3 tnt-boost-python-common tnt-boost-python libprotobuf-dev infra-gisbase infra-oodb &&\ + python3 -m pip install --upgrade pip wheel setuptools &&\ + python3 -m pip install --upgrade poetry==1.7.1 diff --git a/packaging/service.Dockerfile b/packaging/service.Dockerfile new file mode 100644 index 0000000..44b5664 --- /dev/null +++ b/packaging/service.Dockerfile @@ -0,0 +1,17 @@ +FROM FROM harbor.sitronics-kt.dev/infra/python3.8.3:latest + +WORKDIR /opt/ipd/kt-$PROJECT_NAME +COPY ./dist . + +RUN cd xmlrpcserver/deps/pygost-5.12/ && \ + python3 setup.py install && \ + cd ../../.. && \ + pip3 install -r requirements.txt && \ + mkdir -p /opt/tnt/bin && \ + ln -s /usr/bin/python3 /opt/tnt/bin/python3 + +ENV LD_LIBRARY_PATH "/app" +ENV PYTHONPATH "${PYTHONPATH}:/app" +EXPOSE 9000 +EXPOSE 80 +CMD ["python3", "main.py"] diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..476d7b9 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1301 @@ +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. + +[[package]] +name = "aiohttp" +version = "3.8.6" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:41d55fc043954cddbbd82503d9cc3f4814a40bcef30b3569bc7b5e34130718c1"}, + {file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d84166673694841d8953f0a8d0c90e1087739d24632fe86b1a08819168b4566"}, + {file = "aiohttp-3.8.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:253bf92b744b3170eb4c4ca2fa58f9c4b87aeb1df42f71d4e78815e6e8b73c9e"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fd194939b1f764d6bb05490987bfe104287bbf51b8d862261ccf66f48fb4096"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c5f938d199a6fdbdc10bbb9447496561c3a9a565b43be564648d81e1102ac22"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2817b2f66ca82ee699acd90e05c95e79bbf1dc986abb62b61ec8aaf851e81c93"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fa375b3d34e71ccccf172cab401cd94a72de7a8cc01847a7b3386204093bb47"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9de50a199b7710fa2904be5a4a9b51af587ab24c8e540a7243ab737b45844543"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e1d8cb0b56b3587c5c01de3bf2f600f186da7e7b5f7353d1bf26a8ddca57f965"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8e31e9db1bee8b4f407b77fd2507337a0a80665ad7b6c749d08df595d88f1cf5"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7bc88fc494b1f0311d67f29fee6fd636606f4697e8cc793a2d912ac5b19aa38d"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ec00c3305788e04bf6d29d42e504560e159ccaf0be30c09203b468a6c1ccd3b2"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad1407db8f2f49329729564f71685557157bfa42b48f4b93e53721a16eb813ed"}, + {file = "aiohttp-3.8.6-cp310-cp310-win32.whl", hash = "sha256:ccc360e87341ad47c777f5723f68adbb52b37ab450c8bc3ca9ca1f3e849e5fe2"}, + {file = "aiohttp-3.8.6-cp310-cp310-win_amd64.whl", hash = "sha256:93c15c8e48e5e7b89d5cb4613479d144fda8344e2d886cf694fd36db4cc86865"}, + {file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e2f9cc8e5328f829f6e1fb74a0a3a939b14e67e80832975e01929e320386b34"}, + {file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e6a00ffcc173e765e200ceefb06399ba09c06db97f401f920513a10c803604ca"}, + {file = "aiohttp-3.8.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:41bdc2ba359032e36c0e9de5a3bd00d6fb7ea558a6ce6b70acedf0da86458321"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14cd52ccf40006c7a6cd34a0f8663734e5363fd981807173faf3a017e202fec9"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d5b785c792802e7b275c420d84f3397668e9d49ab1cb52bd916b3b3ffcf09ad"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1bed815f3dc3d915c5c1e556c397c8667826fbc1b935d95b0ad680787896a358"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96603a562b546632441926cd1293cfcb5b69f0b4159e6077f7c7dbdfb686af4d"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d76e8b13161a202d14c9584590c4df4d068c9567c99506497bdd67eaedf36403"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e3f1e3f1a1751bb62b4a1b7f4e435afcdade6c17a4fd9b9d43607cebd242924a"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:76b36b3124f0223903609944a3c8bf28a599b2cc0ce0be60b45211c8e9be97f8"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:a2ece4af1f3c967a4390c284797ab595a9f1bc1130ef8b01828915a05a6ae684"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:16d330b3b9db87c3883e565340d292638a878236418b23cc8b9b11a054aaa887"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:42c89579f82e49db436b69c938ab3e1559e5a4409eb8639eb4143989bc390f2f"}, + {file = "aiohttp-3.8.6-cp311-cp311-win32.whl", hash = "sha256:efd2fcf7e7b9d7ab16e6b7d54205beded0a9c8566cb30f09c1abe42b4e22bdcb"}, + {file = "aiohttp-3.8.6-cp311-cp311-win_amd64.whl", hash = "sha256:3b2ab182fc28e7a81f6c70bfbd829045d9480063f5ab06f6e601a3eddbbd49a0"}, + {file = "aiohttp-3.8.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fdee8405931b0615220e5ddf8cd7edd8592c606a8e4ca2a00704883c396e4479"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d25036d161c4fe2225d1abff2bd52c34ed0b1099f02c208cd34d8c05729882f0"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d791245a894be071d5ab04bbb4850534261a7d4fd363b094a7b9963e8cdbd31"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0cccd1de239afa866e4ce5c789b3032442f19c261c7d8a01183fd956b1935349"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f13f60d78224f0dace220d8ab4ef1dbc37115eeeab8c06804fec11bec2bbd07"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a9b5a0606faca4f6cc0d338359d6fa137104c337f489cd135bb7fbdbccb1e39"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:13da35c9ceb847732bf5c6c5781dcf4780e14392e5d3b3c689f6d22f8e15ae31"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:4d4cbe4ffa9d05f46a28252efc5941e0462792930caa370a6efaf491f412bc66"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:229852e147f44da0241954fc6cb910ba074e597f06789c867cb7fb0621e0ba7a"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:713103a8bdde61d13490adf47171a1039fd880113981e55401a0f7b42c37d071"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:45ad816b2c8e3b60b510f30dbd37fe74fd4a772248a52bb021f6fd65dff809b6"}, + {file = "aiohttp-3.8.6-cp36-cp36m-win32.whl", hash = "sha256:2b8d4e166e600dcfbff51919c7a3789ff6ca8b3ecce16e1d9c96d95dd569eb4c"}, + {file = "aiohttp-3.8.6-cp36-cp36m-win_amd64.whl", hash = "sha256:0912ed87fee967940aacc5306d3aa8ba3a459fcd12add0b407081fbefc931e53"}, + {file = "aiohttp-3.8.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e2a988a0c673c2e12084f5e6ba3392d76c75ddb8ebc6c7e9ead68248101cd446"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebf3fd9f141700b510d4b190094db0ce37ac6361a6806c153c161dc6c041ccda"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3161ce82ab85acd267c8f4b14aa226047a6bee1e4e6adb74b798bd42c6ae1f80"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95fc1bf33a9a81469aa760617b5971331cdd74370d1214f0b3109272c0e1e3c"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c43ecfef7deaf0617cee936836518e7424ee12cb709883f2c9a1adda63cc460"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca80e1b90a05a4f476547f904992ae81eda5c2c85c66ee4195bb8f9c5fb47f28"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:90c72ebb7cb3a08a7f40061079817133f502a160561d0675b0a6adf231382c92"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bb54c54510e47a8c7c8e63454a6acc817519337b2b78606c4e840871a3e15349"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:de6a1c9f6803b90e20869e6b99c2c18cef5cc691363954c93cb9adeb26d9f3ae"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:a3628b6c7b880b181a3ae0a0683698513874df63783fd89de99b7b7539e3e8a8"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fc37e9aef10a696a5a4474802930079ccfc14d9f9c10b4662169671ff034b7df"}, + {file = "aiohttp-3.8.6-cp37-cp37m-win32.whl", hash = "sha256:f8ef51e459eb2ad8e7a66c1d6440c808485840ad55ecc3cafefadea47d1b1ba2"}, + {file = "aiohttp-3.8.6-cp37-cp37m-win_amd64.whl", hash = "sha256:b2fe42e523be344124c6c8ef32a011444e869dc5f883c591ed87f84339de5976"}, + {file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9e2ee0ac5a1f5c7dd3197de309adfb99ac4617ff02b0603fd1e65b07dc772e4b"}, + {file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01770d8c04bd8db568abb636c1fdd4f7140b284b8b3e0b4584f070180c1e5c62"}, + {file = "aiohttp-3.8.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3c68330a59506254b556b99a91857428cab98b2f84061260a67865f7f52899f5"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89341b2c19fb5eac30c341133ae2cc3544d40d9b1892749cdd25892bbc6ac951"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71783b0b6455ac8f34b5ec99d83e686892c50498d5d00b8e56d47f41b38fbe04"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f628dbf3c91e12f4d6c8b3f092069567d8eb17814aebba3d7d60c149391aee3a"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04691bc6601ef47c88f0255043df6f570ada1a9ebef99c34bd0b72866c217ae"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee912f7e78287516df155f69da575a0ba33b02dd7c1d6614dbc9463f43066e3"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9c19b26acdd08dd239e0d3669a3dddafd600902e37881f13fbd8a53943079dbc"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:99c5ac4ad492b4a19fc132306cd57075c28446ec2ed970973bbf036bcda1bcc6"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f0f03211fd14a6a0aed2997d4b1c013d49fb7b50eeb9ffdf5e51f23cfe2c77fa"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:8d399dade330c53b4106160f75f55407e9ae7505263ea86f2ccca6bfcbdb4921"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ec4fd86658c6a8964d75426517dc01cbf840bbf32d055ce64a9e63a40fd7b771"}, + {file = "aiohttp-3.8.6-cp38-cp38-win32.whl", hash = "sha256:33164093be11fcef3ce2571a0dccd9041c9a93fa3bde86569d7b03120d276c6f"}, + {file = "aiohttp-3.8.6-cp38-cp38-win_amd64.whl", hash = "sha256:bdf70bfe5a1414ba9afb9d49f0c912dc524cf60141102f3a11143ba3d291870f"}, + {file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d52d5dc7c6682b720280f9d9db41d36ebe4791622c842e258c9206232251ab2b"}, + {file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ac39027011414dbd3d87f7edb31680e1f430834c8cef029f11c66dad0670aa5"}, + {file = "aiohttp-3.8.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3f5c7ce535a1d2429a634310e308fb7d718905487257060e5d4598e29dc17f0b"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b30e963f9e0d52c28f284d554a9469af073030030cef8693106d918b2ca92f54"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:918810ef188f84152af6b938254911055a72e0f935b5fbc4c1a4ed0b0584aed1"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:002f23e6ea8d3dd8d149e569fd580c999232b5fbc601c48d55398fbc2e582e8c"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fcf3eabd3fd1a5e6092d1242295fa37d0354b2eb2077e6eb670accad78e40e1"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:255ba9d6d5ff1a382bb9a578cd563605aa69bec845680e21c44afc2670607a95"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d67f8baed00870aa390ea2590798766256f31dc5ed3ecc737debb6e97e2ede78"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:86f20cee0f0a317c76573b627b954c412ea766d6ada1a9fcf1b805763ae7feeb"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:39a312d0e991690ccc1a61f1e9e42daa519dcc34ad03eb6f826d94c1190190dd"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e827d48cf802de06d9c935088c2924e3c7e7533377d66b6f31ed175c1620e05e"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bd111d7fc5591ddf377a408ed9067045259ff2770f37e2d94e6478d0f3fc0c17"}, + {file = "aiohttp-3.8.6-cp39-cp39-win32.whl", hash = "sha256:caf486ac1e689dda3502567eb89ffe02876546599bbf915ec94b1fa424eeffd4"}, + {file = "aiohttp-3.8.6-cp39-cp39-win_amd64.whl", hash = "sha256:3f0e27e5b733803333bb2371249f41cf42bae8884863e8e8965ec69bebe53132"}, + {file = "aiohttp-3.8.6.tar.gz", hash = "sha256:b0cf2a4501bff9330a8a5248b4ce951851e415bdcce9dc158e76cfd55e15085c"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +attrs = ">=17.3.0" +charset-normalizer = ">=2.0,<4.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "cchardet"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} + +[[package]] +name = "anyio" +version = "3.7.1" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"}, + {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"}, +] + +[package.dependencies] +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"] +test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (<0.22)"] + +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "backports-zoneinfo" +version = "0.2.1" +description = "Backport of the standard library zoneinfo module" +optional = false +python-versions = ">=3.6" +files = [ + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"}, + {file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"}, +] + +[package.extras] +tzdata = ["tzdata"] + +[[package]] +name = "boto3" +version = "1.26.76" +description = "The AWS SDK for Python" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "boto3-1.26.76-py3-none-any.whl", hash = "sha256:b4c2969b7677762914394b8273cc1905dfe5b71f250741c1a575487ae357e729"}, + {file = "boto3-1.26.76.tar.gz", hash = "sha256:30c7d967ed1c6b5a05643e42cae9d4d36c3f1cb6782637ddc7007a104cfd9027"}, +] + +[package.dependencies] +botocore = ">=1.29.76,<1.30.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.6.0,<0.7.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "botocore" +version = "1.29.76" +description = "Low-level, data-driven core of boto 3." +optional = false +python-versions = ">= 3.7" +files = [ + {file = "botocore-1.29.76-py3-none-any.whl", hash = "sha256:70735b00cd529f152992231ca6757e458e5ec25db43767b3526e9a35b2f143b7"}, + {file = "botocore-1.29.76.tar.gz", hash = "sha256:c2f67b6b3f8acf2968eafca06526f07b9fb0d27bac4c68a635d51abb675134a7"}, +] + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = ">=1.25.4,<1.27" + +[package.extras] +crt = ["awscrt (==0.16.9)"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +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 = "deb_structurer" +version = "0.1.2" +description = "Универсальный пакет формирования структуры deb-пакета для poetry проекта" +optional = false +python-versions = "*" +files = [] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "fastapi" +version = "0.92.0" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.7" +files = [ + {file = "fastapi-0.92.0-py3-none-any.whl", hash = "sha256:ae7b97c778e2f2ec3fb3cb4fb14162129411d99907fb71920f6d69a524340ebf"}, + {file = "fastapi-0.92.0.tar.gz", hash = "sha256:023a0f5bd2c8b2609014d3bba1e14a1d7df96c6abea0a73070621c9862b9a4de"}, +] + +[package.dependencies] +pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" +starlette = ">=0.25.0,<0.26.0" + +[package.extras] +all = ["email-validator (>=1.1.1)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +dev = ["pre-commit (>=2.17.0,<3.0.0)", "ruff (==0.0.138)", "uvicorn[standard] (>=0.12.0,<0.21.0)"] +doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer[all] (>=0.6.1,<0.8.0)"] +test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==22.10.0)", "coverage[toml] (>=6.5.0,<8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "pyyaml (>=5.3.1,<7.0.0)", "ruff (==0.0.138)", "sqlalchemy (>=1.3.18,<1.4.43)", "types-orjson (==3.6.2)", "types-ujson (==5.6.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] + +[[package]] +name = "frozenlist" +version = "1.4.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, + {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, + {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, + {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, + {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, + {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, + {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, + {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, + {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, + {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, +] + +[[package]] +name = "gql" +version = "3.4.1" +description = "GraphQL client for Python" +optional = false +python-versions = "*" +files = [ + {file = "gql-3.4.1-py2.py3-none-any.whl", hash = "sha256:315624ca0f4d571ef149d455033ebd35e45c1a13f18a059596aeddcea99135cf"}, + {file = "gql-3.4.1.tar.gz", hash = "sha256:11dc5d8715a827f2c2899593439a4f36449db4f0eafa5b1ea63948f8a2f8c545"}, +] + +[package.dependencies] +backoff = ">=1.11.1,<3.0" +graphql-core = ">=3.2,<3.3" +yarl = ">=1.6,<2.0" + +[package.extras] +aiohttp = ["aiohttp (>=3.7.1,<3.9.0)"] +all = ["aiohttp (>=3.7.1,<3.9.0)", "botocore (>=1.21,<2)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26,<2)", "websockets (>=10,<11)", "websockets (>=9,<10)"] +botocore = ["botocore (>=1.21,<2)"] +dev = ["aiofiles", "aiohttp (>=3.7.1,<3.9.0)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "sphinx (>=3.0.0,<4)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "urllib3 (>=1.26,<2)", "vcrpy (==4.0.2)", "websockets (>=10,<11)", "websockets (>=9,<10)"] +requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26,<2)"] +test = ["aiofiles", "aiohttp (>=3.7.1,<3.9.0)", "botocore (>=1.21,<2)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26,<2)", "vcrpy (==4.0.2)", "websockets (>=10,<11)", "websockets (>=9,<10)"] +test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.0.2)"] +websockets = ["websockets (>=10,<11)", "websockets (>=9,<10)"] + +[[package]] +name = "graphql-core" +version = "3.2.1" +description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL." +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "graphql-core-3.2.1.tar.gz", hash = "sha256:9d1bf141427b7d54be944587c8349df791ce60ade2e3cccaf9c56368c133c201"}, + {file = "graphql_core-3.2.1-py3-none-any.whl", hash = "sha256:f83c658e4968998eed1923a2e3e3eddd347e005ac0315fbb7ca4d70ea9156323"}, +] + +[[package]] +name = "greenlet" +version = "2.0.0" +description = "Lightweight in-process concurrent programming" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +files = [ + {file = "greenlet-2.0.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:4be4dedbd2fa9b7c35627f322d6d3139cb125bc18d5ef2f40237990850ea446f"}, + {file = "greenlet-2.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:75c022803de010294366f3608d4bba3e346693b1b7427b79d57e3d924ed03838"}, + {file = "greenlet-2.0.0-cp27-cp27m-win32.whl", hash = "sha256:4a1953465b7651073cffde74ed7d121e602ef9a9740d09ee137b01879ac15a2f"}, + {file = "greenlet-2.0.0-cp27-cp27m-win_amd64.whl", hash = "sha256:a65205e6778142528978b4acca76888e7e7f0be261e395664e49a5c21baa2141"}, + {file = "greenlet-2.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d71feebf5c8041c80dfda76427e14e3ca00bca042481bd3e9612a9d57b2cbbf7"}, + {file = "greenlet-2.0.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:f7edbd2957f72aea357241fe42ffc712a8e9b8c2c42f24e2ef5d97b255f66172"}, + {file = "greenlet-2.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79687c48e7f564be40c46b3afea6d141b8d66ffc2bc6147e026d491c6827954a"}, + {file = "greenlet-2.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a245898ec5e9ca0bc87a63e4e222cc633dc4d1f1a0769c34a625ad67edb9f9de"}, + {file = "greenlet-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adcf45221f253b3a681c99da46fa6ac33596fa94c2f30c54368f7ee1c4563a39"}, + {file = "greenlet-2.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3dc294afebf2acfd029373dbf3d01d36fd8d6888a03f5a006e2d690f66b153d9"}, + {file = "greenlet-2.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1cfeae4dda32eb5c64df05d347c4496abfa57ad16a90082798a2bba143c6c854"}, + {file = "greenlet-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:d58d4b4dc82e2d21ebb7dd7d3a6d370693b2236a1407fe3988dc1d4ea07575f9"}, + {file = "greenlet-2.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0d7efab8418c1fb3ea00c4abb89e7b0179a952d0d53ad5fcff798ca7440f8e8"}, + {file = "greenlet-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:f8a10e14238407be3978fa6d190eb3724f9d766655fefc0134fd5482f1fb0108"}, + {file = "greenlet-2.0.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:98b848a0b75e76b446dc71fdbac712d9078d96bb1c1607f049562dde1f8801e1"}, + {file = "greenlet-2.0.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:8e8dbad9b4f4c3e37898914cfccb7c4f00dbe3146333cfe52a1a3103cc2ff97c"}, + {file = "greenlet-2.0.0-cp35-cp35m-win32.whl", hash = "sha256:069a8a557541a04518dc3beb9a78637e4e6b286814849a2ecfac529eaa78562b"}, + {file = "greenlet-2.0.0-cp35-cp35m-win_amd64.whl", hash = "sha256:cc211c2ff5d3b2ba8d557a71e3b4f0f0a2020067515143a9516ea43884271192"}, + {file = "greenlet-2.0.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:d4e7642366e638f45d70c5111590a56fbd0ffb7f474af20c6c67c01270bcf5cf"}, + {file = "greenlet-2.0.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e7a0dca752b4e3395890ab4085c3ec3838d73714261914c01b53ed7ea23b5867"}, + {file = "greenlet-2.0.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8c67ecda450ad4eac7837057f5deb96effa836dacaf04747710ccf8eeb73092"}, + {file = "greenlet-2.0.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3cc1abaf47cfcfdc9ac0bdff173cebab22cd54e9e3490135a4a9302d0ff3b163"}, + {file = "greenlet-2.0.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efdbbbf7b6c8d5be52977afa65b9bb7b658bab570543280e76c0fabc647175ed"}, + {file = "greenlet-2.0.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:7acaa51355d5b9549d474dc71be6846ee9a8f2cb82f4936e5efa7a50bbeb94ad"}, + {file = "greenlet-2.0.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2be628bca0395610da08921f9376dd14317f37256d41078f5c618358467681e1"}, + {file = "greenlet-2.0.0-cp36-cp36m-win32.whl", hash = "sha256:eca9c0473de053dcc92156dd62c38c3578628b536c7f0cd66e655e211c14ac32"}, + {file = "greenlet-2.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9a4a9fea68fd98814999d91ea585e49ed68d7e199a70bef13a857439f60a4609"}, + {file = "greenlet-2.0.0-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:6b28420ae290bfbf5d827f976abccc2f74f0a3f5e4fb69b66acf98f1cbe95e7e"}, + {file = "greenlet-2.0.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:2b8e1c939b363292ecc93999fb1ad53ffc5d0aac8e933e4362b62365241edda5"}, + {file = "greenlet-2.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c5ddadfe40e903c6217ed2b95a79f49e942bb98527547cc339fc7e43a424aad"}, + {file = "greenlet-2.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e5ead803b11b60b347e08e0f37234d9a595f44a6420026e47bcaf94190c3cd6"}, + {file = "greenlet-2.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b89b78ffb516c2921aa180c2794082666e26680eef05996b91f46127da24d964"}, + {file = "greenlet-2.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:939963d0137ec92540d95b68b7f795e8dbadce0a1fca53e3e7ef8ddc18ee47cb"}, + {file = "greenlet-2.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c1e93ef863810fba75faf418f0861dbf59bfe01a7b5d0a91d39603df58d3d3fa"}, + {file = "greenlet-2.0.0-cp37-cp37m-win32.whl", hash = "sha256:6fd342126d825b76bf5b49717a7c682e31ed1114906cdec7f5a0c2ff1bc737a7"}, + {file = "greenlet-2.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5392ddb893e7fba237b988f846c4a80576557cc08664d56dc1a69c5c02bdc80c"}, + {file = "greenlet-2.0.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:b4fd73b62c1038e7ee938b1de328eaa918f76aa69c812beda3aff8a165494201"}, + {file = "greenlet-2.0.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:0ba0f2e5c4a8f141952411e356dba05d6fe0c38325ee0e4f2d0c6f4c2c3263d5"}, + {file = "greenlet-2.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8bacecee0c9348ab7c95df810e12585e9e8c331dfc1e22da4ed0bd635a5f483"}, + {file = "greenlet-2.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:341053e0a96d512315c27c34fad4672c4573caf9eb98310c39e7747645c88d8b"}, + {file = "greenlet-2.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49fcdd8ae391ffabb3b672397b58a9737aaff6b8cae0836e8db8ff386fcea802"}, + {file = "greenlet-2.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c3aa7d3bc545162a6676445709b24a2a375284dc5e2f2432d58b80827c2bd91c"}, + {file = "greenlet-2.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9d8dca31a39dd9f25641559b8cdf9066168c682dfcfbe0f797f03e4c9718a63a"}, + {file = "greenlet-2.0.0-cp38-cp38-win32.whl", hash = "sha256:aa2b371c3633e694d043d6cec7376cb0031c6f67029f37eef40bda105fd58753"}, + {file = "greenlet-2.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:0fa2a66fdf0d09929e79f786ad61529d4e752f452466f7ddaa5d03caf77a603d"}, + {file = "greenlet-2.0.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:e7ec3f2465ba9b7d25895307abe1c1c101a257c54b9ea1522bbcbe8ca8793735"}, + {file = "greenlet-2.0.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:99e9851e40150504474915605649edcde259a4cd9bce2fcdeb4cf33ad0b5c293"}, + {file = "greenlet-2.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20bf68672ae14ef2e2e6d3ac1f308834db1d0b920b3b0674eef48b2dce0498dd"}, + {file = "greenlet-2.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30198bccd774f9b6b1ba7564a0d02a79dd1fe926cfeb4107856fe16c9dfb441c"}, + {file = "greenlet-2.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d65d7d1ff64fb300127d2ffd27db909de4d21712a5dde59a3ad241fb65ee83d7"}, + {file = "greenlet-2.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2f5d396a5457458460b0c28f738fc8ab2738ee61b00c3f845c7047a333acd96c"}, + {file = "greenlet-2.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09f00f9938eb5ae1fe203558b56081feb0ca34a2895f8374cd01129ddf4d111c"}, + {file = "greenlet-2.0.0-cp39-cp39-win32.whl", hash = "sha256:089e123d80dbc6f61fff1ff0eae547b02c343d50968832716a7b0a33bea5f792"}, + {file = "greenlet-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:bc283f99a4815ef70cad537110e3e03abcef56ab7d005ba9a8c6ec33054ce9c0"}, + {file = "greenlet-2.0.0.tar.gz", hash = "sha256:6c66f0da8049ee3c126b762768179820d4c0ae0ca46ae489039e4da2fae39a52"}, +] + +[package.extras] +docs = ["Sphinx", "docutils (<0.18)"] +test = ["faulthandler", "objgraph"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +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 = "jmespath" +version = "1.0.1" +description = "JSON Matching Expressions" +optional = false +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 = "multidict" +version = "6.0.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + +[[package]] +name = "pika" +version = "1.3.2" +description = "Pika Python AMQP Client Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pika-1.3.2-py3-none-any.whl", hash = "sha256:0779a7c1fafd805672796085560d290213a465e4f6f76a6fb19e378d8041a14f"}, + {file = "pika-1.3.2.tar.gz", hash = "sha256:b2a327ddddf8570b4965b3576ac77091b850262d34ce8c1d8cb4e4146aa4145f"}, +] + +[package.extras] +gevent = ["gevent"] +tornado = ["tornado"] +twisted = ["twisted"] + +[[package]] +name = "pika-stubs" +version = "0.1.3" +description = "Mypy plugin and stubs for Pika" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pika-stubs-0.1.3.tar.gz", hash = "sha256:aaa78fa9f52eb3591b6073fbbe2607567405d1857be268d447bea252e22dd6cf"}, +] + +[package.extras] +dev = ["flake8 (>=3.8.3,<3.9.0)", "mypy (>=0.780,<1.0)"] + +[[package]] +name = "psycopg" +version = "3.1.10" +description = "PostgreSQL database adapter for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psycopg-3.1.10-py3-none-any.whl", hash = "sha256:8bbeddae5075c7890b2fa3e3553440376d3c5e28418335dee3c3656b06fa2b52"}, + {file = "psycopg-3.1.10.tar.gz", hash = "sha256:15b25741494344c24066dc2479b0f383dd1b82fa5e75612fa4fa5bb30726e9b6"}, +] + +[package.dependencies] +"backports.zoneinfo" = {version = ">=0.2.0", markers = "python_version < \"3.9\""} +typing-extensions = ">=4.1" +tzdata = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +binary = ["psycopg-binary (==3.1.10)"] +c = ["psycopg-c (==3.1.10)"] +dev = ["black (>=23.1.0)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.4.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"] +docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"] +pool = ["psycopg-pool"] +test = ["anyio (>=3.6.2)", "mypy (>=1.4.1)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"] + +[[package]] +name = "pydantic" +version = "1.10.13" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, + {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, + {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, + {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, + {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, + {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, + {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, + {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, + {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, +] + +[package.dependencies] +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pydantic-core" +version = "2.6.3" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad"}, + {file = "pydantic_core-2.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728"}, + {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd"}, + {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e"}, + {file = "pydantic_core-2.6.3-cp310-none-win32.whl", hash = "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7"}, + {file = "pydantic_core-2.6.3-cp310-none-win_amd64.whl", hash = "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"}, + {file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"}, + {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"}, + {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"}, + {file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"}, + {file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"}, + {file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"}, + {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"}, + {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"}, + {file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"}, + {file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"}, + {file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58"}, + {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6"}, + {file = "pydantic_core-2.6.3-cp37-none-win32.whl", hash = "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b"}, + {file = "pydantic_core-2.6.3-cp37-none-win_amd64.whl", hash = "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db"}, + {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec"}, + {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb"}, + {file = "pydantic_core-2.6.3-cp38-none-win32.whl", hash = "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc"}, + {file = "pydantic_core-2.6.3-cp38-none-win_amd64.whl", hash = "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465"}, + {file = "pydantic_core-2.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f"}, + {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76"}, + {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef"}, + {file = "pydantic_core-2.6.3-cp39-none-win32.whl", hash = "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a"}, + {file = "pydantic_core-2.6.3-cp39-none-win_amd64.whl", hash = "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"}, + {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"}, + {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"}, + {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"}, + {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"}, + {file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pygost" +version = "5.12" +description = "Pure Python GOST cryptographic functions library" +optional = false +python-versions = "*" +files = [] +develop = true + +[package.source] +type = "directory" +url = "xmlrpcserver/deps/pygost-5.12" + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +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" + +[[package]] +name = "python-multipart" +version = "0.0.6" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, + {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, +] + +[package.extras] +dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "s3transfer" +version = "0.6.2" +description = "An Amazon S3 Transfer Manager" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "s3transfer-0.6.2-py3-none-any.whl", hash = "sha256:b014be3a8a2aab98cfe1abc7229cc5a9a0cf05eb9c1f2b86b230fd8df3f78084"}, + {file = "s3transfer-0.6.2.tar.gz", hash = "sha256:cab66d3380cca3e70939ef2255d01cd8aece6a4907a9528740f668c4b0611861"}, +] + +[package.dependencies] +botocore = ">=1.12.36,<2.0a.0" + +[package.extras] +crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +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" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +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 = "sqlalchemy" +version = "2.0.20" +description = "Database Abstraction Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759b51346aa388c2e606ee206c0bc6f15a5299f6174d1e10cadbe4530d3c7a98"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1506e988ebeaaf316f183da601f24eedd7452e163010ea63dbe52dc91c7fc70e"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5768c268df78bacbde166b48be788b83dddaa2a5974b8810af422ddfe68a9bc8"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3f0dd6d15b6dc8b28a838a5c48ced7455c3e1fb47b89da9c79cc2090b072a50"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:243d0fb261f80a26774829bc2cee71df3222587ac789b7eaf6555c5b15651eed"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6eb6d77c31e1bf4268b4d61b549c341cbff9842f8e115ba6904249c20cb78a61"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-win32.whl", hash = "sha256:bcb04441f370cbe6e37c2b8d79e4af9e4789f626c595899d94abebe8b38f9a4d"}, + {file = "SQLAlchemy-2.0.20-cp310-cp310-win_amd64.whl", hash = "sha256:d32b5ffef6c5bcb452723a496bad2d4c52b346240c59b3e6dba279f6dcc06c14"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd81466bdbc82b060c3c110b2937ab65ace41dfa7b18681fdfad2f37f27acdd7"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6fe7d61dc71119e21ddb0094ee994418c12f68c61b3d263ebaae50ea8399c4d4"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4e571af672e1bb710b3cc1a9794b55bce1eae5aed41a608c0401885e3491179"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3364b7066b3c7f4437dd345d47271f1251e0cfb0aba67e785343cdbdb0fff08c"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1be86ccea0c965a1e8cd6ccf6884b924c319fcc85765f16c69f1ae7148eba64b"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1d35d49a972649b5080557c603110620a86aa11db350d7a7cb0f0a3f611948a0"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-win32.whl", hash = "sha256:27d554ef5d12501898d88d255c54eef8414576f34672e02fe96d75908993cf53"}, + {file = "SQLAlchemy-2.0.20-cp311-cp311-win_amd64.whl", hash = "sha256:411e7f140200c02c4b953b3dbd08351c9f9818d2bd591b56d0fa0716bd014f1e"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c6aceebbc47db04f2d779db03afeaa2c73ea3f8dcd3987eb9efdb987ffa09a3"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d3f175410a6db0ad96b10bfbb0a5530ecd4fcf1e2b5d83d968dd64791f810ed"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea8186be85da6587456c9ddc7bf480ebad1a0e6dcbad3967c4821233a4d4df57"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c3d99ba99007dab8233f635c32b5cd24fb1df8d64e17bc7df136cedbea427897"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:76fdfc0f6f5341987474ff48e7a66c3cd2b8a71ddda01fa82fedb180b961630a"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-win32.whl", hash = "sha256:d3793dcf5bc4d74ae1e9db15121250c2da476e1af8e45a1d9a52b1513a393459"}, + {file = "SQLAlchemy-2.0.20-cp37-cp37m-win_amd64.whl", hash = "sha256:79fde625a0a55220d3624e64101ed68a059c1c1f126c74f08a42097a72ff66a9"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:599ccd23a7146e126be1c7632d1d47847fa9f333104d03325c4e15440fc7d927"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1a58052b5a93425f656675673ef1f7e005a3b72e3f2c91b8acca1b27ccadf5f4"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79543f945be7a5ada9943d555cf9b1531cfea49241809dd1183701f94a748624"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63e73da7fb030ae0a46a9ffbeef7e892f5def4baf8064786d040d45c1d6d1dc5"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3ce5e81b800a8afc870bb8e0a275d81957e16f8c4b62415a7b386f29a0cb9763"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb0d3e94c2a84215532d9bcf10229476ffd3b08f481c53754113b794afb62d14"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-win32.whl", hash = "sha256:8dd77fd6648b677d7742d2c3cc105a66e2681cc5e5fb247b88c7a7b78351cf74"}, + {file = "SQLAlchemy-2.0.20-cp38-cp38-win_amd64.whl", hash = "sha256:6f8a934f9dfdf762c844e5164046a9cea25fabbc9ec865c023fe7f300f11ca4a"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:26a3399eaf65e9ab2690c07bd5cf898b639e76903e0abad096cd609233ce5208"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4cde2e1096cbb3e62002efdb7050113aa5f01718035ba9f29f9d89c3758e7e4e"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b09ba72e4e6d341bb5bdd3564f1cea6095d4c3632e45dc69375a1dbe4e26ec"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b74eeafaa11372627ce94e4dc88a6751b2b4d263015b3523e2b1e57291102f0"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:77d37c1b4e64c926fa3de23e8244b964aab92963d0f74d98cbc0783a9e04f501"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:eefebcc5c555803065128401a1e224a64607259b5eb907021bf9b175f315d2a6"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-win32.whl", hash = "sha256:3423dc2a3b94125094897118b52bdf4d37daf142cbcf26d48af284b763ab90e9"}, + {file = "SQLAlchemy-2.0.20-cp39-cp39-win_amd64.whl", hash = "sha256:5ed61e3463021763b853628aef8bc5d469fe12d95f82c74ef605049d810f3267"}, + {file = "SQLAlchemy-2.0.20-py3-none-any.whl", hash = "sha256:63a368231c53c93e2b67d0c5556a9836fdcd383f7e3026a39602aad775b14acf"}, + {file = "SQLAlchemy-2.0.20.tar.gz", hash = "sha256:ca8a5ff2aa7f3ade6c498aaafce25b1eaeabe4e42b73e25519183e4566a16fc6"}, +] + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +typing-extensions = ">=4.2.0" + +[package.extras] +aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] +aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] +asyncio = ["greenlet (!=0.4.17)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] +mssql = ["pyodbc"] +mssql-pymssql = ["pymssql"] +mssql-pyodbc = ["pyodbc"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"] +mysql-connector = ["mysql-connector-python"] +oracle = ["cx-oracle (>=7)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] +postgresql-psycopg2binary = ["psycopg2-binary"] +postgresql-psycopg2cffi = ["psycopg2cffi"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] +sqlcipher = ["sqlcipher3-binary"] + +[[package]] +name = "starlette" +version = "0.25.0" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.7" +files = [ + {file = "starlette-0.25.0-py3-none-any.whl", hash = "sha256:774f1df1983fd594b9b6fb3ded39c2aa1979d10ac45caac0f4255cbe2acb8628"}, + {file = "starlette-0.25.0.tar.gz", hash = "sha256:854c71e73736c429c2bdb07801f2c76c9cba497e7c3cf4988fde5e95fe4cdb3c"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "urllib3" +version = "1.26.18" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, + {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, +] + +[package.extras] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "uvicorn" +version = "0.20.0" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.7" +files = [ + {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"}, + {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"}, +] + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "2c4a54b4c807fdfc65ad9457c3b328000417cc167bb15c9effa17bd43600485b" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f07b920 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,53 @@ +[tool.poetry] +name = "xmlrpcserver" +version = "0.1.2" +description = "" +authors = ["Sitronics "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.8" +aiohttp = "3.8.6" +aiosignal = "1.3.1" +annotated-types = "0.5.0" +anyio = "3.7.1" +async-timeout = "4.0.3" +attrs = "23.1.0" +backoff = "2.2.1" +boto3 = "1.26.76" +botocore = "1.29.76" +certifi = "2023.7.22" +charset-normalizer = "3.3.2" +click = "8.1.7" +fastapi = "0.92.0" +frozenlist = "1.4.0" +gql = "3.4.1" +graphql-core = "3.2.1" +greenlet = "2.0.0" +h11 = "0.14.0" +idna = "3.4" +jmespath = "1.0.1" +multidict = "6.0.4" +pika = "1.3.2" +pika-stubs = "0.1.3" +psycopg = "3.1.10" +pydantic = "1.10.13" +pydantic_core = "2.6.3" +pygost = { path = "./xmlrpcserver/deps/pygost-5.12", develop = true } +python-dateutil = "2.8.2" +python-multipart = "0.0.6" +requests = "2.31.0" +s3transfer = "0.6.2" +six = "1.16.0" +sniffio = "1.3.0" +SQLAlchemy = "2.0.20" +typing_extensions = "4.8.0" +urllib3 = "1.26.18" +uvicorn = "0.20.0" +yarl = "1.9.2" +deb_structurer = "*" + + +[build-system] +requires = ["setuptools", "poetry_core>=1.0"] +build-backend = "poetry.core.masonry.api" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8ecf94b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,40 @@ +--find-links=deps +aiohttp==3.8.4 +aiosignal==1.3.1 +annotated-types==0.5.0 +anyio==3.7.1 +async-timeout==4.0.3 +attrs==23.1.0 +backoff==2.2.1 +boto3==1.28.37 +botocore==1.31.40 +certifi==2023.7.22 +charset-normalizer==3.2.0 +click==8.1.7 +fastapi==0.103.1 +frozenlist==1.4.0 +gql==3.5.0b5 +graphql-core==3.3.0a3 +greenlet==2.0.2 +h11==0.14.0 +idna==3.4 +jmespath==1.0.1 +multidict==6.0.4 +pika==1.3.2 +pika-stubs==0.1.3 +psycopg==3.1.10 +pydantic==2.3.0 +pydantic_core==2.6.3 +pygost==5.12 +python-dateutil==2.8.2 +python-multipart==0.0.6 +requests==2.31.0 +s3transfer==0.6.2 +six==1.16.0 +sniffio==1.3.0 +SQLAlchemy==2.0.20 +starlette==0.27.0 +typing_extensions==4.7.1 +urllib3==1.26 +uvicorn==0.23.2 +yarl==1.9.2 diff --git a/xmlrpcserver/__init__.py b/xmlrpcserver/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/xmlrpcserver/__main__.py b/xmlrpcserver/__main__.py new file mode 100644 index 0000000..a5ba9d7 --- /dev/null +++ b/xmlrpcserver/__main__.py @@ -0,0 +1,310 @@ +from tempfile import TemporaryDirectory +from typing import Optional, Any + +import pika +import threading +import time +from queue import Queue +import datetime +import json +from uuid import uuid4, UUID +from xmlrpc.server import SimpleXMLRPCServer +from xmlrpc.client import ServerProxy +import logging +import io +import zlib +import os.path +import requests +from .reqs_graphql import get_catalog, get_object +from pygost import gost34112012256 +import xml.etree.ElementTree as ET +from .reqs.request_xml_service import RequestXmlService +import zipfile +from .config import Config +from .zip import Zip +import boto3 +import xmlrpcserver.db as db +from sqlalchemy.orm import Session +from fastapi import FastAPI, Response, Form, UploadFile, File, Request +from fastapi.middleware.cors import CORSMiddleware +import uvicorn +from typing_extensions import Annotated +import pathlib +from shutil import make_archive + +NEW_REPLICATION_REQUEST = 99 +NEW_COMMIT_REQUEST = 98 +NEW_COMMIT_RESPONSE = 1098 +NEW_DATA_REQUEST = 97 +NEW_DATA_RESPONSE = 1097 + +connected = set() + +server: Optional[SimpleXMLRPCServer] = None + +logger = logging.getLogger('xmlrpcserver') + + +def s3_connection(): + return boto3.client('s3', endpoint_url=Config.s3_endpoint, + aws_access_key_id=Config.s3_key_id, + aws_secret_access_key=Config.s3_access_key) + + +def download_file(key: str, bucket: str, filename: str): + client = s3_connection() + obj = client.get_object(Bucket=bucket, Key=key) + with open(f"{filename}", 'wb') as f: + for chunk in obj['Body'].iter_chunks(chunk_size=4096): + f.write(chunk) + + +def upload_file(filename: str, key: str, bucket: str): + client = s3_connection() + with open(filename, 'rb') as f: + client.put_object(Body=f.read(), Bucket=bucket, Key=key) + + +def get_branch(bndname: str, scheme: str): + conn = db.connect_db() + with Session(conn) as session: + item = session.query(db.IncomeBranch).filter_by(scheme=scheme).join( + db.User).filter_by(bndname=bndname).one_or_none() + if item: + return item.branch, item.local_scheme + return None, None + + +def list_contents(dir_name): + logger.warning('list_contents(%s)', dir_name) + return os.listdir(dir_name) + + +def aud_add(message): + if not isinstance(message, list): + logger.warning(message) + return 'OK' + for item in message: + logger.warning(item) + return 'OK' + + +def auth_response(challenge, server_id, is_server): + # logging.debug(f'Challenge: {challenge}, Server: {server_id}, IsServer: {is_server}') + conn = db.connect_db() + with Session(conn) as session: + try: + user = session.query(db.User).filter((db.User.username == server_id)).one() + passwd = user.passwd + msg = '%s%s%s' % (challenge, server_id, passwd) + response = gost34112012256.new(msg.encode('utf-8')[::-1]).digest()[::-1].hex() + session.commit() + return {'error': False, 'response': response} + except Exception: + return {'error': True, 'response': 'Wrong user/bnd'} + + +def auth_challenge(): + logging.debug('get challenge') + return uuid4().hex + + +def put_object(params, files, url): + date = datetime.datetime.now() + req = ET.fromstring(params['query_data']) + obj = req.find('chart') + class_id = obj.get('Class') + con = OOConnectionParams(Config.oodb_schema, Config.oodb_host, Config.oodb_port, Config.oodb_dbname, + Config.oodb_username, Config.oodb_passwd, Config.oodb_schema) + ws = OODBWorkspace.ws(Config.oodb_schema) + if not ws.isInit(): + res = ws.init(con) + logger.warning(res) + logging.info(class_id) + fc = ws.featureClass(class_id) + feature = fc.createFeature('') + geom = Polygon.fromExtent(Envelope(0.0, 0.0, 1.0, 1.0, SRFactory.PZ9011())) + res = feature.setGeometry(geom) + for attr in obj.findall('Attribute'): + name = attr.get('name') + value = attr.get('value') + res &= feature.addAttribute(name, variantFromString(value)) + + assert len(files) == 1 + file = files[0] + dir = TemporaryDirectory() + with zipfile.ZipFile(file, 'r') as zip_ref: + zip_ref.extractall(dir.name) + + fp = pathlib.Path(dir.name) + for item in fp.glob('**/*'): + if not item.is_file(): + continue + fileVal = FileValue() + key = uuid4().hex + fileVal.fileName = variantToString(item.relative_to(dir.name)) + fileVal.key = variantToString(key) + fileVal.bucket = variantToString(Config.s3_bucket) + res &= feature.addAttribute('c1000', variantFromFileValue(fileVal)) + upload_file(str(item), key, Config.s3_bucket) + + ws.transaction() + res = ws.save() + ws.commit(f'Putobject from {params["to"]}') + ws.clearData(True) + + +def accept(params, files, url): + print(params, files, url) + logger.warning('Accept: ' + json.dumps(params, ensure_ascii=False)) + # TODO: run_task(params['query_type'], params, files, url) + return True + + +def onSent(params, files, callback_url): + logger.debug('OnSent') + logger.warning(params) + + +def onDelivered(params, files, callback_url): + logger.warning('onDelivered') + + +def bnd_connected(bnd_name: str): + logger.warning(f'{bnd_name} connected') + connected.add(bnd_name) + + +def bnd_disconnected(bnd_name: str): + logger.warning(f'{bnd_name} disconnected') + if bnd_name in connected: + connected.remove(bnd_name) + + +def xmlrpc_task(): + global server + server = SimpleXMLRPCServer(('0.0.0.0', 9000), logRequests=True, allow_none=True) + server.register_function(list_contents) + server.register_function(aud_add) + server.register_function(auth_response) + server.register_function(auth_challenge) + server.register_function(accept) + server.register_function(onSent) + server.register_function(onDelivered) + server.register_function(bnd_connected) + server.register_function(bnd_disconnected) + server.serve_forever() + + +app = FastAPI() +app.add_middleware(CORSMiddleware, + allow_origins=['http://10.10.8.24:3000'], + allow_credentials=True, + allow_methods=['*'], + allow_headers=['*'] + ) + + +@app.get("/") +async def fa_root(): + return {"message": "Hello World"} + + +@app.get("/login") +async def fa_login_get(response: Response): + response.set_cookie(key='sessionid', value='87654321') + response.set_cookie(key='csrftoken', value='12345678') + return {"login": "Ok", "success": True} + + +@app.post("/login") +async def fa_login(response: Response): + logger.warning('login action') + response.set_cookie(key='sessionid', value='87654321') + response.set_cookie(key='csrftoken', value='12345678') + return {"login": "Ok", "success": True} + + +@app.post('/webapi') +async def fa_webapi(request: Request): + body = await request.body() + logger.warning('webapi') + if 'has_perm' in body.decode('utf-8'): + return Response( + content='success1', + media_type='application/xml') + else: + return Response( + content='1', + media_type='application/xml') + + +@app.post("/api/easo/PutObject") +async def fa_put_object(response: Response, + object_attrs: Annotated[str, Form()], + object_file: Annotated[UploadFile, File()] + ): + date = datetime.datetime.now() + files = [{'name': object_file.filename, 'url': object_file.file.name, 'size': object_file.size}] + request_params = { + 'from': '', + 'to': '', + 'ts_added': date.timestamp(), + 'user_id': '0', + 'user_id_to': '0', + 'query_type': 6, + 'query_data': object_attrs, + } + put_object(request_params, files, None) + return {"Upload": "Ok"} + + +@app.get("/cr") +async def correction_replication(bnd_name: str, schema: str): + date = datetime.datetime.now() + rxmls = RequestXmlService() + res_id = uuid4().hex + + res = rxmls.get_request_document(res_id, None) + ET.SubElement(res, 'currentCommit', {'scheme': schema}) + params = { + 'from': f'tcp://{Config.self_bnd}', + 'to': f'tcp://{bnd_name}', + 'ts_added': date.timestamp(), + 'user_id': '0', + 'query_type': NEW_COMMIT_REQUEST, + 'query_data': ET.tostring(res, encoding='unicode', xml_declaration=True), + } + proxy = ServerProxy(Config.enserver) + try: + proxy.send(params, [], Config.ret_path) + except: + logger.error('Error sending') + + +def main(): + global connection + global server + global channel + + logger.setLevel(logging.INFO) + logger.warning('Use Control-C to exit') + + xmlrpc_thread = threading.Thread(target=xmlrpc_task) + xmlrpc_thread.start() + + try: + logger.warning('Start server') + uvicorn.run(app, host="0.0.0.0", port=8000) + except KeyboardInterrupt: + logger.warning('Exiting') + finally: + server.server_close() + + +def vers_key(e): + return e.version() + + +if __name__ == '__main__': + main() diff --git a/xmlrpcserver/config.py b/xmlrpcserver/config.py new file mode 100644 index 0000000..1e6eff7 --- /dev/null +++ b/xmlrpcserver/config.py @@ -0,0 +1,39 @@ + +class Config: + ret_path: str = 'http://10.10.8.81:9000/' + self_bnd: str = 'bnd127' + enserver: str = 'http://127.0.0.1:7000/xmlrpc' + remote_bnd: str = 'bnd128' + + pg_host: str = '10.10.8.83' + pg_port: int = 32101 + pg_dbname: str = 'db' + pg_username: str = 'postgres' + pg_password: str = 'Root12345678' + + oodb_host: str = '10.10.8.83' + oodb_port: int = 32100 + oodb_dbname: str = 'db' + oodb_username: str = 'postgres' + oodb_passwd: str = 'Root12345678' + oodb_schema: str = 'documents_src' + + rabbit_conn: str = 'amqp://user:password@10.10.8.83:31005/%2f' + rabbit_queue: str = 'ipd' + + ws_rabbit_params: dict = { + 'host': '10.10.8.83', + 'port': 31005, + 'exchange': 'ipd', + 'user': 'user', + 'password': 'password', + } + + s3_endpoint: str = 'http://10.10.8.83:31006' + s3_key_id: str = 's57' + s3_access_key: str = 'd9MMinLF3U8TLSj' + s3_bucket: str = 'files' + + gql_url: str = 'https://gql.ivazh.ru/graphql' + gql_download: str = 'https://gql.ivazh.ru/item/{key}' + gql_schema: str = 'pdim' diff --git a/xmlrpcserver/config/response2.json b/xmlrpcserver/config/response2.json new file mode 100644 index 0000000..d1121cb --- /dev/null +++ b/xmlrpcserver/config/response2.json @@ -0,0 +1,12 @@ +{ + "filestorage": { + "type": "s3", + "endpoint": "http://10.10.8.83:31006", + "key_id": "s57", + "access_key": "d9MMinLF3U8TLSj", + "download_path": "/tmp" + }, + "file_code": "c1000", + "name_code": "c122", + "use_version": true +} \ No newline at end of file diff --git a/xmlrpcserver/config/workspaces.json b/xmlrpcserver/config/workspaces.json new file mode 100644 index 0000000..cdd79f5 --- /dev/null +++ b/xmlrpcserver/config/workspaces.json @@ -0,0 +1,167 @@ +{ + "databases": { + "oodb_git": { + "host": "10.10.8.83", + "port": 32100, + "database": "db", + "user": "postgres", + "password": "Root12345678" + } + }, + "workspaces": { + "documents_src": { + "type": "documents", + "group": "src", + "database": "oodb_git", + "schema": "documents_src", + "alias": "Документы исходная" + }, + "documents_standard": { + "type": "documents", + "group": "order", + "database": "oodb_git", + "schema": "documents_standard", + "alias": "Документы эталон" + }, + "documents_standard_pub": { + "type": "documents", + "group": "order", + "database": "oodb_git", + "schema": "documents_standard", + "alias": "Документы публичная" + }, + "ood": { + "type": "npd", + "group": "src", + "database": "oodb_git", + "schema": "ood", + "alias": "ООБД исходные НПД", + "map_service": "VUE_APP_GISAIS_URL:/styles/ood/style.json" + }, + "oodb": { + "type": "oodb", + "group": "order", + "database": "oodb_git", + "schema": "kartap", + "alias": "ООДБ эталон", + "map_service": "VUE_APP_GISAIS_URL:/styles/oodb/style.json" + }, + "oodb_standard": { + "type": "oodb", + "group": "forming_standard", + "database": "oodb_git", + "schema": "kartap", + "alias": "ООДБ эталон", + "map_service": "VUE_APP_GISAIS_URL:/styles/oodb/style.json" + }, + "oodb_working": { + "type": "oodb", + "group": "forming_work", + "database": "oodb_git", + "schema": "kartap", + "alias": "ООДБ рабочая", + "map_service": "VUE_APP_GISAIS_URL:/styles/oodb_tech/style.json" + }, + "oodb_pub": { + "type": "oodb", + "group": "order", + "database": "oodb_git", + "schema": "kartap", + "alias": "ООБД публичная", + "map_service": "VUE_APP_GISAIS_URL:/styles/oodb/style.json" + }, + "regions": { + "type": "regions", + "database": "oodb_git", + "schema": "regions_hard", + "alias": "Регионы", + "map_service": "VUE_APP_GISAIS_URL_GK:/styles/regions/style.json" + }, + "regions_contour": { + "type": "regions", + "database": "oodb_git", + "schema": "regions_hard", + "alias": "Регионы", + "map_service": "VUE_APP_GISAIS_URL_GK:/styles/regions_contour/style.json" + }, + "npd_9": { + "type": "npd", + "database": "oodb_git", + "schema": "npd_9", + "alias": "НПД 9.0" + }, + "npd": { + "type": "npd", + "database": "oodb_git", + "schema": "initial", + "alias": "НПД 9.0" + }, + "npd_831": { + "type": "npd", + "group": "order", + "database": "oodb_git", + "schema": "npd_831", + "alias": "НПД 8.31" + }, + "updater_test": { + "type": "npd", + "group": "order", + "database": "oodb_git", + "schema": "npd_831_test", + "alias": "НПД 8.31 публичная" + }, + "lukoil": { + "type": "oodb", + "database": "oodb_git", + "schema": "lukoil", + "alias": "ЛУКОЙЛ", + "map_service": "VUE_APP_GISAIS_URL_GK:/styles/lukoil/style.json" + }, + "geocover": { + "type": "ecpz", + "group": "order", + "database": "oodb_git", + "schema": "coverage", + "alias": "ЕЦПЗ" + }, + "geocover_test": { + "type": "ecpz", + "database": "oodb_git", + "schema": "coverage", + "alias": "ЕЦПЗ тест" + }, + "gcmr": { + "type": "gcmr", + "group": "order", + "database": "oodb_git", + "schema": "gcmr", + "alias": "ГЦМР" + }, + "orders": { + "type": "system", + "database": "oodb_git", + "schema": "orders", + "alias": "Заказы" + }, + "ilo": { + "type": "system", + "database": "oodb_git", + "schema": "ilo", + "alias": "ИЛО" + }, + "raz_sgok": { + "type": "raz_sgok", + "database": "razsgok", + "schema": "razsgok", + "alias": "СГОК", + "map_service": "VUE_APP_GISAIS_URL_GK:/styles/raz_sgok/style.json" + }, + "raz_vtu": { + "type": "raz_vtu", + "database": "razvtu", + "schema": "razvtu", + "alias": "ВТУ", + "map_service": "VUE_APP_GISAIS_URL_GK:/styles/raz_vtu/style.json" + } + } +} diff --git a/xmlrpcserver/db.py b/xmlrpcserver/db.py new file mode 100644 index 0000000..f8e3a99 --- /dev/null +++ b/xmlrpcserver/db.py @@ -0,0 +1,165 @@ +from datetime import datetime +from typing import List, Optional +from sqlalchemy import create_engine, String, select, ForeignKey, Enum +from sqlalchemy.orm import Session, DeclarativeBase, Mapped, mapped_column, relationship +from .config import Config + + +def tow(day: int, hour: int, minute: int): + return minute + hour * 60 + day * 60 * 24 + + +class Base(DeclarativeBase): + pass + + +class User(Base): + __tablename__ = 'users' + + id: Mapped[int] = mapped_column(primary_key=True) + username: Mapped[str] + passwd: Mapped[str] + bndname: Mapped[str] + newbnd: Mapped[bool] + active: Mapped[bool] + upstream: Mapped[bool] + + profiles: Mapped[List['Profile']] = relationship( + back_populates='user', cascade='all, delete-orphan' + ) + + income_branches: Mapped[List['IncomeBranch']] = relationship( + back_populates='user', cascade='all, delete-orphan' + ) + + schedule: Mapped[List['Schedule']] = relationship( + back_populates='user', cascade='all, delete-orphan' + ) + + queue: Mapped[List['Queue']] = relationship( + back_populates='user', cascade='all, delete-orphan' + ) + + def __repr__(self) -> str: + return f'User(id={self.id!r}, username={self.username!r}, password={self.passwd!r}, newbnd={self.newbnd})' + + def to_dict(self) -> dict: + return { + 'id': self.id, + 'username': self.username, + 'bndname': self.bndname, + 'newbnd': self.newbnd, + 'active': self.active, + 'upstream': self.upstream, + 'profiles': [x.to_dict() for x in self.profiles], + 'schedule': [x.to_dict() for x in self.schedule], + 'queue': [x.to_dict() for x in self.queue], + 'income_branches': [x.to_dict() for x in self.income_branches], + } + + def is_active_now(self): + if not len(self.schedule): + return True + dt = datetime.now() + curr_tow = tow(dt.weekday(), dt.hour, dt.minute) + for x in self.schedule: + if (tow(x.day_start, x.hour_start, x.minute_start) <= curr_tow + <= tow(x.day_end, x.hour_end, x.minute_end)): + return True + return False + + +class Profile(Base): + __tablename__ = 'profiles' + + id: Mapped[int] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) + scheme: Mapped[str] + branch: Mapped[str] = mapped_column(String, nullable=True) + json: Mapped[str] = mapped_column(String, nullable=True) + + user: Mapped['User'] = relationship(back_populates='profiles') + + def to_dict(self) -> dict: + return { + 'id': self.id, + 'scheme': self.scheme, + 'branch': self.branch, + 'json': self.json, + } + + +class IncomeBranch(Base): + __tablename__ = 'income_branches' + + id: Mapped[int] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) + scheme: Mapped[str] + branch: Mapped[str] + local_scheme: Mapped[str] + + user: Mapped['User'] = relationship(back_populates='income_branches') + + def to_dict(self) -> dict: + return { + 'id': self.id, + 'scheme': self.scheme, + 'branch': self.branch, + 'local_scheme': self.local_scheme, + } + + +class Schedule(Base): + __tablename__ = 'schedule' + + id: Mapped[int] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) + day_start: Mapped[int] + hour_start: Mapped[int] + minute_start: Mapped[int] + day_end: Mapped[int] + hour_end: Mapped[int] + minute_end: Mapped[int] + + user: Mapped['User'] = relationship(back_populates='schedule') + + def to_dict(self) -> dict: + return { + 'id': self.id, + 'day_start': self.day_start, + 'hour_start': self.hour_start, + 'minute_start': self.minute_start, + 'day_end': self.day_end, + 'hour_end': self.hour_end, + 'minute_end': self.minute_end, + } + + +class Queue(Base): + __tablename__ = 'queue' + + id: Mapped[int] = mapped_column(primary_key=True) + user_id: Mapped[int] = mapped_column(ForeignKey('users.id')) + commit_id: Mapped[str] + schema: Mapped[str] + + user: Mapped['User'] = relationship(back_populates='queue') + + def to_dict(self) -> dict: + return { + 'id': self.id, + 'commit_id': self.commit_id, + 'schema': self.schema, + } + + +class Schemas(Base): + __tablename__ = 'schemas' + + id: Mapped[int] = mapped_column(primary_key=True) + schema: Mapped[str] + schema_type: Mapped[str] + + +def connect_db(): + return create_engine(f"postgresql+psycopg://{Config.pg_username}:{Config.pg_password}@{Config.pg_host}:{Config.pg_port}/{Config.pg_dbname}") diff --git a/xmlrpcserver/deps/infra-0.3-py3-none-any.whl b/xmlrpcserver/deps/infra-0.3-py3-none-any.whl new file mode 100644 index 0000000..5c64290 Binary files /dev/null and b/xmlrpcserver/deps/infra-0.3-py3-none-any.whl differ diff --git a/xmlrpcserver/deps/pygost-5.12/AUTHORS b/xmlrpcserver/deps/pygost-5.12/AUTHORS new file mode 100644 index 0000000..f047789 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/AUTHORS @@ -0,0 +1 @@ +* Sergey Matveev diff --git a/xmlrpcserver/deps/pygost-5.12/COPYING b/xmlrpcserver/deps/pygost-5.12/COPYING new file mode 100644 index 0000000..9a2708d --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/xmlrpcserver/deps/pygost-5.12/FAQ b/xmlrpcserver/deps/pygost-5.12/FAQ new file mode 100644 index 0000000..16cdce0 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/FAQ @@ -0,0 +1,24 @@ +Frequently asked questions +************************** + +My signature is not validated by other implementations. What is wrong? + + Try to reverse it ("sign[::-1]"). Try to swap its halves + ("sign[len(sign)/2:] + sign[:len(sign)/2]"). Try to reverse its + swapped halves too. + + It is GOST: do you expect serialization unification?! + +My signature is *still* not validated by other implementations! + + Try to reverse digest you are signing/verifying ("dgst[::-1]"). + + It is GOST: do you expect serialization unification?! + +Everything above did not help me. Does PyGOST sucks? + + No way! You still have not tried to reverse your binary private + key, public key and swap its halves. + + It is GOST: do you expect serialization unification?! + diff --git a/xmlrpcserver/deps/pygost-5.12/INSTALL b/xmlrpcserver/deps/pygost-5.12/INSTALL new file mode 100644 index 0000000..02914c6 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/INSTALL @@ -0,0 +1,64 @@ +Download +******** + +No additional dependencies except Python 2.7/3.x interpreter are +required. + + Preferable way is to download tarball with the signature: + + $ [fetch|wget] http://www.pygost.cypherpunks.ru/pygost-5.10.tar.zst + $ [fetch|wget] http://www.pygost.cypherpunks.ru/pygost-5.10.tar.zst.sig + $ gpg --verify pygost-5.10.tar.zst.sig pygost-5.10.tar.zst + $ zstd -d < pygost-5.10.tar.zst | tar xf - + $ cd pygost-5.10 + $ python setup.py install + + You can obtain releases source code prepared tarballs on +. + + But also you can use pip (*no* OpenPGP authentication is performed!) +with PyPI: + + $ echo pygost==5.10 --hash=sha256:TARBALL-HASH > requirements.txt + $ pip install --requirement requirements.txt + + You *have to* verify downloaded tarballs integrity and authenticity +to be sure that you retrieved trusted and untampered software. GNU +Privacy Guard (https://www.gnupg.org/) is used for that purpose. + + For the very first time it is necessary to get signing public key and +import it. It is provided below, but you should check alternative +resources. + +pub rsa2048/0xE6FD1269CD0C009E 2016-09-13 + F55A 7619 3A0C 323A A031 0E6B E6FD 1269 CD0C 009E +uid PyGOST releases + + • gost (http://lists.cypherpunks.ru/gost.html) maillist + + • $ gpg --auto-key-locate dane --locate-keys pygost at cypherpunks dot ru + $ gpg --auto-key-locate wkd --locate-keys pygost at cypherpunks dot ru + + • -----BEGIN PGP PUBLIC KEY BLOCK----- + + mQENBFfXoPQBCACfxmT1M/oDKh+3DxiIHwA2YdyJ0joxe+QhT1cACApvD9GBOlbS + QqJU3kyO1+uOO5QzeTsSYdZbdcXF+Y7koEUsAVGY6aTKNKuuOrhVPTnhbG8Em++p + i6LPAvHs1/pD9xYWgSyGueu5OrcUu1bk7Ii16BePkGdoVqIo53OrteNH8fabJ5Ga + Rqvn2SxyTZ/HrgSfWqXOPmP62oiUKD6ztQPv1qP5GoSqPT3zXRF+c7yoJzAi09/D + trKpOH+eZqj/5M1v853i/TIQE975+AH9HNuIK3XYt67VQiDqU3CFeWC6wFUt/FOD + eAA9pKuJvY7eCyKVCOuNYJ5af1fGuxrEZPxJABEBAAG0J1B5R09TVCByZWxlYXNl + cyA8cHlnb3N0QGN5cGhlcnB1bmtzLnJ1PokBQAQTAQgAKgUCV9eg9AIbAwwLCgkN + CAwHCwMEAQIHFQoJCAsDAgUWAgEDAAIeAQIXgAAKCRDm/RJpzQwAnkiQB/wLD29x + 75urRIOCxLKrynERF2z/lxUv8aA6VB6Bp3/c08xbrtrNKpq970WvcxyNrsTFgcno + Sc2QBwGjSM4Oh5z1UxHt8wLvk+FTOYxlkUiOQv9uCwhU4ZtypV7Ps759dwneY2nS + Y0R5oGa3nFhi7JujBu7/9Xr2riBBczsGh3chFUe/WeQZxwfF4ZJFN/ykJpvlwkhe + txhAWSG2JTR9xDxbt6JBzdZ8hmS9YNZrzzyU3XUkdATi6zgkgv8BYPlc/QUCBVYp + xukpfqopwuT0QPKXZjPEBUNRAXGtPMo83OQyanMLm/BkSJXFBO2mVjaalEohc7Iq + jMcy/DjqMIpsOdVfiF4EEBEIAAYFAlfXoRkACgkQrhqBCeSYV+9zEgD/Weliq0bC + bQbT+AV0oPSsh4cl7/7yBWXuERUm0uIsDRsA/RSss+81tbyKTt8oObmDqi3gt8ka + 6j2AvJWj4I8J/fT9 + =pQ8y + -----END PGP PUBLIC KEY BLOCK----- + + You can obtain development source code with "git clone +git://git.cypherpunks.ru/pygost.git". diff --git a/xmlrpcserver/deps/pygost-5.12/MANIFEST.in b/xmlrpcserver/deps/pygost-5.12/MANIFEST.in new file mode 100644 index 0000000..f7ccb5c --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/MANIFEST.in @@ -0,0 +1,8 @@ +include AUTHORS +include COPYING +include FAQ +include INSTALL +include NEWS +include README +include THANKS +include VERSION diff --git a/xmlrpcserver/deps/pygost-5.12/NEWS b/xmlrpcserver/deps/pygost-5.12/NEWS new file mode 100644 index 0000000..840ca6d --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/NEWS @@ -0,0 +1,264 @@ +News +**** + +*5.11* + "gost34112012"’s "update()"/"digest()" methods are streaming now – + they do not store the whole data in memory. + +*5.10* + Added ISO 10126 "pygost.gost3413.(un)pad_iso10126" padding support. + +*5.9* + Fixed "wrap.wrap_cryptopro", that ignored Sbox for key + diversification. + +*5.8* + Added human-readable name of the curve in "GOST3410Curve.name". + +*5.7* + Fixed MGM ignoring of the set tag size. + +*5.6* + Fixed lint errors for previous release. + +*5.5* + More 34.10 curve parameters aliases: + id-tc26-gost-3410-2012-256-paramSetA -> id-tc26-gost-3410-12-256-paramSetA + id-tc26-gost-3410-2012-256-paramSetB -> id-tc26-gost-3410-12-256-paramSetB + id-tc26-gost-3410-2012-256-paramSetC -> id-tc26-gost-3410-12-256-paramSetC + id-tc26-gost-3410-2012-256-paramSetD -> id-tc26-gost-3410-12-256-paramSetD + id-tc26-gost-3410-2012-512-paramSetTest -> id-tc26-gost-3410-12-512-paramSetTest + id-tc26-gost-3410-2012-512-paramSetA -> id-tc26-gost-3410-12-512-paramSetA + id-tc26-gost-3410-2012-512-paramSetB -> id-tc26-gost-3410-12-512-paramSetB + id-tc26-gost-3410-2012-512-paramSetC -> id-tc26-gost-3410-12-512-paramSetC + +*5.4* + "gost3410.prv_marshal" helper can make private keys that are in + curve’s Q field, for better compatibility with some + implementations. + +*5.3* + • More than 4 times speed increase of "gost34112012". + • "asn1schemas/cert-selfsigned-example.py" optionally can issue + CA signed child certificate. + +*5.2* + • "GOST3410Curve" has ".contains(point)" method for checking if + point is on the curve. + • "gost3410_vko" functions check if remote peer’s public key is + on the curve. + • Small typing stubs fixes. + +*5.1* + Small typing stubs fixes. + +*5.0* + • Backward incompatible removing of misleading and excess "mode" + keyword argument from all "gost3410*" related functions. + Point/key sizes are determined by looking at curve’s + parameters size. + • "asn1schemas/cert-selfsigned-example.py" optionally can create + CA certificate. + +*4.9* + • *Fixed* nasty bug with Edwards curves using in 34.10-VKO + functions: curve’s cofactor has not been used + • CTR-ACPKM mode of operation + • OMAC-ACPKM-Master moder of operation + • KExp15/KImp15 key export/import functions + • KDF_GOSTR3411_2012_256, KDF_TREE_GOSTR3411_2012_256 + • KEG export key generation function + +*4.8* + MGM AEAD mode for 64 and 128 bit ciphers. + +*4.7* + Removed "gost28147.addmod" for simplicity. + +*4.6* + Fix invalid "gost28147.addmod"’s behaviour with much bigger values + than the modulo. + +*4.5* + Fixed digest endianness and more RFC4491bis conformance in + "asn1schemas/cert-selfsigned-example.py" certificate’s. + +*4.4* + • "id-tc26-gost-3410-2012-512-paramSetTest" curve + • Simple FAQ + • More test vectors for 34.10-2012 + • More X.509, PKCS #10 and corresponding ASN.1 helper structures + +*4.3* + Dummy release with fixed "pygost.__version__". + +*4.2* + • "pygost.gost3410.sign" accepts predefined random data used for + k/r generation + • More test vectors for 34.10-2012 + +*4.1* + • PEP-396 compatible module’s "__version__" + • Curve parameters aliases: + id-GostR3410-2001-CryptoPro-XchA-ParamSet -> id-GostR3410-2001-CryptoPro-A-ParamSet + id-GostR3410-2001-CryptoPro-XchB-ParamSet -> id-GostR3410-2001-CryptoPro-C-ParamSet + id-tc26-gost-3410-2012-256-paramSetB -> id-GostR3410-2001-CryptoPro-A-ParamSet + id-tc26-gost-3410-2012-256-paramSetC -> id-GostR3410-2001-CryptoPro-B-ParamSet + id-tc26-gost-3410-2012-256-paramSetD -> id-GostR3410-2001-CryptoPro-C-ParamSet + • Forbid any later GNU GPL version autousage (project’s licence + now is GNU GPLv3 only) + +*4.0* + • 34.10-2012 TC26 twisted Edwards curve related parameters + • Coordinates conversion from twisted Edwards to Weierstrass + form and vice versa + • More test vectors + • Backward incompatible Sbox and curves parameters renaming, to + comply with OIDs identifying them: + Gost2814789_TestParamSet -> id-Gost28147-89-TestParamSet + Gost28147_CryptoProParamSetA -> id-Gost28147-89-CryptoPro-A-ParamSet + Gost28147_CryptoProParamSetB -> id-Gost28147-89-CryptoPro-B-ParamSet + Gost28147_CryptoProParamSetC -> id-Gost28147-89-CryptoPro-C-ParamSet + Gost28147_CryptoProParamSetD -> id-Gost28147-89-CryptoPro-D-ParamSet + Gost28147_tc26_ParamZ -> id-tc26-gost-28147-param-Z + GostR3411_94_TestParamSet -> id-GostR3411-94-TestParamSet + GostR3411_94_CryptoProParamSet -> id-GostR3411-94-CryptoProParamSet + + GostR3410_2001_TestParamSet -> id-GostR3410-2001-TestParamSet + GostR3410_2001_CryptoPro_A_ParamSet -> id-GostR3410-2001-CryptoPro-A-ParamSet + GostR3410_2001_CryptoPro_B_ParamSet -> id-GostR3410-2001-CryptoPro-B-ParamSet + GostR3410_2001_CryptoPro_C_ParamSet -> id-GostR3410-2001-CryptoPro-C-ParamSet + GostR3410_2001_CryptoPro_XchA_ParamSet -> id-GostR3410-2001-CryptoPro-XchA-ParamSet + GostR3410_2001_CryptoPro_XchB_ParamSet -> id-GostR3410-2001-CryptoPro-XchB-ParamSet + GostR3410_2012_TC26_256_ParamSetA -> id-tc26-gost-3410-2012-256-paramSetA + GostR3410_2012_TC26_ParamSetA -> id-tc26-gost-3410-12-512-paramSetA + GostR3410_2012_TC26_ParamSetB -> id-tc26-gost-3410-12-512-paramSetB + GostR3410_2012_TC26_ParamSetC -> id-tc26-gost-3410-2012-512-paramSetC + • Backward incompatible "GOST3410Curve" initialization: all + parameters are passed not as big-endian encoded binaries, but + as integers + • Backward incompatible change: "gost3410.CURVE_PARAMS" is + disappeared. "gost3410.CURVES" dictionary holds already + initialized "GOST3410Curve". Just use + "CURVES["id-tc26-gost-3410-12-512-paramSetA"]" instead of + "GOST3410Curve(*CURVE_PARAMS["id-tc26-gost-3410-12-512-paramSetA"])" + +*3.15* + • Licence changed back to GNU GPLv3+. GNU LGPLv3+ licenced + versions are not available anymore + • More ASN.1-based test vectors (PyDERASN + (http://www.pyderasn.cypherpunks.ru/) dependency required) + +*3.14* + Add missing typing stubs related to previous release. + +*3.13* + • Ability to explicitly specify used 28147-89 Sbox in + "pygost.wrap.*" functions + • Ability to use key meshing in 28147-89 CBC mode + +*3.12* + • Added mode argument to "pygost.gost3410_vko.kek_34102012256", + because 256-bit private keys can be used with that algorithm + too. + • Fix incorrect degree sanitizing in + "pygost.gost3410.GOST3410Curve.exp" preventing using of + "UKM=1" in "pygost.gost3410_vko.kek_*" functions. + +*3.11* + Fixed PEP247 typing stub with invalid hexdigest method. + +*3.10* + Additional missing 34.11-* typing stubs. + +*3.9* + Add missing 34.11-2012 PBKDF2 typing stub. + +*3.8* + • 34.11-2012 based PBKDF2 function added + • 34.13-2015 does not require double blocksized IVs + +*3.7* + Fixed 34.13-2015 OFB bug with IVs longer than 2 blocks. + +*3.6* + Fixed source files installation during "setup.py install" + invocation. + +*3.5* + Dummy release: added long description in package metadata. + +*3.4* + • Small mypy stubs related fixes + • Licence changed from GNU GPLv3+ to GNU LGPLv3+ + +*3.3* + • "GOST3412Kuz" renamed to "GOST3412Kuznechik" + • "GOST3412Magma" implements GOST R 34.12-2015 Magma 64-bit + block cipher + +*3.2* + 34.13-2015 block cipher modes of operation implementations. + +*3.1* + Fixed mypy stubs related to PEP247-successors. + +*3.0* + • "gost3411_94" renamed to "gost341194" + • "gost3411_2012" renamed and split to "gost34112012256", + "gost34112012512" + • "GOST34112012" split to "GOST34112012256", "GOST34112012512" + • "gost3410.kek" moved to separate "gost3410_vko.kek_34102001" + • VKO GOST R 34.10-2012 appeared in "gost3410_vko", with test + vectors + • 34.11-94 digest is reversed, to be compatible with HMAC and + PBKDF2 test vectors describe in TC26 documents + • 34.11-94 PBKDF2 test vectors added + • "gost3410.prv_unmarshal", "gost3410.pub_marshal", + "gost3410.pub_unmarshal" helpers added, removing the need of + "x509" module at all + • "gost3410.verify" requires "(pubX, pubY)" tuple, instead of + two separate "pubX", "pubY" arguments + • 34.11-94 based PBKDF2 function added + +*2.4* + Fixed 34.13 mypy stub. + +*2.3* + Typo and pylint fixes. + +*2.2* + GOST R 34.13-2015 padding methods. + +*2.1* + Documentation and supplementary files refactoring. + +*2.0* + PEP-0247 compatible hashers and MAC. + +*1.0* + • Ability to specify curve in pygost.x509 module + • Ability to use 34.10-2012 in pygost.x509 functions + • Renamed classes and modules: + pygost.gost3410.SIZE_34100 -> pygost.gost3410.SIZE_3410_2001 + pygost.gost3410.SIZE_34112 -> pygost.gost3410.SIZE_3410_2012 + pygost.gost3411_12.GOST341112 -> pygost.gost3411_2012.GOST34112012 + +*0.16* + 34.10-2012 TC26 curve parameters. + +*0.15* + PEP-0484 static typing hints. + +*0.14* + 34.10-2012 workability fix. + +*0.13* + Python3 compatibility. + +*0.11* + GOST R 34.12-2015 Кузнечик (Kuznechik) implementation. + +*0.10* + CryptoPro and GOST key wrapping, CryptoPro key meshing. + diff --git a/xmlrpcserver/deps/pygost-5.12/PKG-INFO b/xmlrpcserver/deps/pygost-5.12/PKG-INFO new file mode 100644 index 0000000..d85054a --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/PKG-INFO @@ -0,0 +1,96 @@ +Metadata-Version: 2.1 +Name: pygost +Version: 5.12 +Summary: Pure Python GOST cryptographic functions library +Home-page: http://www.pygost.cypherpunks.ru/ +Author: Sergey Matveev +Author-email: stargrave@stargrave.org +License: GPLv3 +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) +Classifier: Natural Language :: English +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Security :: Cryptography +Classifier: Topic :: Software Development :: Libraries :: Python Modules +License-File: COPYING +License-File: AUTHORS + +Pure Python 2.7/3.x GOST cryptographic functions library. + +GOST is GOvernment STandard of Russian Federation (and Soviet Union). + +* GOST 28147-89 (RFC 5830) block cipher with ECB, CNT (CTR), CFB, MAC, + CBC (RFC 4357) modes of operation +* various 28147-89-related S-boxes included +* GOST R 34.11-94 hash function (RFC 5831) +* GOST R 34.11-94 based PBKDF2 function +* GOST R 34.11-2012 Стрибог (Streebog) hash function (RFC 6986) +* GOST R 34.11-2012 based PBKDF2 function (Р 50.1.111-2016) +* GOST R 34.10-2001 (RFC 5832) public key signature function +* GOST R 34.10-2012 (RFC 7091) public key signature function +* various 34.10 curve parameters included +* Coordinates conversion from twisted Edwards to Weierstrass form and + vice versa +* VKO GOST R 34.10-2001 key agreement function (RFC 4357) +* VKO GOST R 34.10-2012 key agreement function (RFC 7836) +* 28147-89 and CryptoPro key wrapping (RFC 4357) +* 28147-89 CryptoPro key meshing for CFB and CBC modes (RFC 4357) +* RFC 4491 (using GOST algorithms with X.509) compatibility helpers +* GOST R 34.12-2015 128-bit block cipher Кузнечик (Kuznechik) (RFC 7801) +* GOST R 34.12-2015 64-bit block cipher Магма (Magma) +* GOST R 34.13-2015 padding methods and block cipher modes of operation + (ECB, CTR, OFB, CBC, CFB, MAC), ISO 10126 padding +* MGM AEAD mode for 64 and 128 bit ciphers (RFC 9058) +* CTR-ACPKM, OMAC-ACPKM-Master modes of operation (Р 1323565.1.017-2018) +* KExp15/KImp15 key export/import functions (Р 1323565.1.017-2018) +* KDF_GOSTR3411_2012_256, KDF_TREE_GOSTR3411_2012_256 (Р 50.1.113-2016) +* KEG export key generation function (Р 1323565.1.020-2018) +* PEP247-compatible hash/MAC functions + +Known problems: low performance and non time-constant calculations. + +Example 34.10-2012 keypair generation, signing and verifying: + + >>> from pygost.gost3410 import CURVES + >>> curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + >>> from os import urandom + >>> prv_raw = urandom(64) + >>> from pygost.gost3410 import prv_unmarshal + >>> from pygost.gost3410 import prv_marshal + >>> prv = prv_unmarshal(prv_raw) + >>> prv_raw = prv_marshal(curve, prv) + >>> from pygost.gost3410 import public_key + >>> pub = public_key(curve, prv) + >>> from pygost.gost3410 import pub_marshal + >>> from pygost.utils import hexenc + >>> print "Public key is:", hexenc(pub_marshal(pub)) + >>> from pygost import gost34112012512 + >>> data_for_signing = b"some data" + >>> dgst = gost34112012512.new(data_for_signing).digest() + >>> from pygost.gost3410 import sign + >>> signature = sign(curve, prv, dgst) + >>> from pygost.gost3410 import verify + >>> verify(curve, pub, dgst, signature) + True + +Other examples can be found in docstrings and unittests. +Example self-signed X.509 certificate creation can be found in +pygost/asn1schemas/cert-selfsigned-example.py. + +PyGOST is free software: see the file COPYING for copying conditions. + +PyGOST'es home page is: http://www.pygost.cypherpunks.ru/ +You can read about GOST algorithms more: http://www.gost.cypherpunks.ru/ + +Please send questions, bug reports and patches to +http://lists.cypherpunks.ru/gost.html mailing list. +Announcements also go to this mailing list. + +Development Git source code repository currently is located here: +http://www.git.cypherpunks.ru/?p=pygost.git;a=summary + + diff --git a/xmlrpcserver/deps/pygost-5.12/README b/xmlrpcserver/deps/pygost-5.12/README new file mode 100644 index 0000000..2034715 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/README @@ -0,0 +1,73 @@ +Pure Python 2.7/3.x GOST cryptographic functions library. + +GOST is GOvernment STandard of Russian Federation (and Soviet Union). + +* GOST 28147-89 (RFC 5830) block cipher with ECB, CNT (CTR), CFB, MAC, + CBC (RFC 4357) modes of operation +* various 28147-89-related S-boxes included +* GOST R 34.11-94 hash function (RFC 5831) +* GOST R 34.11-94 based PBKDF2 function +* GOST R 34.11-2012 Стрибог (Streebog) hash function (RFC 6986) +* GOST R 34.11-2012 based PBKDF2 function (Р 50.1.111-2016) +* GOST R 34.10-2001 (RFC 5832) public key signature function +* GOST R 34.10-2012 (RFC 7091) public key signature function +* various 34.10 curve parameters included +* Coordinates conversion from twisted Edwards to Weierstrass form and + vice versa +* VKO GOST R 34.10-2001 key agreement function (RFC 4357) +* VKO GOST R 34.10-2012 key agreement function (RFC 7836) +* 28147-89 and CryptoPro key wrapping (RFC 4357) +* 28147-89 CryptoPro key meshing for CFB and CBC modes (RFC 4357) +* RFC 4491 (using GOST algorithms with X.509) compatibility helpers +* GOST R 34.12-2015 128-bit block cipher Кузнечик (Kuznechik) (RFC 7801) +* GOST R 34.12-2015 64-bit block cipher Магма (Magma) +* GOST R 34.13-2015 padding methods and block cipher modes of operation + (ECB, CTR, OFB, CBC, CFB, MAC), ISO 10126 padding +* MGM AEAD mode for 64 and 128 bit ciphers (RFC 9058) +* CTR-ACPKM, OMAC-ACPKM-Master modes of operation (Р 1323565.1.017-2018) +* KExp15/KImp15 key export/import functions (Р 1323565.1.017-2018) +* KDF_GOSTR3411_2012_256, KDF_TREE_GOSTR3411_2012_256 (Р 50.1.113-2016) +* KEG export key generation function (Р 1323565.1.020-2018) +* PEP247-compatible hash/MAC functions + +Known problems: low performance and non time-constant calculations. + +Example 34.10-2012 keypair generation, signing and verifying: + + >>> from pygost.gost3410 import CURVES + >>> curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + >>> from os import urandom + >>> prv_raw = urandom(64) + >>> from pygost.gost3410 import prv_unmarshal + >>> from pygost.gost3410 import prv_marshal + >>> prv = prv_unmarshal(prv_raw) + >>> prv_raw = prv_marshal(curve, prv) + >>> from pygost.gost3410 import public_key + >>> pub = public_key(curve, prv) + >>> from pygost.gost3410 import pub_marshal + >>> from pygost.utils import hexenc + >>> print "Public key is:", hexenc(pub_marshal(pub)) + >>> from pygost import gost34112012512 + >>> data_for_signing = b"some data" + >>> dgst = gost34112012512.new(data_for_signing).digest() + >>> from pygost.gost3410 import sign + >>> signature = sign(curve, prv, dgst) + >>> from pygost.gost3410 import verify + >>> verify(curve, pub, dgst, signature) + True + +Other examples can be found in docstrings and unittests. +Example self-signed X.509 certificate creation can be found in +pygost/asn1schemas/cert-selfsigned-example.py. + +PyGOST is free software: see the file COPYING for copying conditions. + +PyGOST'es home page is: http://www.pygost.cypherpunks.ru/ +You can read about GOST algorithms more: http://www.gost.cypherpunks.ru/ + +Please send questions, bug reports and patches to +http://lists.cypherpunks.ru/gost.html mailing list. +Announcements also go to this mailing list. + +Development Git source code repository currently is located here: +http://www.git.cypherpunks.ru/?p=pygost.git;a=summary diff --git a/xmlrpcserver/deps/pygost-5.12/THANKS b/xmlrpcserver/deps/pygost-5.12/THANKS new file mode 100644 index 0000000..cb2ec9d --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/THANKS @@ -0,0 +1,8 @@ +There are people deserving to be thanked for helping this project: + +* Dmitry Eremin-Solenikov for his + suggestions of TK26 standards usage as a base point for serialized + structures representation +* Alexander Lodin for finding bug in 34.13-2015 + OFB mode with IVs longer than 2 blocks +* Efimov Vasiliy for adding and testing of CBC-mode key meshing diff --git a/xmlrpcserver/deps/pygost-5.12/VERSION b/xmlrpcserver/deps/pygost-5.12/VERSION new file mode 100644 index 0000000..fa5f02c --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/VERSION @@ -0,0 +1 @@ +5.12 diff --git a/xmlrpcserver/deps/pygost-5.12/__init__.py b/xmlrpcserver/deps/pygost-5.12/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/__init__.py b/xmlrpcserver/deps/pygost-5.12/pygost/__init__.py new file mode 100644 index 0000000..c0695ad --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/__init__.py @@ -0,0 +1,6 @@ +"""Pure Python GOST cryptographic functions library. + +PyGOST is free software: see the file COPYING for copying conditions. +""" + +__version__ = "5.12" diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/__init__.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cert-dane-hash.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cert-dane-hash.py new file mode 100755 index 0000000..0292b9e --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cert-dane-hash.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +"""DANE's SPKI hash calculator +""" + +from base64 import standard_b64decode +from hashlib import sha256 +import sys + +from pygost.asn1schemas.x509 import Certificate + + +lines = sys.stdin.read().split("-----") +idx = lines.index("BEGIN CERTIFICATE") +if idx == -1: + raise ValueError("PEM has no CERTIFICATE") +cert_raw = standard_b64decode(lines[idx + 1]) +cert = Certificate().decod(cert_raw) +print(sha256(cert["tbsCertificate"]["subjectPublicKeyInfo"].encode()).hexdigest()) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cert-selfsigned-example.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cert-selfsigned-example.py new file mode 100755 index 0000000..bd562b1 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cert-selfsigned-example.py @@ -0,0 +1,348 @@ +#!/usr/bin/env python3 +"""Create example self-signed X.509 certificate +""" + +from argparse import ArgumentParser +from base64 import standard_b64decode +from base64 import standard_b64encode +from datetime import datetime +from datetime import timedelta +from os import urandom +from sys import exit as sys_exit +from sys import stdout +from textwrap import fill + +from pyderasn import Any +from pyderasn import BitString +from pyderasn import Boolean +from pyderasn import IA5String +from pyderasn import Integer +from pyderasn import OctetString +from pyderasn import PrintableString +from pyderasn import UTCTime + +from pygost.asn1schemas.oids import id_at_commonName +from pygost.asn1schemas.oids import id_at_countryName +from pygost.asn1schemas.oids import id_ce_authorityKeyIdentifier +from pygost.asn1schemas.oids import id_ce_basicConstraints +from pygost.asn1schemas.oids import id_ce_keyUsage +from pygost.asn1schemas.oids import id_ce_subjectAltName +from pygost.asn1schemas.oids import id_ce_subjectKeyIdentifier +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256 +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetA +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetB +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetC +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetD +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512 +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetA +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetB +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetC +from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_256 +from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_512 +from pygost.asn1schemas.prvkey import PrivateKey +from pygost.asn1schemas.prvkey import PrivateKeyAlgorithmIdentifier +from pygost.asn1schemas.prvkey import PrivateKeyInfo +from pygost.asn1schemas.x509 import AlgorithmIdentifier +from pygost.asn1schemas.x509 import AttributeType +from pygost.asn1schemas.x509 import AttributeTypeAndValue +from pygost.asn1schemas.x509 import AttributeValue +from pygost.asn1schemas.x509 import AuthorityKeyIdentifier +from pygost.asn1schemas.x509 import BasicConstraints +from pygost.asn1schemas.x509 import Certificate +from pygost.asn1schemas.x509 import CertificateSerialNumber +from pygost.asn1schemas.x509 import Extension +from pygost.asn1schemas.x509 import Extensions +from pygost.asn1schemas.x509 import GeneralName +from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters +from pygost.asn1schemas.x509 import KeyIdentifier +from pygost.asn1schemas.x509 import KeyUsage +from pygost.asn1schemas.x509 import Name +from pygost.asn1schemas.x509 import RDNSequence +from pygost.asn1schemas.x509 import RelativeDistinguishedName +from pygost.asn1schemas.x509 import SubjectAltName +from pygost.asn1schemas.x509 import SubjectKeyIdentifier +from pygost.asn1schemas.x509 import SubjectPublicKeyInfo +from pygost.asn1schemas.x509 import TBSCertificate +from pygost.asn1schemas.x509 import Time +from pygost.asn1schemas.x509 import Validity +from pygost.asn1schemas.x509 import Version +from pygost.gost3410 import CURVES +from pygost.gost3410 import prv_unmarshal +from pygost.gost3410 import pub_marshal +from pygost.gost3410 import public_key +from pygost.gost3410 import sign +from pygost.gost34112012256 import GOST34112012256 +from pygost.gost34112012512 import GOST34112012512 +from pygost.utils import bytes2long + +parser = ArgumentParser(description="Self-signed X.509 certificate creator") +parser.add_argument( + "--ca", + action="store_true", + help="Enable BasicConstraints.cA", +) +parser.add_argument( + "--cn", + required=True, + help="Subject's CommonName", +) +parser.add_argument( + "--country", + help="Subject's Country", +) +parser.add_argument( + "--serial", + help="Serial number", +) +parser.add_argument( + "--ai", + required=True, + help="Signing algorithm: {256[ABCD],512[ABC]}", +) +parser.add_argument( + "--issue-with", + help="Path to PEM with CA to issue the child", +) +parser.add_argument( + "--reuse-key", + help="Path to PEM with the key to reuse", +) +parser.add_argument( + "--out-key", + help="Path to PEM with the resulting key", +) +parser.add_argument( + "--only-key", + action="store_true", + help="Only generate the key", +) +parser.add_argument( + "--out-cert", + help="Path to PEM with the resulting certificate", +) +args = parser.parse_args() +AIs = { + "256A": { + "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetA, + "key_algorithm": id_tc26_gost3410_2012_256, + "prv_len": 32, + "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetA"], + "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256, + "hasher": GOST34112012256, + }, + "256B": { + "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetB, + "key_algorithm": id_tc26_gost3410_2012_256, + "prv_len": 32, + "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetB"], + "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256, + "hasher": GOST34112012256, + }, + "256C": { + "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetC, + "key_algorithm": id_tc26_gost3410_2012_256, + "prv_len": 32, + "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetC"], + "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256, + "hasher": GOST34112012256, + }, + "256D": { + "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetD, + "key_algorithm": id_tc26_gost3410_2012_256, + "prv_len": 32, + "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetD"], + "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256, + "hasher": GOST34112012256, + }, + "512A": { + "publicKeyParamSet": id_tc26_gost3410_2012_512_paramSetA, + "key_algorithm": id_tc26_gost3410_2012_512, + "prv_len": 64, + "curve": CURVES["id-tc26-gost-3410-12-512-paramSetA"], + "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_512, + "hasher": GOST34112012512, + }, + "512B": { + "publicKeyParamSet": id_tc26_gost3410_2012_512_paramSetB, + "key_algorithm": id_tc26_gost3410_2012_512, + "prv_len": 64, + "curve": CURVES["id-tc26-gost-3410-12-512-paramSetB"], + "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_512, + "hasher": GOST34112012512, + }, + "512C": { + "publicKeyParamSet": id_tc26_gost3410_2012_512_paramSetC, + "key_algorithm": id_tc26_gost3410_2012_512, + "prv_len": 64, + "curve": CURVES["id-tc26-gost-3410-2012-512-paramSetC"], + "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_512, + "hasher": GOST34112012512, + }, +} +ai = AIs[args.ai] + +ca_prv = None +ca_cert = None +ca_subj = None +ca_ai = None +if args.issue_with is not None: + with open(args.issue_with, "rb") as fd: + lines = fd.read().decode("ascii").split("-----") + idx = lines.index("BEGIN PRIVATE KEY") + if idx == -1: + raise ValueError("PEM has no PRIVATE KEY") + prv_raw = standard_b64decode(lines[idx + 1]) + idx = lines.index("BEGIN CERTIFICATE") + if idx == -1: + raise ValueError("PEM has no CERTIFICATE") + cert_raw = standard_b64decode(lines[idx + 1]) + pki = PrivateKeyInfo().decod(prv_raw) + ca_prv = prv_unmarshal(bytes(OctetString().decod(bytes(pki["privateKey"])))) + ca_cert = Certificate().decod(cert_raw) + tbs = ca_cert["tbsCertificate"] + ca_subj = tbs["subject"] + curve_oid = GostR34102012PublicKeyParameters().decod(bytes( + tbs["subjectPublicKeyInfo"]["algorithm"]["parameters"] + ))["publicKeyParamSet"] + ca_ai = next(iter([ + params for params in AIs.values() + if params["publicKeyParamSet"] == curve_oid + ])) + +key_params = GostR34102012PublicKeyParameters(( + ("publicKeyParamSet", ai["publicKeyParamSet"]), +)) + + +def pem(obj): + return fill(standard_b64encode(obj.encode()).decode("ascii"), 64) + + +if args.reuse_key is not None: + with open(args.reuse_key, "rb") as fd: + lines = fd.read().decode("ascii").split("-----") + idx = lines.index("BEGIN PRIVATE KEY") + if idx == -1: + raise ValueError("PEM has no PRIVATE KEY") + prv_raw = standard_b64decode(lines[idx + 1]) + pki = PrivateKeyInfo().decod(prv_raw) + prv = prv_unmarshal(bytes(OctetString().decod(bytes(pki["privateKey"])))) +else: + prv_raw = urandom(ai["prv_len"]) + out = stdout if args.out_key is None else open(args.out_key, "w") + print("-----BEGIN PRIVATE KEY-----", file=out) + print(pem(PrivateKeyInfo(( + ("version", Integer(0)), + ("privateKeyAlgorithm", PrivateKeyAlgorithmIdentifier(( + ("algorithm", ai["key_algorithm"]), + ("parameters", Any(key_params)), + ))), + ("privateKey", PrivateKey(OctetString(prv_raw).encode())), + ))), file=out) + print("-----END PRIVATE KEY-----", file=out) + if args.only_key: + sys_exit() + prv = prv_unmarshal(prv_raw) + +curve = ai["curve"] +pub_raw = pub_marshal(public_key(curve, prv)) +rdn = [RelativeDistinguishedName(( + AttributeTypeAndValue(( + ("type", AttributeType(id_at_commonName)), + ("value", AttributeValue(PrintableString(args.cn))), + )), +))] +if args.country: + rdn.append(RelativeDistinguishedName(( + AttributeTypeAndValue(( + ("type", AttributeType(id_at_countryName)), + ("value", AttributeValue(PrintableString(args.country))), + )), + ))) +subj = Name(("rdnSequence", RDNSequence(rdn))) +not_before = datetime.utcnow() +not_after = not_before + timedelta(days=365 * (10 if args.ca else 1)) +ai_sign = AlgorithmIdentifier(( + ("algorithm", (ai if ca_ai is None else ca_ai)["sign_algorithm"]), +)) +exts = [ + Extension(( + ("extnID", id_ce_subjectKeyIdentifier), + ("extnValue", OctetString( + SubjectKeyIdentifier(GOST34112012256(pub_raw).digest()[:20]).encode() + )), + )), + Extension(( + ("extnID", id_ce_keyUsage), + ("critical", Boolean(True)), + ("extnValue", OctetString(KeyUsage( + ("keyCertSign" if args.ca else "digitalSignature",), + ).encode())), + )), +] +if args.ca: + exts.append(Extension(( + ("extnID", id_ce_basicConstraints), + ("critical", Boolean(True)), + ("extnValue", OctetString(BasicConstraints(( + ("cA", Boolean(True)), + )).encode())), + ))) +else: + exts.append(Extension(( + ("extnID", id_ce_subjectAltName), + ("extnValue", OctetString( + SubjectAltName(( + GeneralName(("dNSName", IA5String(args.cn))), + )).encode() + )), + ))) +if ca_ai is not None: + caKeyId = [ + bytes(SubjectKeyIdentifier().decod(bytes(ext["extnValue"]))) + for ext in ca_cert["tbsCertificate"]["extensions"] + if ext["extnID"] == id_ce_subjectKeyIdentifier + ][0] + exts.append(Extension(( + ("extnID", id_ce_authorityKeyIdentifier), + ("extnValue", OctetString(AuthorityKeyIdentifier(( + ("keyIdentifier", KeyIdentifier(caKeyId)), + )).encode())), + ))) + +serial = ( + bytes2long(GOST34112012256(urandom(16)).digest()[:20]) + if args.serial is None else int(args.serial) +) +tbs = TBSCertificate(( + ("version", Version("v3")), + ("serialNumber", CertificateSerialNumber(serial)), + ("signature", ai_sign), + ("issuer", subj if ca_ai is None else ca_subj), + ("validity", Validity(( + ("notBefore", Time(("utcTime", UTCTime(not_before)))), + ("notAfter", Time(("utcTime", UTCTime(not_after)))), + ))), + ("subject", subj), + ("subjectPublicKeyInfo", SubjectPublicKeyInfo(( + ("algorithm", AlgorithmIdentifier(( + ("algorithm", ai["key_algorithm"]), + ("parameters", Any(key_params)), + ))), + ("subjectPublicKey", BitString(OctetString(pub_raw).encode())), + ))), + ("extensions", Extensions(exts)), +)) +cert = Certificate(( + ("tbsCertificate", tbs), + ("signatureAlgorithm", ai_sign), + ("signatureValue", BitString( + sign(curve, prv, ai["hasher"](tbs.encode()).digest()[::-1]) + if ca_ai is None else + sign(ca_ai["curve"], ca_prv, ca_ai["hasher"](tbs.encode()).digest()[::-1]) + )), +)) +out = stdout if args.out_cert is None else open(args.out_cert, "w") +print("-----BEGIN CERTIFICATE-----", file=out) +print(pem(cert), file=out) +print("-----END CERTIFICATE-----", file=out) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cms.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cms.py new file mode 100644 index 0000000..8028d2b --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/cms.py @@ -0,0 +1,431 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""CMS related structures (**NOT COMPLETE**) +""" + +from pyderasn import Any +from pyderasn import BitString +from pyderasn import Choice +from pyderasn import Integer +from pyderasn import ObjectIdentifier +from pyderasn import OctetString +from pyderasn import Sequence +from pyderasn import SequenceOf +from pyderasn import SetOf +from pyderasn import tag_ctxc +from pyderasn import tag_ctxp + +from pygost.asn1schemas.oids import id_cms_mac_attr +from pygost.asn1schemas.oids import id_contentType +from pygost.asn1schemas.oids import id_digestedData +from pygost.asn1schemas.oids import id_encryptedData +from pygost.asn1schemas.oids import id_envelopedData +from pygost.asn1schemas.oids import id_Gost28147_89 +from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm +from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm_omac +from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_wrap_kexp15 +from pygost.asn1schemas.oids import id_gostr3412_2015_magma_ctracpkm +from pygost.asn1schemas.oids import id_gostr3412_2015_magma_ctracpkm_omac +from pygost.asn1schemas.oids import id_gostr3412_2015_magma_wrap_kexp15 +from pygost.asn1schemas.oids import id_messageDigest +from pygost.asn1schemas.oids import id_signedData +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256 +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512 +from pygost.asn1schemas.x509 import AlgorithmIdentifier +from pygost.asn1schemas.x509 import Certificate +from pygost.asn1schemas.x509 import CertificateSerialNumber +from pygost.asn1schemas.x509 import Name +from pygost.asn1schemas.x509 import SubjectPublicKeyInfo + + +class CMSVersion(Integer): + pass + + +class ContentType(ObjectIdentifier): + pass + + +class IssuerAndSerialNumber(Sequence): + schema = ( + ("issuer", Name()), + ("serialNumber", CertificateSerialNumber()), + ) + + +class KeyIdentifier(OctetString): + pass + + +class SubjectKeyIdentifier(KeyIdentifier): + pass + + +class RecipientIdentifier(Choice): + schema = ( + ("issuerAndSerialNumber", IssuerAndSerialNumber()), + ("subjectKeyIdentifier", SubjectKeyIdentifier(impl=tag_ctxp(0))), + ) + + +class Gost2814789Key(OctetString): + bounds = (32, 32) + + +class Gost2814789MAC(OctetString): + bounds = (4, 4) + + +class Gost2814789EncryptedKey(Sequence): + schema = ( + ("encryptedKey", Gost2814789Key()), + ("maskKey", Gost2814789Key(impl=tag_ctxp(0), optional=True)), + ("macKey", Gost2814789MAC()), + ) + + +class GostR34102001TransportParameters(Sequence): + schema = ( + ("encryptionParamSet", ObjectIdentifier()), + ("ephemeralPublicKey", SubjectPublicKeyInfo( + impl=tag_ctxc(0), + optional=True, + )), + ("ukm", OctetString()), + ) + + +class GostR3410KeyTransport(Sequence): + schema = ( + ("sessionEncryptedKey", Gost2814789EncryptedKey()), + ("transportParameters", GostR34102001TransportParameters( + impl=tag_ctxc(0), + optional=True, + )), + ) + + +class GostR3410KeyTransport2019(Sequence): + schema = ( + ("encryptedKey", OctetString()), + ("ephemeralPublicKey", SubjectPublicKeyInfo()), + ("ukm", OctetString()), + ) + + +class GostR341012KEGParameters(Sequence): + schema = ( + ("algorithm", ObjectIdentifier()), + ) + + +class KeyEncryptionAlgorithmIdentifier(AlgorithmIdentifier): + schema = ( + ("algorithm", ObjectIdentifier(defines=( + (("parameters",), { + id_gostr3412_2015_magma_wrap_kexp15: GostR341012KEGParameters(), + id_gostr3412_2015_kuznyechik_wrap_kexp15: GostR341012KEGParameters(), + }), + (("..", "encryptedKey"), { + id_tc26_gost3410_2012_256: GostR3410KeyTransport(), + id_tc26_gost3410_2012_512: GostR3410KeyTransport(), + id_gostr3412_2015_magma_wrap_kexp15: GostR3410KeyTransport2019(), + id_gostr3412_2015_kuznyechik_wrap_kexp15: GostR3410KeyTransport2019(), + }), + (("..", "recipientEncryptedKeys", any, "encryptedKey"), { + id_tc26_gost3410_2012_256: Gost2814789EncryptedKey(), + id_tc26_gost3410_2012_512: Gost2814789EncryptedKey(), + }), + ))), + ("parameters", Any(optional=True)), + ) + + +class EncryptedKey(OctetString): + pass + + +class KeyTransRecipientInfo(Sequence): + schema = ( + ("version", CMSVersion()), + ("rid", RecipientIdentifier()), + ("keyEncryptionAlgorithm", KeyEncryptionAlgorithmIdentifier()), + ("encryptedKey", EncryptedKey()), + ) + + +class OriginatorPublicKey(Sequence): + schema = ( + ("algorithm", AlgorithmIdentifier()), + ("publicKey", BitString()), + ) + + +class OriginatorIdentifierOrKey(Choice): + schema = ( + ("issuerAndSerialNumber", IssuerAndSerialNumber()), + ("subjectKeyIdentifier", SubjectKeyIdentifier(impl=tag_ctxp(0))), + ("originatorKey", OriginatorPublicKey(impl=tag_ctxc(1))), + ) + + +class UserKeyingMaterial(OctetString): + pass + + +class KeyAgreeRecipientIdentifier(Choice): + schema = ( + ("issuerAndSerialNumber", IssuerAndSerialNumber()), + # ("rKeyId", RecipientKeyIdentifier(impl=tag_ctxc(0))), + ) + + +class RecipientEncryptedKey(Sequence): + schema = ( + ("rid", KeyAgreeRecipientIdentifier()), + ("encryptedKey", EncryptedKey()), + ) + + +class RecipientEncryptedKeys(SequenceOf): + schema = RecipientEncryptedKey() + + +class KeyAgreeRecipientInfo(Sequence): + schema = ( + ("version", CMSVersion(3)), + ("originator", OriginatorIdentifierOrKey(expl=tag_ctxc(0))), + ("ukm", UserKeyingMaterial(expl=tag_ctxc(1), optional=True)), + ("keyEncryptionAlgorithm", KeyEncryptionAlgorithmIdentifier()), + ("recipientEncryptedKeys", RecipientEncryptedKeys()), + ) + + +class RecipientInfo(Choice): + schema = ( + ("ktri", KeyTransRecipientInfo()), + ("kari", KeyAgreeRecipientInfo(impl=tag_ctxc(1))), + # ("kekri", KEKRecipientInfo(impl=tag_ctxc(2))), + # ("pwri", PasswordRecipientInfo(impl=tag_ctxc(3))), + # ("ori", OtherRecipientInfo(impl=tag_ctxc(4))), + ) + + +class RecipientInfos(SetOf): + schema = RecipientInfo() + bounds = (1, float("+inf")) + + +class Gost2814789IV(OctetString): + bounds = (8, 8) + + +class Gost2814789Parameters(Sequence): + schema = ( + ("iv", Gost2814789IV()), + ("encryptionParamSet", ObjectIdentifier()), + ) + + +class Gost341215EncryptionParameters(Sequence): + schema = ( + ("ukm", OctetString()), + ) + + +class ContentEncryptionAlgorithmIdentifier(AlgorithmIdentifier): + schema = ( + ("algorithm", ObjectIdentifier(defines=( + (("parameters",), { + id_Gost28147_89: Gost2814789Parameters(), + id_gostr3412_2015_magma_ctracpkm: Gost341215EncryptionParameters(), + id_gostr3412_2015_kuznyechik_ctracpkm: Gost341215EncryptionParameters(), + id_gostr3412_2015_magma_ctracpkm_omac: Gost341215EncryptionParameters(), + id_gostr3412_2015_kuznyechik_ctracpkm_omac: Gost341215EncryptionParameters(), + }), + ))), + ("parameters", Any(optional=True)), + ) + + +class EncryptedContent(OctetString): + pass + + +class EncryptedContentInfo(Sequence): + schema = ( + ("contentType", ContentType()), + ("contentEncryptionAlgorithm", ContentEncryptionAlgorithmIdentifier()), + ("encryptedContent", EncryptedContent(impl=tag_ctxp(0), optional=True)), + ) + + +class Digest(OctetString): + pass + + +class AttributeValue(Any): + pass + + +class AttributeValues(SetOf): + schema = AttributeValue() + + +class EncryptedMac(OctetString): + pass + + +class Attribute(Sequence): + schema = ( + ("attrType", ObjectIdentifier(defines=( + (("attrValues",), { + id_contentType: ObjectIdentifier(), + id_messageDigest: Digest(), + id_cms_mac_attr: EncryptedMac(), + },), + ))), + ("attrValues", AttributeValues()), + ) + + +class UnprotectedAttributes(SetOf): + schema = Attribute() + bounds = (1, float("+inf")) + + +class CertificateChoices(Choice): + schema = ( + ("certificate", Certificate()), + # ("extendedCertificate", OctetString(impl=tag_ctxp(0))), + # ("v1AttrCert", AttributeCertificateV1(impl=tag_ctxc(1))), # V1 is osbolete + # ("v2AttrCert", AttributeCertificateV2(impl=tag_ctxc(2))), + # ("other", OtherCertificateFormat(impl=tag_ctxc(3))), + ) + + +class CertificateSet(SetOf): + schema = CertificateChoices() + + +class OriginatorInfo(Sequence): + schema = ( + ("certs", CertificateSet(impl=tag_ctxc(0), optional=True)), + # ("crls", RevocationInfoChoices(impl=tag_ctxc(1), optional=True)), + ) + + +class EnvelopedData(Sequence): + schema = ( + ("version", CMSVersion()), + ("originatorInfo", OriginatorInfo(impl=tag_ctxc(0), optional=True)), + ("recipientInfos", RecipientInfos()), + ("encryptedContentInfo", EncryptedContentInfo()), + ("unprotectedAttrs", UnprotectedAttributes(impl=tag_ctxc(1), optional=True)), + ) + + +class EncapsulatedContentInfo(Sequence): + schema = ( + ("eContentType", ContentType()), + ("eContent", OctetString(expl=tag_ctxc(0), optional=True)), + ) + + +class SignerIdentifier(Choice): + schema = ( + ("issuerAndSerialNumber", IssuerAndSerialNumber()), + ("subjectKeyIdentifier", SubjectKeyIdentifier(impl=tag_ctxp(0))), + ) + + +class DigestAlgorithmIdentifiers(SetOf): + schema = AlgorithmIdentifier() + + +class DigestAlgorithmIdentifier(AlgorithmIdentifier): + pass + + +class SignatureAlgorithmIdentifier(AlgorithmIdentifier): + pass + + +class SignatureValue(OctetString): + pass + + +class SignedAttributes(SetOf): + schema = Attribute() + bounds = (1, float("+inf")) + + +class SignerInfo(Sequence): + schema = ( + ("version", CMSVersion()), + ("sid", SignerIdentifier()), + ("digestAlgorithm", DigestAlgorithmIdentifier()), + ("signedAttrs", SignedAttributes(impl=tag_ctxc(0), optional=True)), + ("signatureAlgorithm", SignatureAlgorithmIdentifier()), + ("signature", SignatureValue()), + # ("unsignedAttrs", UnsignedAttributes(impl=tag_ctxc(1), optional=True)), + ) + + +class SignerInfos(SetOf): + schema = SignerInfo() + + +class SignedData(Sequence): + schema = ( + ("version", CMSVersion()), + ("digestAlgorithms", DigestAlgorithmIdentifiers()), + ("encapContentInfo", EncapsulatedContentInfo()), + ("certificates", CertificateSet(impl=tag_ctxc(0), optional=True)), + # ("crls", RevocationInfoChoices(impl=tag_ctxc(1), optional=True)), + ("signerInfos", SignerInfos()), + ) + + +class DigestedData(Sequence): + schema = ( + ("version", CMSVersion()), + ("digestAlgorithm", DigestAlgorithmIdentifier()), + ("encapContentInfo", EncapsulatedContentInfo()), + ("digest", Digest()), + ) + + +class EncryptedData(Sequence): + schema = ( + ("version", CMSVersion()), + ("encryptedContentInfo", EncryptedContentInfo()), + ("unprotectedAttrs", UnprotectedAttributes(impl=tag_ctxc(1), optional=True)), + ) + + +class ContentInfo(Sequence): + schema = ( + ("contentType", ContentType(defines=( + (("content",), { + id_digestedData: DigestedData(), + id_encryptedData: EncryptedData(), + id_envelopedData: EnvelopedData(), + id_signedData: SignedData(), + }), + ))), + ("content", Any(expl=tag_ctxc(0))), + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/oids.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/oids.py new file mode 100644 index 0000000..4638900 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/oids.py @@ -0,0 +1,60 @@ +from pyderasn import ObjectIdentifier + + +id_at_commonName = ObjectIdentifier("2.5.4.3") +id_at_countryName = ObjectIdentifier("2.5.4.6") +id_at_localityName = ObjectIdentifier("2.5.4.7") +id_at_stateOrProvinceName = ObjectIdentifier("2.5.4.8") +id_at_organizationName = ObjectIdentifier("2.5.4.10") + +id_pkcs7 = ObjectIdentifier("1.2.840.113549.1.7") +id_data = id_pkcs7 + (1,) +id_signedData = id_pkcs7 + (2,) +id_envelopedData = id_pkcs7 + (3,) +id_digestedData = id_pkcs7 + (5,) +id_encryptedData = id_pkcs7 + (6,) + +id_pkcs9 = ObjectIdentifier("1.2.840.113549.1.9") +id_contentType = id_pkcs9 + (3,) +id_messageDigest = id_pkcs9 + (4,) +id_pkcs9_certTypes_x509Certificate = ObjectIdentifier("1.2.840.113549.1.9.22.1") +id_pkcs12_bagtypes_keyBag = ObjectIdentifier("1.2.840.113549.1.12.10.1.1") +id_pkcs12_bagtypes_pkcs8ShroudedKeyBag = ObjectIdentifier("1.2.840.113549.1.12.10.1.2") +id_pkcs12_bagtypes_certBag = ObjectIdentifier("1.2.840.113549.1.12.10.1.3") + +id_Gost28147_89 = ObjectIdentifier("1.2.643.2.2.21") +id_GostR3410_2001_TestParamSet = ObjectIdentifier("1.2.643.2.2.35.0") +id_cms_mac_attr = ObjectIdentifier("1.2.643.7.1.0.6.1.1") +id_tc26_gost3410_2012_256 = ObjectIdentifier("1.2.643.7.1.1.1.1") +id_tc26_gost3410_2012_512 = ObjectIdentifier("1.2.643.7.1.1.1.2") +id_tc26_gost3411_2012_256 = ObjectIdentifier("1.2.643.7.1.1.2.2") +id_tc26_gost3411_2012_512 = ObjectIdentifier("1.2.643.7.1.1.2.3") +id_tc26_signwithdigest_gost3410_2012_256 = ObjectIdentifier("1.2.643.7.1.1.3.2") +id_tc26_signwithdigest_gost3410_2012_512 = ObjectIdentifier("1.2.643.7.1.1.3.3") +id_gostr3412_2015_magma_ctracpkm = ObjectIdentifier("1.2.643.7.1.1.5.1.1") +id_gostr3412_2015_magma_ctracpkm_omac = ObjectIdentifier("1.2.643.7.1.1.5.1.2") +id_gostr3412_2015_kuznyechik_ctracpkm = ObjectIdentifier("1.2.643.7.1.1.5.2.1") +id_gostr3412_2015_kuznyechik_ctracpkm_omac = ObjectIdentifier("1.2.643.7.1.1.5.2.2") +id_tc26_agreement_gost3410_2012_256 = ObjectIdentifier("1.2.643.7.1.1.6.1") +id_tc26_agreement_gost3410_2012_512 = ObjectIdentifier("1.2.643.7.1.1.6.2") +id_gostr3412_2015_magma_wrap_kexp15 = ObjectIdentifier("1.2.643.7.1.1.7.1.1") +id_gostr3412_2015_kuznyechik_wrap_kexp15 = ObjectIdentifier("1.2.643.7.1.1.7.2.1") +id_tc26_gost3410_2012_256_paramSetA = ObjectIdentifier("1.2.643.7.1.2.1.1.1") +id_tc26_gost3410_2012_256_paramSetB = ObjectIdentifier("1.2.643.7.1.2.1.1.2") +id_tc26_gost3410_2012_256_paramSetC = ObjectIdentifier("1.2.643.7.1.2.1.1.3") +id_tc26_gost3410_2012_256_paramSetD = ObjectIdentifier("1.2.643.7.1.2.1.1.4") +id_tc26_gost3410_2012_512_paramSetTest = ObjectIdentifier("1.2.643.7.1.2.1.2.0") +id_tc26_gost3410_2012_512_paramSetA = ObjectIdentifier("1.2.643.7.1.2.1.2.1") +id_tc26_gost3410_2012_512_paramSetB = ObjectIdentifier("1.2.643.7.1.2.1.2.2") +id_tc26_gost3410_2012_512_paramSetC = ObjectIdentifier("1.2.643.7.1.2.1.2.3") +id_tc26_gost_28147_param_Z = ObjectIdentifier("1.2.643.7.1.2.5.1.1") + +id_pbes2 = ObjectIdentifier("1.2.840.113549.1.5.13") +id_pbkdf2 = ObjectIdentifier("1.2.840.113549.1.5.12") + +id_at_commonName = ObjectIdentifier("2.5.4.3") +id_ce_basicConstraints = ObjectIdentifier("2.5.29.19") +id_ce_subjectKeyIdentifier = ObjectIdentifier("2.5.29.14") +id_ce_keyUsage = ObjectIdentifier("2.5.29.15") +id_ce_subjectAltName = ObjectIdentifier("2.5.29.17") +id_ce_authorityKeyIdentifier = ObjectIdentifier("2.5.29.35") diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/pfx.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/pfx.py new file mode 100644 index 0000000..27a87d0 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/pfx.py @@ -0,0 +1,250 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""PKCS #12 related structures (**NOT COMPLETE**) +""" + +from pyderasn import Any +from pyderasn import Choice +from pyderasn import Integer +from pyderasn import ObjectIdentifier +from pyderasn import OctetString +from pyderasn import Sequence +from pyderasn import SequenceOf +from pyderasn import SetOf +from pyderasn import tag_ctxc +from pyderasn import tag_ctxp + +from pygost.asn1schemas.cms import CMSVersion +from pygost.asn1schemas.cms import ContentType +from pygost.asn1schemas.cms import Gost2814789Parameters +from pygost.asn1schemas.cms import Gost341215EncryptionParameters +from pygost.asn1schemas.oids import id_data +from pygost.asn1schemas.oids import id_encryptedData +from pygost.asn1schemas.oids import id_Gost28147_89 +from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm +from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm_omac +from pygost.asn1schemas.oids import id_gostr3412_2015_magma_ctracpkm +from pygost.asn1schemas.oids import id_gostr3412_2015_magma_ctracpkm_omac +from pygost.asn1schemas.oids import id_pbes2 +from pygost.asn1schemas.oids import id_pbkdf2 +from pygost.asn1schemas.oids import id_pkcs9_certTypes_x509Certificate +from pygost.asn1schemas.prvkey import PrivateKeyInfo +from pygost.asn1schemas.x509 import AlgorithmIdentifier +from pygost.asn1schemas.x509 import Certificate + + +class PBKDF2Salt(Choice): + schema = ( + ("specified", OctetString()), + # ("otherSource", PBKDF2SaltSources()), + ) + + +id_hmacWithSHA1 = ObjectIdentifier("1.2.840.113549.2.7") + + +class PBKDF2PRFs(AlgorithmIdentifier): + schema = ( + ("algorithm", ObjectIdentifier(default=id_hmacWithSHA1)), + ("parameters", Any(optional=True)), + ) + + +class IterationCount(Integer): + bounds = (1, float("+inf")) + + +class KeyLength(Integer): + bounds = (1, float("+inf")) + + +class PBKDF2Params(Sequence): + schema = ( + ("salt", PBKDF2Salt()), + ("iterationCount", IterationCount(optional=True)), + ("keyLength", KeyLength(optional=True)), + ("prf", PBKDF2PRFs()), + ) + + +class PBES2KDFs(AlgorithmIdentifier): + schema = ( + ("algorithm", ObjectIdentifier(defines=( + (("parameters",), {id_pbkdf2: PBKDF2Params()}), + ))), + ("parameters", Any(optional=True)), + ) + + +class PBES2Encs(AlgorithmIdentifier): + schema = ( + ("algorithm", ObjectIdentifier(defines=( + (("parameters",), { + id_Gost28147_89: Gost2814789Parameters(), + id_gostr3412_2015_magma_ctracpkm: Gost341215EncryptionParameters(), + id_gostr3412_2015_magma_ctracpkm_omac: Gost341215EncryptionParameters(), + id_gostr3412_2015_kuznyechik_ctracpkm: Gost341215EncryptionParameters(), + id_gostr3412_2015_kuznyechik_ctracpkm_omac: Gost341215EncryptionParameters(), + }), + ))), + ("parameters", Any(optional=True)), + ) + + +class PBES2Params(Sequence): + schema = ( + ("keyDerivationFunc", PBES2KDFs()), + ("encryptionScheme", PBES2Encs()), + ) + + +class EncryptionAlgorithmIdentifier(AlgorithmIdentifier): + schema = ( + ("algorithm", ObjectIdentifier(defines=( + (("parameters",), {id_pbes2: PBES2Params()}), + ))), + ("parameters", Any(optional=True)), + ) + + +class ContentEncryptionAlgorithmIdentifier(EncryptionAlgorithmIdentifier): + schema = ( + ("algorithm", ObjectIdentifier(defines=( + (("parameters",), {id_pbes2: PBES2Params()}), + ))), + ("parameters", Any(optional=True)), + ) + + +class EncryptedContent(OctetString): + pass + + +class EncryptedContentInfo(Sequence): + schema = ( + ("contentType", ContentType()), + ("contentEncryptionAlgorithm", ContentEncryptionAlgorithmIdentifier()), + ("encryptedContent", EncryptedContent(impl=tag_ctxp(0), optional=True)), + ) + + +class EncryptedData(Sequence): + schema = ( + ("version", CMSVersion()), + ("encryptedContentInfo", EncryptedContentInfo()), + # ("unprotectedAttrs", UnprotectedAttributes(impl=tag_ctxc(1), optional=True)), + ) + + +class PKCS12BagSet(Any): + pass + + +class AttrValue(SetOf): + schema = Any() + + +class PKCS12Attribute(Sequence): + schema = ( + ("attrId", ObjectIdentifier()), + ("attrValue", AttrValue()), + ) + + +class PKCS12Attributes(SetOf): + schema = PKCS12Attribute() + + +class SafeBag(Sequence): + schema = ( + ("bagId", ObjectIdentifier(defines=( + (("bagValue",), {id_encryptedData: EncryptedData()}), + ))), + ("bagValue", PKCS12BagSet(expl=tag_ctxc(0))), + ("bagAttributes", PKCS12Attributes(optional=True)), + ) + + +class SafeContents(SequenceOf): + schema = SafeBag() + + +OctetStringSafeContents = SafeContents(expl=OctetString.tag_default) + + +class AuthSafe(Sequence): + schema = ( + ("contentType", ContentType(defines=( + (("content",), {id_data: OctetStringSafeContents()}), + ))), + ("content", Any(expl=tag_ctxc(0))), + ) + + +class DigestInfo(Sequence): + schema = ( + ("digestAlgorithm", AlgorithmIdentifier()), + ("digest", OctetString()), + ) + + +class MacData(Sequence): + schema = ( + ("mac", DigestInfo()), + ("macSalt", OctetString()), + ("iterations", Integer(default=1)), + ) + + +class PFX(Sequence): + schema = ( + ("version", Integer(default=1)), + ("authSafe", AuthSafe()), + ("macData", MacData(optional=True)), + ) + + +class EncryptedPrivateKeyInfo(Sequence): + schema = ( + ("encryptionAlgorithm", EncryptionAlgorithmIdentifier()), + ("encryptedData", OctetString()), + ) + + +class PKCS8ShroudedKeyBag(EncryptedPrivateKeyInfo): + pass + + +OctetStringX509Certificate = Certificate(expl=OctetString.tag_default) + + +class CertTypes(Any): + pass + + +class CertBag(Sequence): + schema = ( + ("certId", ObjectIdentifier(defines=( + (("certValue",), { + id_pkcs9_certTypes_x509Certificate: OctetStringX509Certificate(), + }), + ))), + ("certValue", CertTypes(expl=tag_ctxc(0))), + ) + + +class KeyBag(PrivateKeyInfo): + pass diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/pkcs10.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/pkcs10.py new file mode 100644 index 0000000..dce45dd --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/pkcs10.py @@ -0,0 +1,49 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""PKCS #10 related structures (**NOT COMPLETE**) +""" + +from pyderasn import BitString +from pyderasn import Integer +from pyderasn import Sequence +from pyderasn import SetOf +from pyderasn import tag_ctxc + +from pygost.asn1schemas.cms import Attribute +from pygost.asn1schemas.x509 import AlgorithmIdentifier +from pygost.asn1schemas.x509 import Name +from pygost.asn1schemas.x509 import SubjectPublicKeyInfo + + +class Attributes(SetOf): + schema = Attribute() + + +class CertificationRequestInfo(Sequence): + schema = ( + ("version", Integer(0)), + ("subject", Name()), + ("subjectPKInfo", SubjectPublicKeyInfo()), + ("attributes", Attributes(impl=tag_ctxc(0))), + ) + + +class CertificationRequest(Sequence): + schema = ( + ("certificationRequestInfo", CertificationRequestInfo()), + ("signatureAlgorithm", AlgorithmIdentifier()), + ("signature", BitString()), + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/prvkey.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/prvkey.py new file mode 100644 index 0000000..7da2533 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/prvkey.py @@ -0,0 +1,100 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from pyderasn import Any +from pyderasn import BitString +from pyderasn import Choice +from pyderasn import Integer +from pyderasn import Null +from pyderasn import ObjectIdentifier +from pyderasn import OctetString +from pyderasn import Sequence +from pyderasn import SetOf +from pyderasn import tag_ctxc +from pyderasn import tag_ctxp + +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256 +from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512 +from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters + + +class ECParameters(Choice): + schema = ( + ("namedCurve", ObjectIdentifier()), + ("implicitCurve", Null()), + # ("specifiedCurve", SpecifiedECDomain()), + ) + + +ecPrivkeyVer1 = Integer(1) + + +class ECPrivateKey(Sequence): + schema = ( + ("version", Integer(ecPrivkeyVer1)), + ("privateKey", OctetString()), + ("parameters", ECParameters(expl=tag_ctxc(0), optional=True)), + ("publicKey", BitString(expl=tag_ctxc(1), optional=True)), + ) + + +class PrivateKeyAlgorithmIdentifier(Sequence): + schema = ( + ("algorithm", ObjectIdentifier(defines=( + (("parameters",), { + id_tc26_gost3410_2012_256: GostR34102012PublicKeyParameters(), + id_tc26_gost3410_2012_512: GostR34102012PublicKeyParameters(), + }), + ))), + ("parameters", Any(optional=True)), + ) + + +class PrivateKey(OctetString): + pass + + +class AttributeValue(Any): + pass + + +class AttributeValues(SetOf): + schema = AttributeValue() + + +class Attribute(Sequence): + schema = ( + ("attrType", ObjectIdentifier()), + ("attrValues", AttributeValues()), + ) + + +class Attributes(SetOf): + schema = Attribute() + + +class PublicKey(BitString): + pass + + +class PrivateKeyInfo(Sequence): + schema = ( + ("version", Integer(0)), + ("privateKeyAlgorithm", PrivateKeyAlgorithmIdentifier()), + ("privateKey", PrivateKey()), + ("attributes", Attributes(impl=tag_ctxc(0), optional=True)), + ("publicKey", PublicKey(impl=tag_ctxp(1), optional=True)), + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/x509.py b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/x509.py new file mode 100644 index 0000000..86ad7da --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/asn1schemas/x509.py @@ -0,0 +1,262 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""":rfc:`5280` related structures (**NOT COMPLETE**) + +They are taken from `PyDERASN +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""GOST 28147-89 block cipher + +This is implementation of :rfc:`5830` ECB, CNT, CFB and :rfc:`4357` +CBC modes of operation. N1, N2, K names are taken according to +specification's terminology. CNT and CFB modes can work with arbitrary +data lengths. +""" + +from functools import partial + +from pygost.gost3413 import pad2 +from pygost.gost3413 import pad_size +from pygost.gost3413 import unpad2 +from pygost.utils import hexdec +from pygost.utils import strxor +from pygost.utils import xrange + + +KEYSIZE = 32 +BLOCKSIZE = 8 +C1 = 0x01010104 +C2 = 0x01010101 + +# Sequence of K_i S-box applying for encryption and decryption +SEQ_ENCRYPT = ( + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, + 7, 6, 5, 4, 3, 2, 1, 0, +) +SEQ_DECRYPT = ( + 0, 1, 2, 3, 4, 5, 6, 7, + 7, 6, 5, 4, 3, 2, 1, 0, + 7, 6, 5, 4, 3, 2, 1, 0, + 7, 6, 5, 4, 3, 2, 1, 0, +) + +# S-box parameters +DEFAULT_SBOX = "id-Gost28147-89-CryptoPro-A-ParamSet" +SBOXES = { + "id-Gost28147-89-TestParamSet": ( + (4, 2, 15, 5, 9, 1, 0, 8, 14, 3, 11, 12, 13, 7, 10, 6), + (12, 9, 15, 14, 8, 1, 3, 10, 2, 7, 4, 13, 6, 0, 11, 5), + (13, 8, 14, 12, 7, 3, 9, 10, 1, 5, 2, 4, 6, 15, 0, 11), + (14, 9, 11, 2, 5, 15, 7, 1, 0, 13, 12, 6, 10, 4, 3, 8), + (3, 14, 5, 9, 6, 8, 0, 13, 10, 11, 7, 12, 2, 1, 15, 4), + (8, 15, 6, 11, 1, 9, 12, 5, 13, 3, 7, 10, 0, 14, 2, 4), + (9, 11, 12, 0, 3, 6, 7, 5, 4, 8, 14, 15, 1, 10, 2, 13), + (12, 6, 5, 2, 11, 0, 9, 13, 3, 14, 7, 10, 15, 4, 1, 8), + ), + "id-Gost28147-89-CryptoPro-A-ParamSet": ( + (9, 6, 3, 2, 8, 11, 1, 7, 10, 4, 14, 15, 12, 0, 13, 5), + (3, 7, 14, 9, 8, 10, 15, 0, 5, 2, 6, 12, 11, 4, 13, 1), + (14, 4, 6, 2, 11, 3, 13, 8, 12, 15, 5, 10, 0, 7, 1, 9), + (14, 7, 10, 12, 13, 1, 3, 9, 0, 2, 11, 4, 15, 8, 5, 6), + (11, 5, 1, 9, 8, 13, 15, 0, 14, 4, 2, 3, 12, 7, 10, 6), + (3, 10, 13, 12, 1, 2, 0, 11, 7, 5, 9, 4, 8, 15, 14, 6), + (1, 13, 2, 9, 7, 10, 6, 0, 8, 12, 4, 5, 15, 3, 11, 14), + (11, 10, 15, 5, 0, 12, 14, 8, 6, 2, 3, 9, 1, 7, 13, 4), + ), + "id-Gost28147-89-CryptoPro-B-ParamSet": ( + (8, 4, 11, 1, 3, 5, 0, 9, 2, 14, 10, 12, 13, 6, 7, 15), + (0, 1, 2, 10, 4, 13, 5, 12, 9, 7, 3, 15, 11, 8, 6, 14), + (14, 12, 0, 10, 9, 2, 13, 11, 7, 5, 8, 15, 3, 6, 1, 4), + (7, 5, 0, 13, 11, 6, 1, 2, 3, 10, 12, 15, 4, 14, 9, 8), + (2, 7, 12, 15, 9, 5, 10, 11, 1, 4, 0, 13, 6, 8, 14, 3), + (8, 3, 2, 6, 4, 13, 14, 11, 12, 1, 7, 15, 10, 0, 9, 5), + (5, 2, 10, 11, 9, 1, 12, 3, 7, 4, 13, 0, 6, 15, 8, 14), + (0, 4, 11, 14, 8, 3, 7, 1, 10, 2, 9, 6, 15, 13, 5, 12), + ), + "id-Gost28147-89-CryptoPro-C-ParamSet": ( + (1, 11, 12, 2, 9, 13, 0, 15, 4, 5, 8, 14, 10, 7, 6, 3), + (0, 1, 7, 13, 11, 4, 5, 2, 8, 14, 15, 12, 9, 10, 6, 3), + (8, 2, 5, 0, 4, 9, 15, 10, 3, 7, 12, 13, 6, 14, 1, 11), + (3, 6, 0, 1, 5, 13, 10, 8, 11, 2, 9, 7, 14, 15, 12, 4), + (8, 13, 11, 0, 4, 5, 1, 2, 9, 3, 12, 14, 6, 15, 10, 7), + (12, 9, 11, 1, 8, 14, 2, 4, 7, 3, 6, 5, 10, 0, 15, 13), + (10, 9, 6, 8, 13, 14, 2, 0, 15, 3, 5, 11, 4, 1, 12, 7), + (7, 4, 0, 5, 10, 2, 15, 14, 12, 6, 1, 11, 13, 9, 3, 8), + ), + "id-Gost28147-89-CryptoPro-D-ParamSet": ( + (15, 12, 2, 10, 6, 4, 5, 0, 7, 9, 14, 13, 1, 11, 8, 3), + (11, 6, 3, 4, 12, 15, 14, 2, 7, 13, 8, 0, 5, 10, 9, 1), + (1, 12, 11, 0, 15, 14, 6, 5, 10, 13, 4, 8, 9, 3, 7, 2), + (1, 5, 14, 12, 10, 7, 0, 13, 6, 2, 11, 4, 9, 3, 15, 8), + (0, 12, 8, 9, 13, 2, 10, 11, 7, 3, 6, 5, 4, 14, 15, 1), + (8, 0, 15, 3, 2, 5, 14, 11, 1, 10, 4, 7, 12, 9, 13, 6), + (3, 0, 6, 15, 1, 14, 9, 2, 13, 8, 12, 4, 11, 10, 5, 7), + (1, 10, 6, 8, 15, 11, 0, 4, 12, 3, 5, 9, 7, 13, 2, 14), + ), + "id-tc26-gost-28147-param-Z": ( + (12, 4, 6, 2, 10, 5, 11, 9, 14, 8, 13, 7, 0, 3, 15, 1), + (6, 8, 2, 3, 9, 10, 5, 12, 1, 14, 4, 7, 11, 13, 0, 15), + (11, 3, 5, 8, 2, 15, 10, 13, 14, 1, 7, 4, 12, 9, 6, 0), + (12, 8, 2, 1, 13, 4, 15, 6, 7, 0, 10, 5, 3, 14, 9, 11), + (7, 15, 5, 10, 8, 1, 6, 13, 0, 9, 3, 14, 11, 4, 2, 12), + (5, 13, 15, 6, 9, 2, 12, 10, 11, 7, 8, 1, 4, 3, 14, 0), + (8, 14, 2, 5, 6, 9, 1, 12, 15, 4, 11, 0, 13, 10, 3, 7), + (1, 7, 14, 13, 0, 5, 8, 3, 4, 15, 10, 6, 9, 12, 11, 2), + ), + "id-GostR3411-94-TestParamSet": ( + (4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3), + (14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9), + (5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11), + (7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3), + (6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2), + (4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14), + (13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12), + (1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12), + ), + "id-GostR3411-94-CryptoProParamSet": ( + (10, 4, 5, 6, 8, 1, 3, 7, 13, 12, 14, 0, 9, 2, 11, 15), + (5, 15, 4, 0, 2, 13, 11, 9, 1, 7, 6, 3, 12, 14, 10, 8), + (7, 15, 12, 14, 9, 4, 1, 0, 3, 11, 5, 2, 6, 10, 8, 13), + (4, 10, 7, 12, 0, 15, 2, 8, 14, 1, 6, 5, 13, 11, 9, 3), + (7, 6, 4, 11, 9, 12, 2, 10, 1, 8, 0, 14, 15, 13, 3, 5), + (7, 6, 2, 4, 13, 9, 15, 0, 10, 1, 5, 11, 8, 14, 12, 3), + (13, 14, 4, 1, 7, 0, 5, 10, 3, 12, 8, 15, 6, 2, 9, 11), + (1, 3, 10, 9, 5, 11, 4, 15, 8, 6, 7, 14, 13, 0, 2, 12), + ), + "EACParamSet": ( + (11, 4, 8, 10, 9, 7, 0, 3, 1, 6, 2, 15, 14, 5, 12, 13), + (1, 7, 14, 9, 11, 3, 15, 12, 0, 5, 4, 6, 13, 10, 8, 2), + (7, 3, 1, 9, 2, 4, 13, 15, 8, 10, 12, 6, 5, 0, 11, 14), + (10, 5, 15, 7, 14, 11, 3, 9, 2, 8, 1, 12, 0, 4, 6, 13), + (0, 14, 6, 11, 9, 3, 8, 4, 12, 15, 10, 5, 13, 7, 1, 2), + (9, 2, 11, 12, 0, 4, 5, 6, 3, 15, 13, 8, 1, 7, 14, 10), + (4, 0, 14, 1, 5, 11, 8, 3, 12, 2, 9, 7, 6, 10, 13, 15), + (7, 14, 12, 13, 9, 4, 8, 15, 10, 2, 6, 0, 3, 11, 5, 1), + ), +} +SBOXES["AppliedCryptography"] = SBOXES["id-GostR3411-94-TestParamSet"] + + +def _K(s, _in): + """S-box substitution + + :param s: S-box + :param _in: 32-bit word + :returns: substituted 32-bit word + """ + return ( + (s[0][(_in >> 0) & 0x0F] << 0) + + (s[1][(_in >> 4) & 0x0F] << 4) + + (s[2][(_in >> 8) & 0x0F] << 8) + + (s[3][(_in >> 12) & 0x0F] << 12) + + (s[4][(_in >> 16) & 0x0F] << 16) + + (s[5][(_in >> 20) & 0x0F] << 20) + + (s[6][(_in >> 24) & 0x0F] << 24) + + (s[7][(_in >> 28) & 0x0F] << 28) + ) + + +def block2ns(data): + """Convert block to N1 and N2 integers + """ + data = bytearray(data) + return ( + data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24, + data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24, + ) + + +def ns2block(ns): + """Convert N1 and N2 integers to 8-byte block + """ + n1, n2 = ns + return bytes(bytearray(( + (n2 >> 0) & 0xFF, (n2 >> 8) & 0xFF, (n2 >> 16) & 0xFF, (n2 >> 24) & 0xFF, + (n1 >> 0) & 0xFF, (n1 >> 8) & 0xFF, (n1 >> 16) & 0xFF, (n1 >> 24) & 0xFF, + ))) + + +def _shift11(x): + """11-bit cyclic shift + """ + return ((x << 11) & (2 ** 32 - 1)) | ((x >> (32 - 11)) & (2 ** 32 - 1)) + + +def validate_key(key): + if len(key) != KEYSIZE: + raise ValueError("Invalid key size") + + +def validate_iv(iv): + if len(iv) != BLOCKSIZE: + raise ValueError("Invalid IV size") + + +def validate_sbox(sbox): + if sbox not in SBOXES: + raise ValueError("Unknown sbox supplied") + + +def xcrypt(seq, sbox, key, ns): + """Perform full-round single-block operation + + :param seq: sequence of K_i S-box applying (either encrypt or decrypt) + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + :param bytes key: 256-bit encryption key + :param ns: N1 and N2 integers + :type ns: (int, int) + :returns: resulting N1 and N2 + :rtype: (int, int) + """ + s = SBOXES[sbox] + w = bytearray(key) + x = [ + w[0 + i * 4] | + w[1 + i * 4] << 8 | + w[2 + i * 4] << 16 | + w[3 + i * 4] << 24 for i in range(8) + ] + n1, n2 = ns + for i in seq: + n1, n2 = _shift11(_K(s, (n1 + x[i]) % (2 ** 32))) ^ n2, n1 + return n1, n2 + + +def encrypt(sbox, key, ns): + """Encrypt single block + """ + return xcrypt(SEQ_ENCRYPT, sbox, key, ns) + + +def decrypt(sbox, key, ns): + """Decrypt single block + """ + return xcrypt(SEQ_DECRYPT, sbox, key, ns) + + +def ecb(key, data, action, sbox=DEFAULT_SBOX): + """ECB mode of operation + + :param bytes key: encryption key + :param data: plaintext + :type data: bytes, multiple of BLOCKSIZE + :param func action: "encrypt"/"decrypt" + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + :returns: ciphertext + :rtype: bytes + """ + validate_key(key) + validate_sbox(sbox) + if not data or len(data) % BLOCKSIZE != 0: + raise ValueError("Data is not blocksize aligned") + result = [] + for i in xrange(0, len(data), BLOCKSIZE): + result.append(ns2block(action( + sbox, key, block2ns(data[i:i + BLOCKSIZE]) + ))) + return b"".join(result) + + +ecb_encrypt = partial(ecb, action=encrypt) +ecb_decrypt = partial(ecb, action=decrypt) + + +def cbc_encrypt(key, data, iv=8 * b"\x00", pad=True, sbox=DEFAULT_SBOX, mesh=False): + """CBC encryption mode of operation + + :param bytes key: encryption key + :param bytes data: plaintext + :param iv: initialization vector + :type iv: bytes, BLOCKSIZE length + :type bool pad: perform ISO/IEC 7816-4 padding + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + :param bool mesh: enable key meshing + :returns: ciphertext + :rtype: bytes + + 34.13-2015 padding method 2 is used. + """ + validate_key(key) + validate_iv(iv) + validate_sbox(sbox) + if not data: + raise ValueError("No data supplied") + if pad: + data = pad2(data, BLOCKSIZE) + if len(data) % BLOCKSIZE != 0: + raise ValueError("Data is not blocksize aligned") + ciphertext = [iv] + for i in xrange(0, len(data), BLOCKSIZE): + if mesh and i >= MESH_MAX_DATA and i % MESH_MAX_DATA == 0: + key, _ = meshing(key, iv, sbox=sbox) + ciphertext.append(ns2block(encrypt(sbox, key, block2ns( + strxor(ciphertext[-1], data[i:i + BLOCKSIZE]) + )))) + return b"".join(ciphertext) + + +def cbc_decrypt(key, data, pad=True, sbox=DEFAULT_SBOX, mesh=False): + """CBC decryption mode of operation + + :param bytes key: encryption key + :param bytes data: ciphertext + :type bool pad: perform ISO/IEC 7816-4 unpadding after decryption + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + :param bool mesh: enable key meshing + :returns: plaintext + :rtype: bytes + """ + validate_key(key) + validate_sbox(sbox) + if not data or len(data) % BLOCKSIZE != 0: + raise ValueError("Data is not blocksize aligned") + if len(data) < 2 * BLOCKSIZE: + raise ValueError("There is no either data, or IV in ciphertext") + iv = data[:BLOCKSIZE] + plaintext = [] + for i in xrange(BLOCKSIZE, len(data), BLOCKSIZE): + if ( + mesh and + (i - BLOCKSIZE) >= MESH_MAX_DATA and + (i - BLOCKSIZE) % MESH_MAX_DATA == 0 + ): + key, _ = meshing(key, iv, sbox=sbox) + plaintext.append(strxor( + ns2block(decrypt(sbox, key, block2ns(data[i:i + BLOCKSIZE]))), + data[i - BLOCKSIZE:i], + )) + if pad: + plaintext[-1] = unpad2(plaintext[-1], BLOCKSIZE) + return b"".join(plaintext) + + +def cnt(key, data, iv=8 * b"\x00", sbox=DEFAULT_SBOX): + """Counter mode of operation + + :param bytes key: encryption key + :param bytes data: plaintext + :param iv: initialization vector + :type iv: bytes, BLOCKSIZE length + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + :returns: ciphertext + :rtype: bytes + + For decryption you use the same function again. + """ + validate_key(key) + validate_iv(iv) + validate_sbox(sbox) + if not data: + raise ValueError("No data supplied") + n2, n1 = encrypt(sbox, key, block2ns(iv)) + gamma = [] + for _ in xrange(0, len(data) + pad_size(len(data), BLOCKSIZE), BLOCKSIZE): + n1 = (n1 + C2) % (2 ** 32) + n2 = (n2 + C1) % (2 ** 32 - 1) + gamma.append(ns2block(encrypt(sbox, key, (n1, n2)))) + return strxor(b"".join(gamma), data) + + +MESH_CONST = hexdec("6900722264C904238D3ADB9646E92AC418FEAC9400ED0712C086DCC2EF4CA92B") +MESH_MAX_DATA = 1024 + + +def meshing(key, iv, sbox=DEFAULT_SBOX): + """:rfc:`4357` key meshing + """ + key = ecb_decrypt(key, MESH_CONST, sbox=sbox) + iv = ecb_encrypt(key, iv, sbox=sbox) + return key, iv + + +def cfb_encrypt(key, data, iv=8 * b"\x00", sbox=DEFAULT_SBOX, mesh=False): + """CFB encryption mode of operation + + :param bytes key: encryption key + :param bytes data: plaintext + :param iv: initialization vector + :type iv: bytes, BLOCKSIZE length + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + :param bool mesh: enable key meshing + :returns: ciphertext + :rtype: bytes + """ + validate_key(key) + validate_iv(iv) + validate_sbox(sbox) + if not data: + raise ValueError("No data supplied") + ciphertext = [iv] + for i in xrange(0, len(data) + pad_size(len(data), BLOCKSIZE), BLOCKSIZE): + if mesh and i >= MESH_MAX_DATA and i % MESH_MAX_DATA == 0: + key, iv = meshing(key, ciphertext[-1], sbox=sbox) + ciphertext.append(strxor( + data[i:i + BLOCKSIZE], + ns2block(encrypt(sbox, key, block2ns(iv))), + )) + continue + ciphertext.append(strxor( + data[i:i + BLOCKSIZE], + ns2block(encrypt(sbox, key, block2ns(ciphertext[-1]))), + )) + return b"".join(ciphertext[1:]) + + +def cfb_decrypt(key, data, iv=8 * b"\x00", sbox=DEFAULT_SBOX, mesh=False): + """CFB decryption mode of operation + + :param bytes key: encryption key + :param bytes data: plaintext + :param iv: initialization vector + :type iv: bytes, BLOCKSIZE length + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + :param bool mesh: enable key meshing + :returns: ciphertext + :rtype: bytes + """ + validate_key(key) + validate_iv(iv) + validate_sbox(sbox) + if not data: + raise ValueError("No data supplied") + plaintext = [] + data = iv + data + for i in xrange(BLOCKSIZE, len(data) + pad_size(len(data), BLOCKSIZE), BLOCKSIZE): + if ( + mesh and + (i - BLOCKSIZE) >= MESH_MAX_DATA and + (i - BLOCKSIZE) % MESH_MAX_DATA == 0 + ): + key, iv = meshing(key, data[i - BLOCKSIZE:i], sbox=sbox) + plaintext.append(strxor( + data[i:i + BLOCKSIZE], + ns2block(encrypt(sbox, key, block2ns(iv))), + )) + continue + plaintext.append(strxor( + data[i:i + BLOCKSIZE], + ns2block(encrypt(sbox, key, block2ns(data[i - BLOCKSIZE:i]))), + )) + return b"".join(plaintext) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/gost28147_mac.py b/xmlrpcserver/deps/pygost-5.12/pygost/gost28147_mac.py new file mode 100644 index 0000000..aab2805 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/gost28147_mac.py @@ -0,0 +1,99 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""GOST 28147-89 MAC +""" + +from copy import copy + +from pygost.gost28147 import block2ns +from pygost.gost28147 import BLOCKSIZE +from pygost.gost28147 import DEFAULT_SBOX +from pygost.gost28147 import ns2block +from pygost.gost28147 import validate_iv +from pygost.gost28147 import validate_key +from pygost.gost28147 import validate_sbox +from pygost.gost28147 import xcrypt +from pygost.gost3413 import pad1 +from pygost.iface import PEP247 +from pygost.utils import strxor +from pygost.utils import xrange + +digest_size = 8 +SEQ_MAC = ( + 0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 4, 5, 6, 7, +) + + +class MAC(PEP247): + """GOST 28147-89 MAC mode of operation + + >>> m = MAC(key=key) + >>> m.update("some data") + >>> m.update("another data") + >>> m.hexdigest()[:8] + 'a687a08b' + """ + digest_size = digest_size + + def __init__(self, key, data=b"", iv=8 * b"\x00", sbox=DEFAULT_SBOX): + """ + :param key: authentication key + :type key: bytes, 32 bytes + :param iv: initialization vector + :type iv: bytes, BLOCKSIZE length + :param sbox: S-box parameters to use + :type sbox: str, SBOXES'es key + """ + validate_key(key) + validate_iv(iv) + validate_sbox(sbox) + self.key = key + self.data = data + self.iv = iv + self.sbox = sbox + + def copy(self): + return MAC(self.key, copy(self.data), self.iv, self.sbox) + + def update(self, data): + """Append data that has to be authenticated + """ + self.data += data + + def digest(self): + """Get MAC tag of supplied data + + You have to provide at least single byte of data. + If you want to produce tag length of 3 bytes, then + ``digest()[:3]``. + """ + if not self.data: + raise ValueError("No data processed") + data = pad1(self.data, BLOCKSIZE) + prev = block2ns(self.iv)[::-1] + for i in xrange(0, len(data), BLOCKSIZE): + prev = xcrypt( + SEQ_MAC, self.sbox, self.key, block2ns(strxor( + data[i:i + BLOCKSIZE], + ns2block(prev), + )), + )[::-1] + return ns2block(prev) + + +def new(key, data=b"", iv=8 * b"\x00", sbox=DEFAULT_SBOX): + return MAC(key, data, iv, sbox) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/gost3410.py b/xmlrpcserver/deps/pygost-5.12/pygost/gost3410.py new file mode 100644 index 0000000..cdb5b03 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/gost3410.py @@ -0,0 +1,404 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""GOST R 34.10 public-key signature function. + +This is implementation of GOST R 34.10-2001 (:rfc:`5832`), GOST R +34.10-2012 (:rfc:`7091`). The difference between 2001 and 2012 is the +key, digest and signature lengths. +""" + +from os import urandom + +from pygost.utils import bytes2long +from pygost.utils import hexdec +from pygost.utils import long2bytes +from pygost.utils import modinvert + + +def point_size(point): + """Determine is it either 256 or 512 bit point + """ + return (512 // 8) if point.bit_length() > 256 else (256 // 8) + + +class GOST3410Curve(object): + """GOST 34.10 validated curve + + >>> curve = CURVES["id-GostR3410-2001-TestParamSet"] + >>> prv = prv_unmarshal(urandom(32)) + >>> signature = sign(curve, prv, GOST341194(data).digest()) + >>> pub = public_key(curve, prv) + >>> verify(curve, pub, GOST341194(data).digest(), signature) + True + + :param long p: characteristic of the underlying prime field + :param long q: elliptic curve subgroup order + :param long a, b: coefficients of the equation of the elliptic curve in + the canonical form + :param long x, y: the coordinate of the point P (generator of the + subgroup of order q) of the elliptic curve in + the canonical form + :param long e, d: coefficients of the equation of the elliptic curve in + the twisted Edwards form + :param str name: human-readable curve name + """ + + def __init__(self, p, q, a, b, x, y, cofactor=1, e=None, d=None, name=None): + self.p = p + self.q = q + self.a = a + self.b = b + self.x = x + self.y = y + self.cofactor = cofactor + self.e = e + self.d = d + if not self.contains((x, y)): + raise ValueError("Invalid parameters") + self._st = None + self.name = name + + @property + def point_size(self): + return point_size(self.p) + + def __repr__(self): + return "<%s: %s>" % (self.__class__.__name__, self.name) + + def pos(self, v): + """Make positive number + """ + if v < 0: + return v + self.p + return v + + def contains(self, point): + """Is point on the curve? + + :type point: (long, long) + """ + x, y = point + r1 = y * y % self.p + r2 = ((x * x + self.a) * x + self.b) % self.p + return r1 == self.pos(r2) + + def _add(self, p1x, p1y, p2x, p2y): + if p1x == p2x and p1y == p2y: + # double + t = ((3 * p1x * p1x + self.a) * modinvert(2 * p1y, self.p)) % self.p + else: + tx = self.pos(p2x - p1x) % self.p + ty = self.pos(p2y - p1y) % self.p + t = (ty * modinvert(tx, self.p)) % self.p + tx = self.pos(t * t - p1x - p2x) % self.p + ty = self.pos(t * (p1x - tx) - p1y) % self.p + return tx, ty + + def exp(self, degree, x=None, y=None): + x = x or self.x + y = y or self.y + tx = x + ty = y + if degree == 0: + raise ValueError("Bad degree value") + degree -= 1 + while degree != 0: + if degree & 1 == 1: + tx, ty = self._add(tx, ty, x, y) + degree = degree >> 1 + x, y = self._add(x, y, x, y) + return tx, ty + + def st(self): + """Compute s/t parameters for twisted Edwards curve points conversion + """ + if self.e is None or self.d is None: + raise ValueError("Non twisted Edwards curve") + if self._st is not None: + return self._st + self._st = ( + self.pos(self.e - self.d) * modinvert(4, self.p) % self.p, + (self.e + self.d) * modinvert(6, self.p) % self.p, + ) + return self._st + + +CURVES = { + "GostR3410_2001_ParamSet_cc": GOST3410Curve( + p=bytes2long(hexdec("C0000000000000000000000000000000000000000000000000000000000003C7")), + q=bytes2long(hexdec("5fffffffffffffffffffffffffffffff606117a2f4bde428b7458a54b6e87b85")), + a=bytes2long(hexdec("C0000000000000000000000000000000000000000000000000000000000003c4")), + b=bytes2long(hexdec("2d06B4265ebc749ff7d0f1f1f88232e81632e9088fd44b7787d5e407e955080c")), + x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000002")), + y=bytes2long(hexdec("a20e034bf8813ef5c18d01105e726a17eb248b264ae9706f440bedc8ccb6b22c")), + ), + "id-GostR3410-2001-TestParamSet": GOST3410Curve( + p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000431")), + q=bytes2long(hexdec("8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B3")), + a=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000007")), + b=bytes2long(hexdec("5FBFF498AA938CE739B8E022FBAFEF40563F6E6A3472FC2A514C0CE9DAE23B7E")), + x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000002")), + y=bytes2long(hexdec("08E2A8A0E65147D4BD6316030E16D19C85C97F0A9CA267122B96ABBCEA7E8FC8")), + ), + "id-tc26-gost-3410-12-256-paramSetA": GOST3410Curve( + p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")), + q=bytes2long(hexdec("400000000000000000000000000000000FD8CDDFC87B6635C115AF556C360C67")), + a=bytes2long(hexdec("C2173F1513981673AF4892C23035A27CE25E2013BF95AA33B22C656F277E7335")), + b=bytes2long(hexdec("295F9BAE7428ED9CCC20E7C359A9D41A22FCCD9108E17BF7BA9337A6F8AE9513")), + x=bytes2long(hexdec("91E38443A5E82C0D880923425712B2BB658B9196932E02C78B2582FE742DAA28")), + y=bytes2long(hexdec("32879423AB1A0375895786C4BB46E9565FDE0B5344766740AF268ADB32322E5C")), + cofactor=4, + e=0x01, + d=bytes2long(hexdec("0605F6B7C183FA81578BC39CFAD518132B9DF62897009AF7E522C32D6DC7BFFB")), + ), + "id-tc26-gost-3410-12-256-paramSetB": GOST3410Curve( + p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97")), + q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893")), + a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94")), + b=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000a6")), + x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")), + y=bytes2long(hexdec("8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14")), + ), + "id-tc26-gost-3410-12-256-paramSetC": GOST3410Curve( + p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C99")), + q=bytes2long(hexdec("800000000000000000000000000000015F700CFFF1A624E5E497161BCC8A198F")), + a=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000C96")), + b=bytes2long(hexdec("3E1AF419A269A5F866A7D3C25C3DF80AE979259373FF2B182F49D4CE7E1BBC8B")), + x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000001")), + y=bytes2long(hexdec("3FA8124359F96680B83D1C3EB2C070E5C545C9858D03ECFB744BF8D717717EFC")), + ), + "id-tc26-gost-3410-12-256-paramSetD": GOST3410Curve( + p=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B")), + q=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9")), + a=bytes2long(hexdec("9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598")), + b=bytes2long(hexdec("000000000000000000000000000000000000000000000000000000000000805a")), + x=bytes2long(hexdec("0000000000000000000000000000000000000000000000000000000000000000")), + y=bytes2long(hexdec("41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67")), + ), + "id-tc26-gost-3410-12-512-paramSetTest": GOST3410Curve( + p=bytes2long(hexdec("4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DF1D852741AF4704A0458047E80E4546D35B8336FAC224DD81664BBF528BE6373")), + q=bytes2long(hexdec("4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DA82F2D7ECB1DBAC719905C5EECC423F1D86E25EDBE23C595D644AAF187E6E6DF")), + a=7, + b=bytes2long(hexdec("1CFF0806A31116DA29D8CFA54E57EB748BC5F377E49400FDD788B649ECA1AC4361834013B2AD7322480A89CA58E0CF74BC9E540C2ADD6897FAD0A3084F302ADC")), + x=bytes2long(hexdec("24D19CC64572EE30F396BF6EBBFD7A6C5213B3B3D7057CC825F91093A68CD762FD60611262CD838DC6B60AA7EEE804E28BC849977FAC33B4B530F1B120248A9A")), + y=bytes2long(hexdec("2BB312A43BD2CE6E0D020613C857ACDDCFBF061E91E5F2C3F32447C259F39B2C83AB156D77F1496BF7EB3351E1EE4E43DC1A18B91B24640B6DBB92CB1ADD371E")), + ), + "id-tc26-gost-3410-12-512-paramSetA": GOST3410Curve( + p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")), + q=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275")), + a=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4")), + b=bytes2long(hexdec("E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760")), + x=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003")), + y=bytes2long(hexdec("7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4")), + ), + "id-tc26-gost-3410-12-512-paramSetB": GOST3410Curve( + p=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F")), + q=bytes2long(hexdec("800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD")), + a=bytes2long(hexdec("8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C")), + b=bytes2long(hexdec("687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116")), + x=bytes2long(hexdec("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")), + y=bytes2long(hexdec("1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD")), + ), + "id-tc26-gost-3410-12-512-paramSetC": GOST3410Curve( + p=bytes2long(hexdec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7")), + q=bytes2long(hexdec("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED")), + a=bytes2long(hexdec("DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3")), + b=bytes2long(hexdec("B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1")), + x=bytes2long(hexdec("E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148")), + y=bytes2long(hexdec("F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F")), + cofactor=4, + e=0x01, + d=bytes2long(hexdec("9E4F5D8C017D8D9F13A5CF3CDF5BFE4DAB402D54198E31EBDE28A0621050439CA6B39E0A515C06B304E2CE43E79E369E91A0CFC2BC2A22B4CA302DBB33EE7550")), + ), +} +CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] = CURVES["id-tc26-gost-3410-12-256-paramSetB"] +CURVES["id-GostR3410-2001-CryptoPro-B-ParamSet"] = CURVES["id-tc26-gost-3410-12-256-paramSetC"] +CURVES["id-GostR3410-2001-CryptoPro-C-ParamSet"] = CURVES["id-tc26-gost-3410-12-256-paramSetD"] +CURVES["id-GostR3410-2001-CryptoPro-XchA-ParamSet"] = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] +CURVES["id-GostR3410-2001-CryptoPro-XchB-ParamSet"] = CURVES["id-GostR3410-2001-CryptoPro-C-ParamSet"] +CURVES["id-tc26-gost-3410-2012-256-paramSetA"] = CURVES["id-tc26-gost-3410-12-256-paramSetA"] +CURVES["id-tc26-gost-3410-2012-256-paramSetB"] = CURVES["id-tc26-gost-3410-12-256-paramSetB"] +CURVES["id-tc26-gost-3410-2012-256-paramSetC"] = CURVES["id-tc26-gost-3410-12-256-paramSetC"] +CURVES["id-tc26-gost-3410-2012-256-paramSetD"] = CURVES["id-tc26-gost-3410-12-256-paramSetD"] +CURVES["id-tc26-gost-3410-2012-512-paramSetTest"] = CURVES["id-tc26-gost-3410-12-512-paramSetTest"] +CURVES["id-tc26-gost-3410-2012-512-paramSetA"] = CURVES["id-tc26-gost-3410-12-512-paramSetA"] +CURVES["id-tc26-gost-3410-2012-512-paramSetB"] = CURVES["id-tc26-gost-3410-12-512-paramSetB"] +CURVES["id-tc26-gost-3410-2012-512-paramSetC"] = CURVES["id-tc26-gost-3410-12-512-paramSetC"] +for _name, _curve in CURVES.items(): + _curve.name = _name +DEFAULT_CURVE = CURVES["id-tc26-gost-3410-12-256-paramSetB"] + + +def public_key(curve, prv): + """Generate public key from the private one + + :param GOST3410Curve curve: curve to use + :param long prv: private key + :returns: public key's parts, X and Y + :rtype: (long, long) + """ + return curve.exp(prv) + + +def sign(curve, prv, digest, rand=None): + """Calculate signature for provided digest + + :param GOST3410Curve curve: curve to use + :param long prv: private key + :param digest: digest for signing + :type digest: bytes, 32 or 64 bytes + :param rand: optional predefined random data used for k/r generation + :type rand: bytes, 32 or 64 bytes + :returns: signature, BE(S) || BE(R) + :rtype: bytes, 64 or 128 bytes + """ + size = curve.point_size + q = curve.q + e = bytes2long(digest) % q + if e == 0: + e = 1 + while True: + if rand is None: + rand = urandom(size) + elif len(rand) != size: + raise ValueError("rand length != %d" % size) + k = bytes2long(rand) % q + if k == 0: + continue + r, _ = curve.exp(k) + r %= q + if r == 0: + continue + d = prv * r + k *= e + s = (d + k) % q + if s == 0: + continue + break + return long2bytes(s, size) + long2bytes(r, size) + + +def verify(curve, pub, digest, signature): + """Verify provided digest with the signature + + :param GOST3410Curve curve: curve to use + :type pub: (long, long) + :param digest: digest needed to check + :type digest: bytes, 32 or 64 bytes + :param signature: signature to verify with + :type signature: bytes, 64 or 128 bytes + :rtype: bool + """ + size = curve.point_size + if len(signature) != size * 2: + raise ValueError("Invalid signature length") + q = curve.q + p = curve.p + s = bytes2long(signature[:size]) + r = bytes2long(signature[size:]) + if r <= 0 or r >= q or s <= 0 or s >= q: + return False + e = bytes2long(digest) % curve.q + if e == 0: + e = 1 + v = modinvert(e, q) + z1 = s * v % q + z2 = q - r * v % q + p1x, p1y = curve.exp(z1) + q1x, q1y = curve.exp(z2, pub[0], pub[1]) + lm = q1x - p1x + if lm < 0: + lm += p + lm = modinvert(lm, p) + z1 = q1y - p1y + lm = lm * z1 % p + lm = lm * lm % p + lm = lm - p1x - q1x + lm = lm % p + if lm < 0: + lm += p + lm %= q + # This is not constant time comparison! + return lm == r + + +def prv_unmarshal(prv): + """Unmarshal little-endian private key + + :param bytes prv: serialized private key + :rtype: long + + It is advisable to use :py:func:`pygost.gost3410.prv_marshal` to + assure that key i in curve's Q field for better compatibility with + some implementations. + """ + return bytes2long(prv[::-1]) + + +def prv_marshal(curve, prv): + """Marshal little-endian private key + + :param GOST3410Curve curve: curve to use + :param long prv: serialized private key + :rtype: bytes + + Key is in curve's Q field. + """ + return long2bytes(prv % curve.q, point_size(prv))[::-1] + + +def pub_marshal(pub): + """Marshal public key + + :type pub: (long, long) + :rtype: bytes + :returns: LE(X) || LE(Y) + """ + size = point_size(pub[0]) + return (long2bytes(pub[1], size) + long2bytes(pub[0], size))[::-1] + + +def pub_unmarshal(pub): + """Unmarshal public key + + :param pub: LE(X) || LE(Y) + :type pub: bytes + :rtype: (long, long) + """ + size = len(pub) // 2 + pub = pub[::-1] + return (bytes2long(pub[size:]), bytes2long(pub[:size])) + + +def uv2xy(curve, u, v): + """Convert twisted Edwards curve U,V coordinates to Weierstrass X,Y + """ + s, t = curve.st() + k1 = (s * (1 + v)) % curve.p + k2 = curve.pos(1 - v) + x = t + k1 * modinvert(k2, curve.p) + y = k1 * modinvert(u * k2, curve.p) + return x % curve.p, y % curve.p + + +def xy2uv(curve, x, y): + """Convert Weierstrass X,Y coordinates to twisted Edwards curve U,V + """ + s, t = curve.st() + xmt = curve.pos(x - t) + u = xmt * modinvert(y, curve.p) + v = curve.pos(xmt - s) * modinvert(xmt + s, curve.p) + return u % curve.p, v % curve.p diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/gost3410_vko.py b/xmlrpcserver/deps/pygost-5.12/pygost/gost3410_vko.py new file mode 100644 index 0000000..92f4a26 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/gost3410_vko.py @@ -0,0 +1,95 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Key agreement functions, VKO GOST R 34.10-2001/2012 +""" + +from pygost.gost3410 import pub_marshal +from pygost.gost34112012256 import GOST34112012256 +from pygost.gost34112012512 import GOST34112012512 +from pygost.gost341194 import GOST341194 +from pygost.utils import bytes2long + + +def ukm_unmarshal(ukm): + """Unmarshal UKM value + + :type ukm: little-endian bytes + :rtype: long + """ + return bytes2long(ukm[::-1]) + + +def kek(curve, prv, pub, ukm): + if not curve.contains(pub): + raise ValueError("pub is not on the curve") + key = curve.exp(prv, pub[0], pub[1]) + key = curve.exp(curve.cofactor * ukm, key[0], key[1]) + return pub_marshal(key) + + +def kek_34102001(curve, prv, pub, ukm): + """Key agreement (34.10-2001, 34.11-94) + + :param GOST3410Curve curve: curve to use + :param long prv: private key + :param pub: public key + :type pub: (long, long) + :param long ukm: user keying material, VKO-factor + :returns: Key Encryption Key (shared key) + :rtype: bytes, 32 bytes + + Shared Key Encryption Key computation is based on + :rfc:`4357` VKO GOST R 34.10-2001 with little-endian + hash output. + """ + return GOST341194( + kek(curve, prv, pub, ukm), + sbox="id-GostR3411-94-CryptoProParamSet", + ).digest() + + +def kek_34102012256(curve, prv, pub, ukm=1): + """Key agreement (34.10-2012, 34.11-2012 256 bit) + + :param GOST3410Curve curve: curve to use + :param long prv: private key + :param pub: public key + :type pub: (long, long) + :param long ukm: user keying material, VKO-factor + :returns: Key Encryption Key (shared key) + :rtype: bytes, 32 bytes + + Shared Key Encryption Key computation is based on + :rfc:`7836` VKO GOST R 34.10-2012. + """ + return GOST34112012256(kek(curve, prv, pub, ukm)).digest() + + +def kek_34102012512(curve, prv, pub, ukm=1): + """Key agreement (34.10-2012, 34.11-2012 512 bit) + + :param GOST3410Curve curve: curve to use + :param long prv: private key + :param pub: public key + :type pub: (long, long) + :param long ukm: user keying material, VKO-factor + :returns: Key Encryption Key (shared key) + :rtype: bytes, 32 bytes + + Shared Key Encryption Key computation is based on + :rfc:`7836` VKO GOST R 34.10-2012. + """ + return GOST34112012512(kek(curve, prv, pub, ukm)).digest() diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/gost34112012.py b/xmlrpcserver/deps/pygost-5.12/pygost/gost34112012.py new file mode 100644 index 0000000..91782de --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/gost34112012.py @@ -0,0 +1,299 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""GOST R 34.11-2012 (Streebog) hash function common files + +This is implementation of :rfc:`6986`. Most function and variable names are +taken according to specification's terminology. +""" + +from copy import copy +from struct import pack +from struct import unpack + +from pygost.iface import PEP247 +from pygost.utils import hexdec +from pygost.utils import strxor +from pygost.utils import xrange + + +BLOCKSIZE = 64 +Pi = bytearray(( + 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, + 218, 35, 197, 4, 77, 233, 119, 240, 219, 147, 46, + 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, 249, + 24, 101, 90, 226, 92, 239, 33, 129, 28, 60, 66, + 139, 1, 142, 79, 5, 132, 2, 174, 227, 106, 143, + 160, 6, 11, 237, 152, 127, 212, 211, 31, 235, 52, + 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, + 58, 206, 204, 181, 112, 14, 86, 8, 12, 118, 18, + 191, 114, 19, 71, 156, 183, 93, 135, 21, 161, 150, + 41, 16, 123, 154, 199, 243, 145, 120, 111, 157, 158, + 178, 177, 50, 117, 25, 61, 255, 53, 138, 126, 109, + 84, 198, 128, 195, 189, 13, 87, 223, 245, 36, 169, + 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185, + 3, 224, 15, 236, 222, 122, 148, 176, 188, 220, 232, + 40, 80, 78, 51, 10, 74, 167, 151, 96, 115, 30, + 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65, + 173, 69, 70, 146, 39, 94, 85, 47, 140, 163, 165, + 125, 105, 213, 149, 59, 7, 88, 179, 64, 134, 172, + 29, 247, 48, 55, 107, 228, 136, 217, 231, 137, 225, + 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144, + 202, 216, 133, 97, 32, 113, 103, 164, 45, 43, 9, + 91, 203, 155, 37, 208, 190, 229, 108, 82, 89, 166, + 116, 210, 230, 244, 180, 192, 209, 102, 175, 194, 57, + 75, 99, 182, +)) + +A = [unpack(">Q", hexdec(s))[0] for s in ( + "8e20faa72ba0b470", "47107ddd9b505a38", "ad08b0e0c3282d1c", "d8045870ef14980e", + "6c022c38f90a4c07", "3601161cf205268d", "1b8e0b0e798c13c8", "83478b07b2468764", + "a011d380818e8f40", "5086e740ce47c920", "2843fd2067adea10", "14aff010bdd87508", + "0ad97808d06cb404", "05e23c0468365a02", "8c711e02341b2d01", "46b60f011a83988e", + "90dab52a387ae76f", "486dd4151c3dfdb9", "24b86a840e90f0d2", "125c354207487869", + "092e94218d243cba", "8a174a9ec8121e5d", "4585254f64090fa0", "accc9ca9328a8950", + "9d4df05d5f661451", "c0a878a0a1330aa6", "60543c50de970553", "302a1e286fc58ca7", + "18150f14b9ec46dd", "0c84890ad27623e0", "0642ca05693b9f70", "0321658cba93c138", + "86275df09ce8aaa8", "439da0784e745554", "afc0503c273aa42a", "d960281e9d1d5215", + "e230140fc0802984", "71180a8960409a42", "b60c05ca30204d21", "5b068c651810a89e", + "456c34887a3805b9", "ac361a443d1c8cd2", "561b0d22900e4669", "2b838811480723ba", + "9bcf4486248d9f5d", "c3e9224312c8c1a0", "effa11af0964ee50", "f97d86d98a327728", + "e4fa2054a80b329c", "727d102a548b194e", "39b008152acb8227", "9258048415eb419d", + "492c024284fbaec0", "aa16012142f35760", "550b8e9e21f7a530", "a48b474f9ef5dc18", + "70a6a56e2440598e", "3853dc371220a247", "1ca76e95091051ad", "0edd37c48a08a6d8", + "07e095624504536c", "8d70c431ac02a736", "c83862965601dd1b", "641c314b2b8ee083", +)] + +Tau = ( + 0, 8, 16, 24, 32, 40, 48, 56, + 1, 9, 17, 25, 33, 41, 49, 57, + 2, 10, 18, 26, 34, 42, 50, 58, + 3, 11, 19, 27, 35, 43, 51, 59, + 4, 12, 20, 28, 36, 44, 52, 60, + 5, 13, 21, 29, 37, 45, 53, 61, + 6, 14, 22, 30, 38, 46, 54, 62, + 7, 15, 23, 31, 39, 47, 55, 63, +) + +C = [hexdec("".join(s))[::-1] for s in ( + ( + "b1085bda1ecadae9ebcb2f81c0657c1f", + "2f6a76432e45d016714eb88d7585c4fc", + "4b7ce09192676901a2422a08a460d315", + "05767436cc744d23dd806559f2a64507", + ), + ( + "6fa3b58aa99d2f1a4fe39d460f70b5d7", + "f3feea720a232b9861d55e0f16b50131", + "9ab5176b12d699585cb561c2db0aa7ca", + "55dda21bd7cbcd56e679047021b19bb7", + ), + ( + "f574dcac2bce2fc70a39fc286a3d8435", + "06f15e5f529c1f8bf2ea7514b1297b7b", + "d3e20fe490359eb1c1c93a376062db09", + "c2b6f443867adb31991e96f50aba0ab2", + ), + ( + "ef1fdfb3e81566d2f948e1a05d71e4dd", + "488e857e335c3c7d9d721cad685e353f", + "a9d72c82ed03d675d8b71333935203be", + "3453eaa193e837f1220cbebc84e3d12e", + ), + ( + "4bea6bacad4747999a3f410c6ca92363", + "7f151c1f1686104a359e35d7800fffbd", + "bfcd1747253af5a3dfff00b723271a16", + "7a56a27ea9ea63f5601758fd7c6cfe57", + ), + ( + "ae4faeae1d3ad3d96fa4c33b7a3039c0", + "2d66c4f95142a46c187f9ab49af08ec6", + "cffaa6b71c9ab7b40af21f66c2bec6b6", + "bf71c57236904f35fa68407a46647d6e", + ), + ( + "f4c70e16eeaac5ec51ac86febf240954", + "399ec6c7e6bf87c9d3473e33197a93c9", + "0992abc52d822c3706476983284a0504", + "3517454ca23c4af38886564d3a14d493", + ), + ( + "9b1f5b424d93c9a703e7aa020c6e4141", + "4eb7f8719c36de1e89b4443b4ddbc49a", + "f4892bcb929b069069d18d2bd1a5c42f", + "36acc2355951a8d9a47f0dd4bf02e71e", + ), + ( + "378f5a541631229b944c9ad8ec165fde", + "3a7d3a1b258942243cd955b7e00d0984", + "800a440bdbb2ceb17b2b8a9aa6079c54", + "0e38dc92cb1f2a607261445183235adb", + ), + ( + "abbedea680056f52382ae548b2e4f3f3", + "8941e71cff8a78db1fffe18a1b336103", + "9fe76702af69334b7a1e6c303b7652f4", + "3698fad1153bb6c374b4c7fb98459ced", + ), + ( + "7bcd9ed0efc889fb3002c6cd635afe94", + "d8fa6bbbebab07612001802114846679", + "8a1d71efea48b9caefbacd1d7d476e98", + "dea2594ac06fd85d6bcaa4cd81f32d1b", + ), + ( + "378ee767f11631bad21380b00449b17a", + "cda43c32bcdf1d77f82012d430219f9b", + "5d80ef9d1891cc86e71da4aa88e12852", + "faf417d5d9b21b9948bc924af11bd720", + ), +)] + + +def _lcache(): + cache = [] + for byteN in xrange(8): + cache.append([0 for _ in xrange(256)]) + for byteN in xrange(8): + for byteVal in xrange(256): + res64 = 0 + val = byteVal + for bitN in xrange(8): + if val & 0x80 > 0: + res64 ^= A[(7 - byteN) * 8 + bitN] + val <<= 1 + cache[byteN][byteVal] = res64 + return cache + + +# Trade memory for CPU for part of L() calculations +LCache = _lcache() + + +def add512bit(a, b): + a = int.from_bytes(a, "little") + b = int.from_bytes(b, "little") + r = (a + b) % (1 << 512) + return r.to_bytes(512 // 8, "little") + + +def g(n, hsh, msg): + res = E(LPS(strxor(hsh[:8], pack(">> m = GOST34112012(digest_size=32) + >>> m.update("foo") + >>> m.update("bar") + >>> m.hexdigest() + 'e3c9fd89226d93b489a9fe27d686806e24a514e3787bca053c698ec4616ceb78' + """ + block_size = BLOCKSIZE + + def __init__(self, data=b"", digest_size=64): + """ + :param digest_size: hash digest size to compute + :type digest_size: 32 or 64 bytes + """ + self._digest_size = digest_size + self.hsh = BLOCKSIZE * (b"\x01" if digest_size == 32 else b"\x00") + self.chk = bytearray(BLOCKSIZE * b"\x00") + self.n = 0 + self.buf = b"" + self.update(data) + + def copy(self): + obj = GOST34112012() + obj._digest_size = self._digest_size + obj.hsh = self.hsh + obj.chk = copy(self.chk) + obj.n = self.n + obj.buf = self.buf + return obj + + @property + def digest_size(self): + return self._digest_size + + def _update_block(self, block): + self.hsh = g(self.n, self.hsh, block) + self.chk = add512bit(self.chk, block) + self.n += 512 + + def update(self, data): + """Update state with the new data + """ + if len(self.buf) > 0: + chunk_len = BLOCKSIZE - len(self.buf) + self.buf += data[:chunk_len] + data = data[chunk_len:] + if len(self.buf) == BLOCKSIZE: + self._update_block(self.buf) + self.buf = b"" + while len(data) >= BLOCKSIZE: + self._update_block(data[:BLOCKSIZE]) + data = data[BLOCKSIZE:] + self.buf += data + + def digest(self): + """Get hash of the provided data + """ + data = self.buf + + # Padding + padblock_size = len(data) * 8 + data += b"\x01" + padlen = BLOCKSIZE - len(data) + if padlen != BLOCKSIZE: + data += b"\x00" * padlen + + hsh = g(self.n, self.hsh, data) + n = self.n + padblock_size + chk = add512bit(self.chk, data) + hsh = g(0, hsh, pack(" +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""GOST R 34.11-94 hash function + +This is implementation of :rfc:`5831`. Most function and variable names are +taken according to specification's terminology. +""" + +from copy import copy +from functools import partial +from struct import pack + +from pygost.gost28147 import block2ns +from pygost.gost28147 import encrypt +from pygost.gost28147 import ns2block +from pygost.gost28147 import validate_sbox +from pygost.iface import PEP247 +from pygost.pbkdf2 import pbkdf2 as pbkdf2_base +from pygost.utils import hexdec +from pygost.utils import hexenc +from pygost.utils import strxor +from pygost.utils import xrange + + +DEFAULT_SBOX = "id-GostR3411-94-CryptoProParamSet" +BLOCKSIZE = 32 +C2 = 32 * b"\x00" +C3 = hexdec(b"ff00ffff000000ffff0000ff00ffff0000ff00ff00ff00ffff00ff00ff00ff00") +C4 = 32 * b"\x00" +digest_size = 32 + + +def A(x): + x4, x3, x2, x1 = x[0:8], x[8:16], x[16:24], x[24:32] + return b"".join((strxor(x1, x2), x4, x3, x2)) + + +def P(x): + return bytearray(( + x[0], x[8], x[16], x[24], x[1], x[9], x[17], x[25], x[2], + x[10], x[18], x[26], x[3], x[11], x[19], x[27], x[4], x[12], + x[20], x[28], x[5], x[13], x[21], x[29], x[6], x[14], x[22], + x[30], x[7], x[15], x[23], x[31], + )) + + +def _chi(Y): + """Chi function + + This is some kind of LFSR. + """ + (y16, y15, y14, y13, y12, y11, y10, y9, y8, y7, y6, y5, y4, y3, y2, y1) = ( + Y[0:2], Y[2:4], Y[4:6], Y[6:8], Y[8:10], Y[10:12], Y[12:14], + Y[14:16], Y[16:18], Y[18:20], Y[20:22], Y[22:24], Y[24:26], + Y[26:28], Y[28:30], Y[30:32], + ) + by1, by2, by3, by4, by13, by16, byx = ( + bytearray(y1), bytearray(y2), bytearray(y3), bytearray(y4), + bytearray(y13), bytearray(y16), bytearray(2), + ) + byx[0] = by1[0] ^ by2[0] ^ by3[0] ^ by4[0] ^ by13[0] ^ by16[0] + byx[1] = by1[1] ^ by2[1] ^ by3[1] ^ by4[1] ^ by13[1] ^ by16[1] + return b"".join(( + bytes(byx), y16, y15, y14, y13, y12, y11, y10, y9, y8, y7, y6, y5, y4, y3, y2 + )) + + +def _step(hin, m, sbox): + """Step function + + H_out = f(H_in, m) + """ + # Generate keys + u = hin + v = m + w = strxor(hin, m) + k1 = P(w) + + u = strxor(A(u), C2) + v = A(A(v)) + w = strxor(u, v) + k2 = P(w) + + u = strxor(A(u), C3) + v = A(A(v)) + w = strxor(u, v) + k3 = P(w) + + u = strxor(A(u), C4) + v = A(A(v)) + w = strxor(u, v) + k4 = P(w) + + # Encipher + h4, h3, h2, h1 = hin[0:8], hin[8:16], hin[16:24], hin[24:32] + s1 = ns2block(encrypt(sbox, k1[::-1], block2ns(h1[::-1])))[::-1] + s2 = ns2block(encrypt(sbox, k2[::-1], block2ns(h2[::-1])))[::-1] + s3 = ns2block(encrypt(sbox, k3[::-1], block2ns(h3[::-1])))[::-1] + s4 = ns2block(encrypt(sbox, k4[::-1], block2ns(h4[::-1])))[::-1] + s = b"".join((s4, s3, s2, s1)) + + # Permute + # H_out = chi^61(H_in XOR chi(m XOR chi^12(S))) + x = s + for _ in xrange(12): + x = _chi(x) + x = strxor(x, m) + x = _chi(x) + x = strxor(hin, x) + for _ in xrange(61): + x = _chi(x) + return x + + +class GOST341194(PEP247): + """GOST 34.11-94 big-endian hash + + >>> m = GOST341194() + >>> m.update("foo") + >>> m.update("bar") + >>> m.hexdigest() + '3bd8a3a35917871dfa0d49f9e73e7c57eea028dc061133eb560849ea20c133af' + >>> GOST341194("foobar").hexdigest() + '3bd8a3a35917871dfa0d49f9e73e7c57eea028dc061133eb560849ea20c133af' + """ + block_size = BLOCKSIZE + digest_size = digest_size + + def __init__(self, data=b"", sbox=DEFAULT_SBOX): + """ + :param bytes data: provide initial data + :param bytes sbox: S-box to use + """ + validate_sbox(sbox) + self.data = data + self.sbox = sbox + + def copy(self): + return GOST341194(copy(self.data), self.sbox) + + def update(self, data): + """Append data that has to be hashed + """ + self.data += data + + def digest(self): + """Get hash of the provided data + """ + _len = 0 + checksum = 0 + h = 32 * b"\x00" + m = self.data + for i in xrange(0, len(m), BLOCKSIZE): + part = m[i:i + BLOCKSIZE][::-1] + _len += len(part) * 8 + checksum = (checksum + int(hexenc(part), 16)) % (2 ** 256) + if len(part) < BLOCKSIZE: + part = b"\x00" * (BLOCKSIZE - len(part)) + part + h = _step(h, part, self.sbox) + h = _step(h, 24 * b"\x00" + pack(">Q", _len), self.sbox) + + checksum = hex(checksum)[2:].rstrip("L") + if len(checksum) % 2 != 0: + checksum = "0" + checksum + checksum = hexdec(checksum) + checksum = b"\x00" * (BLOCKSIZE - len(checksum)) + checksum + h = _step(h, checksum, self.sbox) + return h[::-1] + + +def new(data=b"", sbox=DEFAULT_SBOX): + return GOST341194(data, sbox) + + +PBKDF2_HASHER = partial(GOST341194, sbox="id-GostR3411-94-CryptoProParamSet") + + +def pbkdf2(password, salt, iterations, dklen): + return pbkdf2_base(PBKDF2_HASHER, password, salt, iterations, dklen) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/gost3412.py b/xmlrpcserver/deps/pygost-5.12/pygost/gost3412.py new file mode 100644 index 0000000..b9472ee --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/gost3412.py @@ -0,0 +1,186 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""GOST 34.12-2015 64 and 128 bit block ciphers (:rfc:`7801`) + +Several precalculations are performed during this module importing. +""" + +from pygost.gost28147 import block2ns as gost28147_block2ns +from pygost.gost28147 import decrypt as gost28147_decrypt +from pygost.gost28147 import encrypt as gost28147_encrypt +from pygost.gost28147 import ns2block as gost28147_ns2block +from pygost.utils import strxor +from pygost.utils import xrange + + +KEYSIZE = 32 + +LC = bytearray(( + 148, 32, 133, 16, 194, 192, 1, 251, 1, 192, 194, 16, 133, 32, 148, 1, +)) +PI = bytearray(( + 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, 218, 35, 197, 4, 77, + 233, 119, 240, 219, 147, 46, 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, + 249, 24, 101, 90, 226, 92, 239, 33, 129, 28, 60, 66, 139, 1, 142, 79, 5, + 132, 2, 174, 227, 106, 143, 160, 6, 11, 237, 152, 127, 212, 211, 31, 235, + 52, 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, 58, 206, 204, 181, + 112, 14, 86, 8, 12, 118, 18, 191, 114, 19, 71, 156, 183, 93, 135, 21, 161, + 150, 41, 16, 123, 154, 199, 243, 145, 120, 111, 157, 158, 178, 177, 50, 117, + 25, 61, 255, 53, 138, 126, 109, 84, 198, 128, 195, 189, 13, 87, 223, 245, + 36, 169, 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185, 3, 224, 15, + 236, 222, 122, 148, 176, 188, 220, 232, 40, 80, 78, 51, 10, 74, 167, 151, + 96, 115, 30, 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65, 173, 69, 70, + 146, 39, 94, 85, 47, 140, 163, 165, 125, 105, 213, 149, 59, 7, 88, 179, 64, + 134, 172, 29, 247, 48, 55, 107, 228, 136, 217, 231, 137, 225, 27, 131, 73, + 76, 63, 248, 254, 141, 83, 170, 144, 202, 216, 133, 97, 32, 113, 103, 164, + 45, 43, 9, 91, 203, 155, 37, 208, 190, 229, 108, 82, 89, 166, 116, 210, 230, + 244, 180, 192, 209, 102, 175, 194, 57, 75, 99, 182, +)) + +######################################################################## +# Precalculate inverted PI value as a performance optimization. +# Actually it can be computed only once and saved on the disk. +######################################################################## +PIinv = bytearray(256) +for x in xrange(256): + PIinv[PI[x]] = x + + +def gf(a, b): + c = 0 + while b: + if b & 1: + c ^= a + if a & 0x80: + a = (a << 1) ^ 0x1C3 + else: + a <<= 1 + b >>= 1 + return c + +######################################################################## +# Precalculate all possible gf(byte, byte) values as a performance +# optimization. +# Actually it can be computed only once and saved on the disk. +######################################################################## + + +GF = [bytearray(256) for _ in xrange(256)] + +for x in xrange(256): + for y in xrange(256): + GF[x][y] = gf(x, y) + + +def L(blk, rounds=16): + for _ in range(rounds): + t = blk[15] + for i in range(14, -1, -1): + blk[i + 1] = blk[i] + t ^= GF[blk[i]][LC[i]] + blk[0] = t + return blk + + +def Linv(blk): + for _ in range(16): + t = blk[0] + for i in range(15): + blk[i] = blk[i + 1] + t ^= GF[blk[i]][LC[i]] + blk[15] = t + return blk + +######################################################################## +# Precalculate values of the C -- it does not depend on key. +# Actually it can be computed only once and saved on the disk. +######################################################################## + + +C = [] + +for x in range(1, 33): + y = bytearray(16) + y[15] = x + C.append(L(y)) + + +def lp(blk): + return L([PI[v] for v in blk]) + + +class GOST3412Kuznechik(object): + """GOST 34.12-2015 128-bit block cipher Кузнечик (Kuznechik) + """ + blocksize = 16 + + def __init__(self, key): + """ + :param key: encryption/decryption key + :type key: bytes, 32 bytes + + Key scheduling (roundkeys precomputation) is performed here. + """ + kr0 = bytearray(key[:16]) + kr1 = bytearray(key[16:]) + self.ks = [kr0, kr1] + for i in range(4): + for j in range(8): + k = lp(bytearray(strxor(C[8 * i + j], kr0))) + kr0, kr1 = [strxor(k, kr1), kr0] + self.ks.append(kr0) + self.ks.append(kr1) + + def encrypt(self, blk): + blk = bytearray(blk) + for i in range(9): + blk = lp(bytearray(strxor(self.ks[i], blk))) + return bytes(strxor(self.ks[9], blk)) + + def decrypt(self, blk): + blk = bytearray(blk) + for i in range(9, 0, -1): + blk = [PIinv[v] for v in Linv(bytearray(strxor(self.ks[i], blk)))] + return bytes(strxor(self.ks[0], blk)) + + +class GOST3412Magma(object): + """GOST 34.12-2015 64-bit block cipher Магма (Magma) + """ + blocksize = 8 + + def __init__(self, key): + """ + :param key: encryption/decryption key + :type key: bytes, 32 bytes + """ + # Backward compatibility key preparation for 28147-89 key schedule + self.key = b"".join(key[i * 4:i * 4 + 4][::-1] for i in range(8)) + self.sbox = "id-tc26-gost-28147-param-Z" + + def encrypt(self, blk): + return gost28147_ns2block(gost28147_encrypt( + self.sbox, + self.key, + gost28147_block2ns(blk[::-1]), + ))[::-1] + + def decrypt(self, blk): + return gost28147_ns2block(gost28147_decrypt( + self.sbox, + self.key, + gost28147_block2ns(blk[::-1]), + ))[::-1] diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/gost3413.py b/xmlrpcserver/deps/pygost-5.12/pygost/gost3413.py new file mode 100644 index 0000000..f3cb5da --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/gost3413.py @@ -0,0 +1,392 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""GOST R 34.13-2015: Modes of operation for block ciphers + +This module currently includes only padding methods. +""" + +from os import urandom + +from pygost.utils import bytes2long +from pygost.utils import long2bytes +from pygost.utils import strxor +from pygost.utils import xrange + + +KEYSIZE = 32 + + +def pad_size(data_size, blocksize): + """Calculate required pad size to full up blocksize + """ + if data_size < blocksize: + return blocksize - data_size + if data_size % blocksize == 0: + return 0 + return blocksize - data_size % blocksize + + +def pad1(data, blocksize): + """Padding method 1 + + Just fill up with zeros if necessary. + """ + return data + b"\x00" * pad_size(len(data), blocksize) + + +def pad2(data, blocksize): + """Padding method 2 (also known as ISO/IEC 7816-4) + + Add one bit and then fill up with zeros. + """ + return data + b"\x80" + b"\x00" * pad_size(len(data) + 1, blocksize) + + +def unpad2(data, blocksize): + """Unpad method 2 + """ + last_block = bytearray(data[-blocksize:]) + pad_index = last_block.rfind(b"\x80") + if pad_index == -1: + raise ValueError("Invalid padding") + for c in last_block[pad_index + 1:]: + if c != 0: + raise ValueError("Invalid padding") + return data[:-(blocksize - pad_index)] + + +def pad3(data, blocksize): + """Padding method 3 + """ + if pad_size(len(data), blocksize) == 0: + return data + return pad2(data, blocksize) + + +def ecb_encrypt(encrypter, bs, pt): + """ECB encryption mode of operation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes pt: already padded plaintext + """ + if not pt or len(pt) % bs != 0: + raise ValueError("Plaintext is not blocksize aligned") + ct = [] + for i in xrange(0, len(pt), bs): + ct.append(encrypter(pt[i:i + bs])) + return b"".join(ct) + + +def ecb_decrypt(decrypter, bs, ct): + """ECB decryption mode of operation + + :param decrypter: Decrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes ct: ciphertext + """ + if not ct or len(ct) % bs != 0: + raise ValueError("Ciphertext is not blocksize aligned") + pt = [] + for i in xrange(0, len(ct), bs): + pt.append(decrypter(ct[i:i + bs])) + return b"".join(pt) + + +def acpkm(encrypter, bs): + """Perform ACPKM key derivation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + """ + return b"".join([ + encrypter(bytes(bytearray(range(d, d + bs)))) + for d in range(0x80, 0x80 + bs * (KEYSIZE // bs), bs) + ]) + + +def ctr(encrypter, bs, data, iv, _acpkm=None): + """Counter mode of operation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes data: plaintext/ciphertext + :param bytes iv: half blocksize-sized initialization vector + + For decryption you use the same function again. + """ + if len(iv) != bs // 2: + raise ValueError("Invalid IV size") + if len(data) > bs * (1 << (8 * (bs // 2 - 1))): + raise ValueError("Too big data") + stream = [] + ctr_value = 0 + ctr_max_value = 1 << (8 * (bs // 2)) + if _acpkm is not None: + acpkm_algo_class, acpkm_section_size_in_bs = _acpkm + acpkm_section_size_in_bs //= bs + for _ in xrange(0, len(data) + pad_size(len(data), bs), bs): + if ( + _acpkm is not None and + ctr_value != 0 and + ctr_value % acpkm_section_size_in_bs == 0 + ): + encrypter = acpkm_algo_class(acpkm(encrypter, bs)).encrypt + stream.append(encrypter(iv + long2bytes(ctr_value, bs // 2))) + ctr_value = (ctr_value + 1) % ctr_max_value + return strxor(b"".join(stream), data) + + +def ctr_acpkm(algo_class, encrypter, section_size, bs, data, iv): + """CTR-ACPKM mode of operation + + :param algo_class: pygost.gost3412's algorithm class + :param encrypter: encrypting function, that takes block as an input + :param int section_size: ACPKM'es section size (N), in bytes + :param int bs: cipher's blocksize, bytes + :param bytes data: plaintext/ciphertext + :param bytes iv: half blocksize-sized initialization vector + + For decryption you use the same function again. + """ + if section_size % bs != 0: + raise ValueError("section_size must be multiple of bs") + return ctr(encrypter, bs, data, iv, _acpkm=(algo_class, section_size)) + + +def ofb(encrypter, bs, data, iv): + """OFB mode of operation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes data: plaintext/ciphertext + :param bytes iv: blocksize-sized initialization vector + + For decryption you use the same function again. + """ + if len(iv) < bs or len(iv) % bs != 0: + raise ValueError("Invalid IV size") + r = [iv[i:i + bs] for i in range(0, len(iv), bs)] + result = [] + for i in xrange(0, len(data) + pad_size(len(data), bs), bs): + r = r[1:] + [encrypter(r[0])] + result.append(strxor(r[-1], data[i:i + bs])) + return b"".join(result) + + +def cbc_encrypt(encrypter, bs, pt, iv): + """CBC encryption mode of operation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes pt: already padded plaintext + :param bytes iv: blocksize-sized initialization vector + """ + if not pt or len(pt) % bs != 0: + raise ValueError("Plaintext is not blocksize aligned") + if len(iv) < bs or len(iv) % bs != 0: + raise ValueError("Invalid IV size") + r = [iv[i:i + bs] for i in range(0, len(iv), bs)] + ct = [] + for i in xrange(0, len(pt), bs): + ct.append(encrypter(strxor(r[0], pt[i:i + bs]))) + r = r[1:] + [ct[-1]] + return b"".join(ct) + + +def cbc_decrypt(decrypter, bs, ct, iv): + """CBC decryption mode of operation + + :param decrypter: Decrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes ct: ciphertext + :param bytes iv: blocksize-sized initialization vector + """ + if not ct or len(ct) % bs != 0: + raise ValueError("Ciphertext is not blocksize aligned") + if len(iv) < bs or len(iv) % bs != 0: + raise ValueError("Invalid IV size") + r = [iv[i:i + bs] for i in range(0, len(iv), bs)] + pt = [] + for i in xrange(0, len(ct), bs): + blk = ct[i:i + bs] + pt.append(strxor(r[0], decrypter(blk))) + r = r[1:] + [blk] + return b"".join(pt) + + +def cfb_encrypt(encrypter, bs, pt, iv): + """CFB encryption mode of operation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes pt: plaintext + :param bytes iv: blocksize-sized initialization vector + """ + if len(iv) < bs or len(iv) % bs != 0: + raise ValueError("Invalid IV size") + r = [iv[i:i + bs] for i in range(0, len(iv), bs)] + ct = [] + for i in xrange(0, len(pt) + pad_size(len(pt), bs), bs): + ct.append(strxor(encrypter(r[0]), pt[i:i + bs])) + r = r[1:] + [ct[-1]] + return b"".join(ct) + + +def cfb_decrypt(encrypter, bs, ct, iv): + """CFB decryption mode of operation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes ct: ciphertext + :param bytes iv: blocksize-sized initialization vector + """ + if len(iv) < bs or len(iv) % bs != 0: + raise ValueError("Invalid IV size") + r = [iv[i:i + bs] for i in range(0, len(iv), bs)] + pt = [] + for i in xrange(0, len(ct) + pad_size(len(ct), bs), bs): + blk = ct[i:i + bs] + pt.append(strxor(encrypter(r[0]), blk)) + r = r[1:] + [blk] + return b"".join(pt) + + +def _mac_shift(bs, data, xor_lsb=0): + num = (bytes2long(data) << 1) ^ xor_lsb + return long2bytes(num, bs)[-bs:] + + +Rb64 = 0b11011 +Rb128 = 0b10000111 + + +def _mac_ks(encrypter, bs): + Rb = Rb128 if bs == 16 else Rb64 + _l = encrypter(bs * b"\x00") + k1 = _mac_shift(bs, _l, Rb) if bytearray(_l)[0] & 0x80 > 0 else _mac_shift(bs, _l) + k2 = _mac_shift(bs, k1, Rb) if bytearray(k1)[0] & 0x80 > 0 else _mac_shift(bs, k1) + return k1, k2 + + +def mac(encrypter, bs, data): + """MAC (known here as CMAC, OMAC1) mode of operation + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize, bytes + :param bytes data: data to authenticate + + Implementation is based on PyCrypto's CMAC one, that is in public domain. + """ + k1, k2 = _mac_ks(encrypter, bs) + if len(data) % bs == 0: + tail_offset = len(data) - bs + else: + tail_offset = len(data) - (len(data) % bs) + prev = bs * b"\x00" + for i in xrange(0, tail_offset, bs): + prev = encrypter(strxor(data[i:i + bs], prev)) + tail = data[tail_offset:] + return encrypter(strxor( + strxor(pad3(tail, bs), prev), + k1 if len(tail) == bs else k2, + )) + + +def acpkm_master(algo_class, encrypter, key_section_size, bs, keymat_len): + """ACPKM-Master key derivation + + :param algo_class: pygost.gost3412's algorithm class + :param encrypter: encrypting function, that takes block as an input + :param int key_section_size: ACPKM'es key section size (T*), in bytes + :param int bs: cipher's blocksize, bytes + :param int keymat_len: length of key material to produce + """ + return ctr_acpkm( + algo_class, + encrypter, + key_section_size, + bs, + data=b"\x00" * keymat_len, + iv=b"\xFF" * (bs // 2), + ) + + +def mac_acpkm_master(algo_class, encrypter, key_section_size, section_size, bs, data): + """OMAC-ACPKM-Master + + :param algo_class: pygost.gost3412's algorithm class + :param encrypter: encrypting function, that takes block as an input + :param int key_section_size: ACPKM'es key section size (T*), in bytes + :param int section_size: ACPKM'es section size (N), in bytes + :param int bs: cipher's blocksize, bytes + :param bytes data: data to authenticate + """ + if len(data) % bs == 0: + tail_offset = len(data) - bs + else: + tail_offset = len(data) - (len(data) % bs) + prev = bs * b"\x00" + sections = len(data) // section_size + if len(data) % section_size != 0: + sections += 1 + keymats = acpkm_master( + algo_class, + encrypter, + key_section_size, + bs, + (KEYSIZE + bs) * sections, + ) + for i in xrange(0, tail_offset, bs): + if i % section_size == 0: + keymat, keymats = keymats[:KEYSIZE + bs], keymats[KEYSIZE + bs:] + key, k1 = keymat[:KEYSIZE], keymat[KEYSIZE:] + encrypter = algo_class(key).encrypt + prev = encrypter(strxor(data[i:i + bs], prev)) + tail = data[tail_offset:] + if len(tail) == bs: + key, k1 = keymats[:KEYSIZE], keymats[KEYSIZE:] + encrypter = algo_class(key).encrypt + k2 = long2bytes(bytes2long(k1) << 1, size=bs) + if bytearray(k1)[0] & 0x80 != 0: + k2 = strxor(k2, long2bytes(Rb128 if bs == 16 else Rb64, size=bs)) + return encrypter(strxor( + strxor(pad3(tail, bs), prev), + k1 if len(tail) == bs else k2, + )) + + +def pad_iso10126(data, blocksize): + """ISO 10126 padding + + Does not exist in 34.13, but added for convenience. + It uses urandom call for getting the randomness. + """ + pad_len = blocksize - len(data) % blocksize + if pad_len == 0: + pad_len = blocksize + return b"".join((data, urandom(pad_len - 1), bytes((pad_len,)))) + + +def unpad_iso10126(data, blocksize): + """Unpad :py:func:`pygost.gost3413.pad_iso10126` + """ + if len(data) % blocksize != 0: + raise ValueError("Data length is not multiple of blocksize") + pad_len = bytearray(data)[-1] + if pad_len > blocksize: + raise ValueError("Padding length is bigger than blocksize") + return data[:-pad_len] diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/iface.py b/xmlrpcserver/deps/pygost-5.12/pygost/iface.py new file mode 100644 index 0000000..e2d6a4c --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/iface.py @@ -0,0 +1,50 @@ +from abc import ABCMeta +from abc import abstractmethod + +from pygost.utils import hexenc + + +# This function is taken from six package as is +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get("__slots__") + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop("__dict__", None) + orig_vars.pop("__weakref__", None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +@add_metaclass(ABCMeta) +class PEP247(object): + @property + @abstractmethod + def digest_size(self): + """The size of the digest produced by the hashing objects. + """ + + @abstractmethod + def copy(self): + """Return a separate copy of this hashing object. + """ + + @abstractmethod + def update(self, data): + """Hash data into the current state of the hashing object. + """ + + @abstractmethod + def digest(self): + """Return the hash value as a string containing 8-bit data. + """ + + def hexdigest(self): + """Return the hash value as a string containing hexadecimal digits. + """ + return hexenc(self.digest()) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/kdf.py b/xmlrpcserver/deps/pygost-5.12/pygost/kdf.py new file mode 100644 index 0000000..4e404c6 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/kdf.py @@ -0,0 +1,81 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Key derivation functions, Р 50.1.113-2016, Р 1323565.1.020-2018 +""" + +import hmac + +from pygost.gost3410_vko import kek_34102012256 +from pygost.gost3410_vko import kek_34102012512 +from pygost.gost34112012256 import GOST34112012256 +from pygost.utils import bytes2long +from pygost.utils import long2bytes + + +def kdf_gostr3411_2012_256(key, label, seed): + """KDF_GOSTR3411_2012_256 + + :param bytes key: initial key + :param bytes label: label + :param bytes seed: seed + :returns: 32 bytes + """ + return hmac.new( + key=key, + msg=b"".join((b"\x01", label, b"\x00", seed, b"\x01\x00")), + digestmod=GOST34112012256, + ).digest() + + +def kdf_tree_gostr3411_2012_256(key, label, seed, keys, i_len=1): + """KDF_TREE_GOSTR3411_2012_256 + + :param bytes key: initial key + :param bytes label: label + :param bytes seed: seed + :param int keys: number of generated keys + :param int i_len: length of iterations value (called "R") + :returns: list of 256-bit keys + """ + keymat = [] + _len = long2bytes(keys * 32 * 8, size=1) + for i in range(keys): + keymat.append(hmac.new( + key=key, + msg=b"".join((long2bytes(i + 1, size=i_len), label, b"\x00", seed, _len)), + digestmod=GOST34112012256, + ).digest()) + return keymat + + +def keg(curve, prv, pub, h): + """Export key generation (Р 1323565.1.020-2018) + + :param GOST3410Curve curve: curve to use + :param long prv: private key + :param pub: public key + :type pub: (long, long) + :param bytes h: "h"-value, 32 bytes + """ + if len(h) != 32: + raise ValueError("h must be 32 bytes long") + ukm = bytes2long(h[:16]) + if ukm == 0: + ukm = 1 + if curve.point_size == 64: + return kek_34102012512(curve, prv, pub, ukm) + k_exp = kek_34102012256(curve, prv, pub, ukm) + return b"".join(kdf_tree_gostr3411_2012_256(k_exp, b"kdf tree", h[16:24], 2)) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/mgm.py b/xmlrpcserver/deps/pygost-5.12/pygost/mgm.py new file mode 100644 index 0000000..fb51343 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/mgm.py @@ -0,0 +1,168 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Multilinear Galois Mode (MGM) block cipher mode. +""" + +from hmac import compare_digest + +from pygost.gost3413 import pad1 +from pygost.utils import bytes2long +from pygost.utils import long2bytes +from pygost.utils import strxor + + +def _incr(data, bs): + return long2bytes(bytes2long(data) + 1, size=bs // 2) + + +def incr_r(data, bs): + return data[:bs // 2] + _incr(data[bs // 2:], bs) + + +def incr_l(data, bs): + return _incr(data[:bs // 2], bs) + data[bs // 2:] + + +def nonce_prepare(nonce): + """Prepare nonce for MGM usage + + It just clears MSB. + """ + n = bytearray(nonce) + n[0] &= 0x7F + return bytes(n) + + +class MGM(object): + # Implementation is fully based on go.cypherpunks.ru/gogost/mgm + def __init__(self, encrypter, bs, tag_size=None): + """Multilinear Galois Mode (MGM) block cipher mode + + :param encrypter: encrypting function, that takes block as an input + :param int bs: cipher's blocksize + :param int tag_size: authentication tag size + (defaults to blocksize if not specified) + """ + if bs not in (8, 16): + raise ValueError("Only 64/128-bit blocksizes allowed") + self.tag_size = bs if tag_size is None else tag_size + if self.tag_size < 4 or self.tag_size > bs: + raise ValueError("Invalid tag_size") + self.encrypter = encrypter + self.bs = bs + self.max_size = (1 << (bs * 8 // 2)) - 1 + self.r = 0x1B if bs == 8 else 0x87 + + def _validate_nonce(self, nonce): + if len(nonce) != self.bs: + raise ValueError("nonce length must be equal to cipher's blocksize") + if bytearray(nonce)[0] & 0x80 > 0: + raise ValueError("nonce must not have higher bit set") + + def _validate_sizes(self, plaintext, additional_data): + if len(plaintext) == 0 and len(additional_data) == 0: + raise ValueError("At least one of plaintext or additional_data required") + if len(plaintext) + len(additional_data) > self.max_size: + raise ValueError("plaintext+additional_data are too big") + + def _mul(self, x, y): + x = bytes2long(x) + y = bytes2long(y) + z = 0 + max_bit = 1 << (self.bs * 8 - 1) + while y > 0: + if y & 1 == 1: + z ^= x + if x & max_bit > 0: + x = ((x ^ max_bit) << 1) ^ self.r + else: + x <<= 1 + y >>= 1 + return long2bytes(z, size=self.bs) + + def _crypt(self, icn, data): + icn[0] &= 0x7F + enc = self.encrypter(bytes(icn)) + res = [] + while len(data) > 0: + res.append(strxor(self.encrypter(enc), data)) + enc = incr_r(enc, self.bs) + data = data[self.bs:] + return b"".join(res) + + def _auth(self, icn, text, ad): + icn[0] |= 0x80 + enc = self.encrypter(bytes(icn)) + _sum = self.bs * b"\x00" + ad_len = len(ad) + text_len = len(text) + while len(ad) > 0: + _sum = strxor(_sum, self._mul( + self.encrypter(enc), + pad1(ad[:self.bs], self.bs), + )) + enc = incr_l(enc, self.bs) + ad = ad[self.bs:] + while len(text) > 0: + _sum = strxor(_sum, self._mul( + self.encrypter(enc), + pad1(text[:self.bs], self.bs), + )) + enc = incr_l(enc, self.bs) + text = text[self.bs:] + _sum = strxor(_sum, self._mul(self.encrypter(enc), ( + long2bytes(ad_len * 8, size=self.bs // 2) + + long2bytes(text_len * 8, size=self.bs // 2) + ))) + return self.encrypter(_sum)[:self.tag_size] + + def seal(self, nonce, plaintext, additional_data): + """Seal plaintext + + :param bytes nonce: blocksize-sized nonce. + Assure that it does not have MSB bit set + (:py:func:`pygost.mgm.nonce_prepare` helps) + :param bytes plaintext: plaintext to be encrypted and authenticated + :param bytes additional_data: additional data to be authenticated + """ + self._validate_nonce(nonce) + self._validate_sizes(plaintext, additional_data) + icn = bytearray(nonce) + ciphertext = self._crypt(icn, plaintext) + tag = self._auth(icn, ciphertext, additional_data) + return ciphertext + tag + + def open(self, nonce, ciphertext, additional_data): + """Open ciphertext + + :param bytes nonce: blocksize-sized nonce. + Assure that it does not have MSB bit set + (:py:func:`pygost.mgm.nonce_prepare` helps) + :param bytes ciphertext: ciphertext to be decrypted and authenticated + :param bytes additional_data: additional data to be authenticated + :raises ValueError: if ciphertext authentication fails + """ + self._validate_nonce(nonce) + self._validate_sizes(ciphertext, additional_data) + icn = bytearray(nonce) + ciphertext, tag_expected = ( + ciphertext[:-self.tag_size], + ciphertext[-self.tag_size:], + ) + tag = self._auth(icn, ciphertext, additional_data) + if not compare_digest(tag_expected, tag): + raise ValueError("Invalid authentication tag") + return self._crypt(icn, ciphertext) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/pbkdf2.py b/xmlrpcserver/deps/pygost-5.12/pygost/pbkdf2.py new file mode 100644 index 0000000..0fd6ddc --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/pbkdf2.py @@ -0,0 +1,41 @@ +# coding: utf-8 +"""PBKDF2 implementation suitable for GOST R 34.11-94/34.11-2012. + +This implementation is based on Python 3.5.2 source code's one. +PyGOST does not register itself in hashlib anyway, so use it instead. +""" + + +from pygost.utils import bytes2long +from pygost.utils import long2bytes +from pygost.utils import strxor +from pygost.utils import xrange + + +def pbkdf2(hasher, password, salt, iterations, dklen): + """PBKDF2 implementation suitable for GOST R 34.11-94/34.11-2012 + """ + inner = hasher() + outer = hasher() + password = password + b"\x00" * (inner.block_size - len(password)) + inner.update(strxor(password, len(password) * b"\x36")) + outer.update(strxor(password, len(password) * b"\x5C")) + + def prf(msg): + icpy = inner.copy() + ocpy = outer.copy() + icpy.update(msg) + ocpy.update(icpy.digest()) + return ocpy.digest() + + dkey = b"" + loop = 1 + while len(dkey) < dklen: + prev = prf(salt + long2bytes(loop, 4)) + rkey = bytes2long(prev) + for _ in xrange(iterations - 1): + prev = prf(prev) + rkey ^= bytes2long(prev) + loop += 1 + dkey += long2bytes(rkey, inner.digest_size) + return dkey[:dklen] diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/__init__.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/__init__.pyi new file mode 100644 index 0000000..e69de29 diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost28147.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost28147.pyi new file mode 100644 index 0000000..be31261 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost28147.pyi @@ -0,0 +1,101 @@ +from typing import Callable +from typing import Dict +from typing import Sequence +from typing import Tuple + + +SBOXES = ... # type: Dict[str, Tuple[Tuple[int, ...], ...]] +BLOCKSIZE = ... # type: int + +Words = Tuple[int, int] + + +def block2ns(data: bytes) -> Words: ... + + +def ns2block(ns: Words) -> bytes: ... + + +def validate_key(key: bytes) -> None: ... + + +def validate_iv(iv: bytes) -> None: ... + + +def validate_sbox(sbox: str) -> None: ... + + +def xcrypt(seq: Sequence[int], sbox: str, key: bytes, ns: Words) -> Words: ... + + +def encrypt(sbox: str, key: bytes, ns: Words) -> Words: ... + + +def decrypt(sbox: str, key: bytes, ns: Words) -> Words: ... + + +def ecb( + key: bytes, + data: bytes, + action: Callable[[str, bytes, Words], Words], + sbox: str = ..., +) -> bytes: ... + + +def ecb_encrypt( + key: bytes, + data: bytes, + sbox: str = ..., +) -> bytes: ... + + +def ecb_decrypt( + key: bytes, + data: bytes, + sbox: str = ..., +) -> bytes: ... + + +def cbc_encrypt( + key: bytes, + data: bytes, + iv: bytes = ..., + pad: bool = ..., + sbox: str = ..., + mesh: bool = ..., +) -> bytes: ... + + +def cbc_decrypt( + key: bytes, + data: bytes, + pad: bool = ..., + sbox: str = ..., + mesh: bool = ..., +) -> bytes: ... + + +def cnt( + key: bytes, + data: bytes, + iv: bytes = ..., + sbox: str = ..., +) -> bytes: ... + + +def cfb_encrypt( + key: bytes, + data: bytes, + iv: bytes = ..., + sbox: str = ..., + mesh: bool = ..., +) -> bytes: ... + + +def cfb_decrypt( + key: bytes, + data: bytes, + iv: bytes = ..., + sbox: str = ..., + mesh: bool = ..., +) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost28147_mac.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost28147_mac.pyi new file mode 100644 index 0000000..70d90d6 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost28147_mac.pyi @@ -0,0 +1,25 @@ +from pygost.iface import PEP247 + + +class MAC(PEP247): + def __init__( + self, + key: bytes, + data: bytes = ..., + iv: bytes = ..., + sbox: str = ..., + ) -> None: ... + + @property + def digest_size(self) -> int: ... + + def copy(self) -> "MAC": ... + + def update(self, data: bytes) -> None: ... + + def digest(self) -> bytes: ... + + def hexdigest(self) -> str: ... + + +def new(key: bytes, data: bytes = ..., iv: bytes = ..., sbox: str = ...) -> MAC: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3410.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3410.pyi new file mode 100644 index 0000000..8f0dcb8 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3410.pyi @@ -0,0 +1,72 @@ +from typing import Dict +from typing import Tuple + + +DEFAULT_CURVE = ... # type: GOST3410Curve +CURVES = ... # type: Dict[str, GOST3410Curve] +PublicKey = Tuple[int, int] + + +class GOST3410Curve(object): + p = ... # type: int + q = ... # type: int + a = ... # type: int + b = ... # type: int + x = ... # type: int + y = ... # type: int + cofactor = ... # type: int + e = ... # type: int + d = ... # type: int + name = ... # type: str + + def __init__( + self, + p: int, + q: int, + a: int, + b: int, + x: int, + y: int, + cofactor: int = 1, + e: int = None, + d: int = None, + name: str = None, + ) -> None: ... + + def pos(self, v: int) -> int: ... + + def exp(self, degree: int, x: int = ..., y: int = ...) -> int: ... + + def st(self) -> Tuple[int, int]: ... + + @property + def point_size(self) -> int: ... + + def contains(self, point: Tuple[int, int]) -> bool: ... + + +def public_key(curve: GOST3410Curve, prv: int) -> PublicKey: ... + + +def sign(curve: GOST3410Curve, prv: int, digest: bytes, rand: bytes = None) -> bytes: ... + + +def verify(curve: GOST3410Curve, pub: PublicKey, digest: bytes, signature: bytes) -> bool: ... + + +def prv_unmarshal(prv: bytes) -> int: ... + + +def prv_marshal(curve: GOST3410Curve, prv: int) -> bytes: ... + + +def pub_marshal(pub: PublicKey) -> bytes: ... + + +def pub_unmarshal(pub: bytes) -> PublicKey: ... + + +def uv2xy(curve: GOST3410Curve, u: int, v: int) -> Tuple[int, int]: ... + + +def xy2uv(curve: GOST3410Curve, x: int, y: int) -> Tuple[int, int]: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3410_vko.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3410_vko.pyi new file mode 100644 index 0000000..6ea9b82 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3410_vko.pyi @@ -0,0 +1,17 @@ +from pygost.gost3410 import GOST3410Curve +from pygost.gost3410 import PublicKey + + +def ukm_unmarshal(ukm: bytes) -> int: ... + + +def kek(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int) -> bytes: ... + + +def kek_34102001(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int) -> bytes: ... + + +def kek_34102012256(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int = ...) -> bytes: ... + + +def kek_34102012512(curve: GOST3410Curve, prv: int, pub: PublicKey, ukm: int = ...) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012.pyi new file mode 100644 index 0000000..3d5cc41 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012.pyi @@ -0,0 +1,18 @@ +from pygost.iface import PEP247 + + +class GOST34112012(PEP247): + block_size = ... # type: int + + def __init__(self, data: bytes = ..., digest_size: int = ...) -> None: ... + + @property + def digest_size(self) -> int: ... + + def copy(self) -> "GOST34112012": ... + + def update(self, data: bytes) -> None: ... + + def digest(self) -> bytes: ... + + def hexdigest(self) -> str: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012256.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012256.pyi new file mode 100644 index 0000000..a1d2a01 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012256.pyi @@ -0,0 +1,21 @@ +from pygost.iface import PEP247 + + +class GOST34112012256(PEP247): + block_size = ... # type: int + + def __init__(self, data: bytes = ...) -> None: ... + + @property + def digest_size(self) -> int: ... + + def copy(self) -> "GOST34112012256": ... + + def update(self, data: bytes) -> None: ... + + def digest(self) -> bytes: ... + + def hexdigest(self) -> str: ... + + +def new(data: bytes = ...) -> GOST34112012256: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012512.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012512.pyi new file mode 100644 index 0000000..349bddd --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost34112012512.pyi @@ -0,0 +1,24 @@ +from pygost.iface import PEP247 + + +class GOST34112012512(PEP247): + block_size = ... # type: int + + def __init__(self, data: bytes = ...) -> None: ... + + @property + def digest_size(self) -> int: ... + + def copy(self) -> "GOST34112012512": ... + + def update(self, data: bytes) -> None: ... + + def digest(self) -> bytes: ... + + def hexdigest(self) -> str: ... + + +def new(data: bytes = ...) -> GOST34112012512: ... + + +def pbkdf2(password: bytes, salt: bytes, iterations: int, dklen: int) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost341194.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost341194.pyi new file mode 100644 index 0000000..24de2e4 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost341194.pyi @@ -0,0 +1,25 @@ +from pygost.iface import PEP247 + + +class GOST341194(PEP247): + sbox = ... # type: str + block_size = ... # type: int + + def __init__(self, data: bytes = ..., sbox: str = ...) -> None: ... + + @property + def digest_size(self) -> int: ... + + def copy(self) -> "GOST341194": ... + + def update(self, data: bytes) -> None: ... + + def digest(self) -> bytes: ... + + def hexdigest(self) -> str: ... + + +def new(data: bytes = ..., sbox: str = ...) -> GOST341194: ... + + +def pbkdf2(password: bytes, salt: bytes, iterations: int, dklen: int) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3412.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3412.pyi new file mode 100644 index 0000000..ef278b7 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3412.pyi @@ -0,0 +1,18 @@ +class GOST3412Kuznechik(object): + blocksize = ... # type: int + + def __init__(self, key: bytes) -> None: ... + + def encrypt(self, blk: bytes) -> bytes: ... + + def decrypt(self, blk: bytes) -> bytes: ... + + +class GOST3412Magma(object): + blocksize = ... # type: int + + def __init__(self, key: bytes) -> None: ... + + def encrypt(self, blk: bytes) -> bytes: ... + + def decrypt(self, blk: bytes) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3413.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3413.pyi new file mode 100644 index 0000000..4cfd694 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/gost3413.pyi @@ -0,0 +1,81 @@ +from typing import Callable + + +def pad_size(data_size: int, blocksize: int) -> int: ... + + +def pad1(data: bytes, blocksize: int) -> bytes: ... + + +def pad2(data: bytes, blocksize: int) -> bytes: ... + + +def unpad2(data: bytes, blocksize: int) -> bytes: ... + + +def pad3(data: bytes, blocksize: int) -> bytes: ... + + +def ecb_encrypt(encrypter: Callable[[bytes], bytes], bs: int, pt: bytes) -> bytes: ... + + +def ecb_decrypt(decrypter: Callable[[bytes], bytes], bs: int, ct: bytes) -> bytes: ... + + +def acpkm(encrypter: Callable[[bytes], bytes], bs: int) -> bytes: ... + + +def ctr(encrypter: Callable[[bytes], bytes], bs: int, data: bytes, iv: bytes) -> bytes: ... + + +def ctr_acpkm( + algo_class: object, + encrypter: Callable[[bytes], bytes], + section_size: int, + bs: int, + data: bytes, + iv: bytes, +) -> bytes: ... + + +def ofb(encrypter: Callable[[bytes], bytes], bs: int, data: bytes, iv: bytes) -> bytes: ... + + +def cbc_encrypt(encrypter: Callable[[bytes], bytes], bs: int, pt: bytes, iv: bytes) -> bytes: ... + + +def cbc_decrypt(decrypter: Callable[[bytes], bytes], bs: int, ct: bytes, iv: bytes) -> bytes: ... + + +def cfb_encrypt(encrypter: Callable[[bytes], bytes], bs: int, pt: bytes, iv: bytes) -> bytes: ... + + +def cfb_decrypt(encrypter: Callable[[bytes], bytes], bs: int, ct: bytes, iv: bytes) -> bytes: ... + + +def mac(encrypter: Callable[[bytes], bytes], bs: int, data: bytes) -> bytes: ... + + +def acpkm_master( + algo_class: object, + encrypter: Callable[[bytes], bytes], + key_section_size: int, + bs: int, + keymat_len: int, +) -> bytes: ... + + +def mac_acpkm_master( + algo_class: object, + encrypter: Callable[[bytes], bytes], + key_section_size: int, + section_size: int, + bs: int, + data: bytes, +) -> bytes: ... + + +def pad_iso10126(data: bytes, blocksize: int) -> bytes: ... + + +def unpad_iso10126(data: bytes, blocksize: int) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/iface.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/iface.pyi new file mode 100644 index 0000000..a5c2a85 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/iface.pyi @@ -0,0 +1,19 @@ +from abc import ABCMeta +from abc import abstractmethod + + +class PEP247(metaclass=ABCMeta): + @abstractmethod + @property + def digest_size(self) -> int: ... + + @abstractmethod + def copy(self) -> "PEP247": ... + + @abstractmethod + def update(self, data: bytes) -> None: ... + + @abstractmethod + def digest(self) -> bytes: ... + + def hexdigest(self) -> str: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/kdf.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/kdf.pyi new file mode 100644 index 0000000..ccab8af --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/kdf.pyi @@ -0,0 +1,22 @@ +from typing import Sequence +from typing import Tuple + +from pygost.gost3410 import GOST3410Curve + + +PublicKey = Tuple[int, int] + + +def kdf_gostr3411_2012_256(key: bytes, label: bytes, seed: bytes) -> bytes: ... + + +def kdf_tree_gostr3411_2012_256( + key: bytes, + label: bytes, + seed: bytes, + keys: int, + i_len: int = 1, +) -> Sequence[bytes]: ... + + +def keg(curve: GOST3410Curve, prv: int, pub: PublicKey, h: bytes) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/mgm.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/mgm.pyi new file mode 100644 index 0000000..81906b7 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/mgm.pyi @@ -0,0 +1,17 @@ +from typing import Callable + + +def nonce_prepare(nonce: bytes) -> bytes: ... + + +class MGM(object): + def __init__( + self, + encrypter: Callable[[bytes], bytes], + bs: int, + tag_size: int = None, + ) -> None: ... + + def seal(self, nonce: bytes, plaintext: bytes, additional_data: bytes) -> bytes: ... + + def open(self, nonce: bytes, ciphertext: bytes, additional_data: bytes) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/utils.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/utils.pyi new file mode 100644 index 0000000..76460e5 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/utils.pyi @@ -0,0 +1,19 @@ +from typing import AnyStr + + +def strxor(a: bytes, b: bytes) -> bytes: ... + + +def hexdec(data: AnyStr) -> bytes: ... + + +def hexenc(data: bytes) -> str: ... + + +def bytes2long(raw: bytes) -> int: ... + + +def long2bytes(n: int, size: int = ...) -> bytes: ... + + +def modinvert(a: int, n: int) -> int: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/wrap.pyi b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/wrap.pyi new file mode 100644 index 0000000..776a6e7 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/stubs/pygost/wrap.pyi @@ -0,0 +1,31 @@ +from typing import Callable + + +def wrap_gost(ukm: bytes, kek: bytes, cek: bytes, sbox: str = ...) -> bytes: ... + + +def unwrap_gost(kek: bytes, data: bytes, sbox: str = ...) -> bytes: ... + + +def wrap_cryptopro(ukm: bytes, kek: bytes, cek: bytes, sbox: str = ...) -> bytes: ... + + +def unwrap_cryptopro(kek: bytes, data: bytes, sbox: str = ...) -> bytes: ... + + +def kexp15( + encrypter_key: Callable[[bytes], bytes], + encrypter_mac: Callable[[bytes], bytes], + bs: int, + key: bytes, + iv: bytes, +) -> bytes: ... + + +def kimp15( + encrypter_key: Callable[[bytes], bytes], + encrypter_mac: Callable[[bytes], bytes], + bs: int, + kexp: bytes, + iv: bytes, +) -> bytes: ... diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_cms.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_cms.py new file mode 100644 index 0000000..7e5781a --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_cms.py @@ -0,0 +1,1078 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base64 import b64decode +from unittest import skipIf +from unittest import TestCase + +from six import text_type + +from pygost.gost28147 import cfb_decrypt +from pygost.gost3410 import CURVES +from pygost.gost3410 import prv_unmarshal +from pygost.gost3410 import pub_marshal +from pygost.gost3410 import pub_unmarshal +from pygost.gost3410 import public_key +from pygost.gost3410 import verify +from pygost.gost3410_vko import kek_34102012256 +from pygost.gost3410_vko import ukm_unmarshal +from pygost.gost34112012256 import GOST34112012256 +from pygost.gost34112012512 import GOST34112012512 +from pygost.gost3412 import GOST3412Kuznechik +from pygost.gost3412 import GOST3412Magma +from pygost.gost3413 import ctr_acpkm +from pygost.gost3413 import KEYSIZE +from pygost.gost3413 import mac as omac +from pygost.kdf import kdf_tree_gostr3411_2012_256 +from pygost.kdf import keg +from pygost.utils import hexdec +from pygost.wrap import kimp15 +from pygost.wrap import unwrap_cryptopro +from pygost.wrap import unwrap_gost + +try: + from pyderasn import DecodePathDefBy + from pyderasn import OctetString + + from pygost.asn1schemas.cms import ContentInfo + from pygost.asn1schemas.cms import SignedAttributes + from pygost.asn1schemas.oids import id_cms_mac_attr + from pygost.asn1schemas.oids import id_envelopedData + from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm + from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm_omac + from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_wrap_kexp15 + from pygost.asn1schemas.oids import id_gostr3412_2015_magma_ctracpkm + from pygost.asn1schemas.oids import id_gostr3412_2015_magma_ctracpkm_omac + from pygost.asn1schemas.oids import id_gostr3412_2015_magma_wrap_kexp15 + from pygost.asn1schemas.oids import id_messageDigest + from pygost.asn1schemas.oids import id_tc26_agreement_gost3410_2012_256 + from pygost.asn1schemas.oids import id_tc26_agreement_gost3410_2012_512 + from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256 + from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512 + from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetA + from pygost.asn1schemas.oids import id_tc26_gost3411_2012_256 + from pygost.asn1schemas.oids import id_tc26_gost3411_2012_512 + from pygost.asn1schemas.x509 import Certificate + from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters +except ImportError: + pyderasn_exists = False +else: + pyderasn_exists = True + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestSigned(TestCase): + """SignedData test vectors from "Использование + алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10 в + криптографических сообщениях формата CMS" (TK26CMS.pdf) + """ + + def process_cms( + self, + content_info_raw, + prv_key_raw, + curve_name, + hasher, + ): + content_info, tail = ContentInfo().decode(content_info_raw) + self.assertSequenceEqual(tail, b"") + self.assertIsNotNone(content_info["content"].defined) + _, signed_data = content_info["content"].defined + self.assertEqual(len(signed_data["signerInfos"]), 1) + curve = CURVES[curve_name] + self.assertTrue(verify( + curve, + public_key(curve, prv_unmarshal(prv_key_raw)), + hasher(bytes(signed_data["encapContentInfo"]["eContent"])).digest()[::-1], + bytes(signed_data["signerInfos"][0]["signature"]), + )) + + def test_256(self): + content_info_raw = b64decode(""" +MIIBBQYJKoZIhvcNAQcCoIH3MIH0AgEBMQ4wDAYIKoUDBwEBAgIFADAbBgkqhkiG +9w0BBwGgDgQMVGVzdCBtZXNzYWdlMYHBMIG+AgEBMFswVjEpMCcGCSqGSIb3DQEJ +ARYaR29zdFIzNDEwLTIwMTJAZXhhbXBsZS5jb20xKTAnBgNVBAMTIEdvc3RSMzQx +MC0yMDEyICgyNTYgYml0KSBleGFtcGxlAgEBMAwGCCqFAwcBAQICBQAwDAYIKoUD +BwEBAQEFAARAkptb2ekZbC94FaGDQeP70ExvTkXtOY9zgz3cCco/hxPhXUVo3eCx +VNwDQ8enFItJZ8DEX4blZ8QtziNCMl5HbA== + """) + prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1] + self.process_cms( + content_info_raw, + prv_key_raw, + "id-GostR3410-2001-CryptoPro-XchA-ParamSet", + GOST34112012256, + ) + + def test_512(self): + content_info_raw = b64decode(""" +MIIBSQYJKoZIhvcNAQcCoIIBOjCCATYCAQExDjAMBggqhQMHAQECAwUAMBsGCSqG +SIb3DQEHAaAOBAxUZXN0IG1lc3NhZ2UxggECMIH/AgEBMFswVjEpMCcGCSqGSIb3 +DQEJARYaR29zdFIzNDEwLTIwMTJAZXhhbXBsZS5jb20xKTAnBgNVBAMTIEdvc3RS +MzQxMC0yMDEyICg1MTIgYml0KSBleGFtcGxlAgEBMAwGCCqFAwcBAQIDBQAwDAYI +KoUDBwEBAQIFAASBgFyVohNhMHUi/+RAF3Gh/cC7why6v+4jPWVlx1TYlXtV8Hje +hI2Y+rP52/LO6EUHG/XcwCBbUxmRWsbUSRRBAexmaafkSdvv2FFwC8kHOcti+UPX +PS+KRYxT8vhcsBLWWxDkc1McI7aF09hqtED36mQOfACzeJjEoUjALpmJob1V + """) + prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1] + self.process_cms( + content_info_raw, + prv_key_raw, + "id-tc26-gost-3410-12-512-paramSetB", + GOST34112012512, + ) + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestDigested(TestCase): + """DigestedData test vectors from "Использование + алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10 в + криптографических сообщениях формата CMS" (TK26CMS.pdf) + """ + + def process_cms(self, content_info_raw, hasher): + content_info, tail = ContentInfo().decode(content_info_raw) + self.assertSequenceEqual(tail, b"") + self.assertIsNotNone(content_info["content"].defined) + _, digested_data = content_info["content"].defined + self.assertSequenceEqual( + hasher(bytes(digested_data["encapContentInfo"]["eContent"])).digest(), + bytes(digested_data["digest"]), + ) + + def test_256(self): + content_info_raw = b64decode(""" +MIGdBgkqhkiG9w0BBwWggY8wgYwCAQAwDAYIKoUDBwEBAgIFADBXBgkqhkiG9w0B +BwGgSgRI0eUg4uXy8OgsINHy8Ojh7uboIOLt8/boLCDi5f7y+iDxIOzu8P8g8fLw +5evg7Ogg7eAg9fDg4fD7/yDv6/rq+yDI4+7w5eL7BCCd0v5OkECeXah/U5dtdAWw +wMrGKPxmmnQdUAY8VX6PUA== + """) + self.process_cms(content_info_raw, GOST34112012256) + + def test_512(self): + content_info_raw = b64decode(""" +MIG0BgkqhkiG9w0BBwWggaYwgaMCAQAwDAYIKoUDBwEBAgMFADBOBgkqhkiG9w0B +BwGgQQQ/MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAx +MjM0NTY3ODkwMTIzNDU2Nzg5MDEyBEAbVNAaSvW51cw9htaNKFRisZq8JHUiLzXA +hRIr5Lof+gCtMPh2ezqCOExldPAkwxHipIEzKwjvf0F5eJHBZG9I + """) + self.process_cms(content_info_raw, GOST34112012512) + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestEnvelopedKTRI(TestCase): + """EnvelopedData KeyTransRecipientInfo-based test vectors from + "Использование алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10 + в криптографических сообщениях формата CMS" (TK26CMS.pdf) + """ + + def process_cms( + self, + content_info_raw, + prv_key_our, + curve_name, + keker, + plaintext_expected, + ): + sbox = "id-tc26-gost-28147-param-Z" + content_info, tail = ContentInfo().decode(content_info_raw, ctx={ + "defines_by_path": [ + ( + ( + "content", + DecodePathDefBy(id_envelopedData), + "recipientInfos", + any, + "ktri", + "encryptedKey", + DecodePathDefBy(spki_algorithm), + "transportParameters", + "ephemeralPublicKey", + "algorithm", + "algorithm", + ), + ( + ( + ("..", "subjectPublicKey"), + { + id_tc26_gost3410_2012_256: OctetString(), + id_tc26_gost3410_2012_512: OctetString(), + }, + ), + ), + ) for spki_algorithm in ( + id_tc26_gost3410_2012_256, + id_tc26_gost3410_2012_512, + ) + ], + }) + self.assertSequenceEqual(tail, b"") + self.assertIsNotNone(content_info["content"].defined) + _, enveloped_data = content_info["content"].defined + eci = enveloped_data["encryptedContentInfo"] + ri = enveloped_data["recipientInfos"][0] + self.assertIsNotNone(ri["ktri"]["encryptedKey"].defined) + _, encrypted_key = ri["ktri"]["encryptedKey"].defined + ukm = bytes(encrypted_key["transportParameters"]["ukm"]) + spk = encrypted_key["transportParameters"]["ephemeralPublicKey"]["subjectPublicKey"] + self.assertIsNotNone(spk.defined) + _, pub_key_their = spk.defined + curve = CURVES[curve_name] + kek = keker(curve, prv_key_our, bytes(pub_key_their), ukm) + key_wrapped = bytes(encrypted_key["sessionEncryptedKey"]["encryptedKey"]) + mac = bytes(encrypted_key["sessionEncryptedKey"]["macKey"]) + cek = unwrap_cryptopro(kek, ukm + key_wrapped + mac, sbox=sbox) + ciphertext = bytes(eci["encryptedContent"]) + self.assertIsNotNone(eci["contentEncryptionAlgorithm"]["parameters"].defined) + _, encryption_params = eci["contentEncryptionAlgorithm"]["parameters"].defined + iv = bytes(encryption_params["iv"]) + self.assertSequenceEqual( + cfb_decrypt(cek, ciphertext, iv, sbox=sbox, mesh=True), + plaintext_expected, + ) + + def test_256(self): + content_info_raw = b64decode(""" +MIIKGgYJKoZIhvcNAQcDoIIKCzCCCgcCAQAxggE0MIIBMAIBADBbMFYxKTAnBgkq +hkiG9w0BCQEWGkdvc3RSMzQxMC0yMDEyQGV4YW1wbGUuY29tMSkwJwYDVQQDEyBH +b3N0UjM0MTAtMjAxMiAyNTYgYml0cyBleGNoYW5nZQIBATAfBggqhQMHAQEBATAT +BgcqhQMCAiQABggqhQMHAQECAgSBrDCBqTAoBCCVJxUMdbKRzCJ5K1NWJIXnN7Ul +zaceeFlblA2qH4wZrgQEsHnIG6B9BgkqhQMHAQIFAQGgZjAfBggqhQMHAQEBATAT +BgcqhQMCAiQABggqhQMHAQECAgNDAARAFoqoLg1lV780co6GdwtjLtS4KCXv9VGR +sd7PTPHCT/5iGbvOlKNW2I8UhayJ0dv7RV7Nb1lDIxPxf4Mbp2CikgQI1b4+WpGE +sfQwggjIBgkqhkiG9w0BBwEwHwYGKoUDAgIVMBUECHYNkdvFoYdyBgkqhQMHAQIF +AQGAggiYvFFpJKILAFdXjcdLLYv4eruXzL/wOXL8y9HHIDMbSzV1GM033J5Yt/p4 +H6JYe1L1hjAfE/BAAYBndof2sSUxC3/I7xj+b7M8BZ3GYPqATPtR4aCQDK6z91lx +nDBAWx0HdsStT5TOj/plMs4zJDadvIJLfjmGkt0Np8FSnSdDPOcJAO/jcwiOPopg ++Z8eIuZNmY4seegTLue+7DGqvqi1GdZdMnvXBFIKc9m5DUsC7LdyboqKImh6giZE +YZnxb8a2naersPylhrf+zp4Piwwv808yOrD6LliXUiH0RojlmuaQP4wBkb7m073h +MeAWEWSvyXzOvOOuFST/hxPEupiTRoHPUdfboJT3tNpizUhE384SrvXHpwpgivQ4 +J0zF2/uzTBEupXR6dFC9rTHAK3X79SltqBNnHyIXBwe+BMqTmKTfnlPVHBUfTXZg +oakDItwKwa1MBOZeciwtUFza+7o9FZhKIandb848chGdgd5O9ksaXvPJDIPxQjZd +EBVhnXLlje4TScImwTdvYB8GsI8ljKb2bL3FjwQWGbPaOjXc2D9w+Ore8bk1E4TA +ayhypU7MH3Mq1EBZ4j0iROEFBQmYRZn8vAKZ0K7aPxcDeAnKAJxdokqrMkLgI6WX +0glh/3Cs9dI+0D2GqMSygauKCD0vTIo3atkEQswDZR4pMx88gB4gmx7iIGrc/ZXs +ZqHI7NQqeKtBwv2MCIj+/UTqdYDqbaniDwdVS8PE9nQnNU4gKffq3JbT+wRjJv6M +Dr231bQHgAsFTVKbZgoL4gj4V7bLQUmW06+W1BQUJ2+Sn7fp+Xet9Xd3cGtNdxzQ +zl6sGuiOlTNe0bfKP7QIMC7ekjflLBx8nwa2GZG19k3O0Z9JcDdN/kz6bGpPNssY +AIOkTvLQjxIM9MhRqIv6ee0rowTWQPwXJP7yHApop4XZvVX6h9gG2gazqbDej2lo +tAcfRAKj/LJ/bk9+OlNXOXVCKnwE1kXxZDsNJ51GdCungC56U/hmd3C1RhSLTpEc +FlOWgXKNjbn6SQrlq1yASKKr80T0fL7PFoYwKZoQbKMAVZQC1VBWQltHkEzdL73x +FwgZULNfdflF8sEhFC/zsVqckD/UnhzJz88PtCslMArJ7ntbEF1GzsSSfRfjBqnl +kSUreE5XX6+c9yp5HcJBiMzp6ZqqWWaED5Y5xp1hZeYjuKbDMfY4tbWVc7Hy0dD2 +KGfZLp5umqvPNs7aVBPmvuxtrnxcJlUB8u2HoiHc6/TuhrpaopYGBhxL9+kezuLR +v18nsAg8HOmcCNUS46NXQj/Mdpx8W+RsyzCQkJjieT/Yed20Zxq1zJoXIS0xAaUH +TdE2dWqiT6TGlh/KQYk3KyFPNnDmzJm04a2VWIwpp4ypXyxrB7XxnVY6Q4YBYbZs +FycxGjJWqj7lwc+lgZ8YV2WJ4snEo2os8SsA2GFWcUMiVTHDnEJvphDHmhWsf26A +bbRqwaRXNjhj05DamTRsczgvfjdl1pk4lJYE4ES3nixtMe4s1X8nSmM4KvfyVDul +J8uTpw1ZFnolTdfEL63BSf4FREoEqKB7cKuD7cpn7Rg4kRdM0/BLZGuxkH+pGMsI +Bb8LecUWyjGsI6h74Wz/U2uBrfgdRqhR+UsfB2QLaRgM6kCXZ4vM0auuzBViFCwK +tYMHzZWWz8gyVtJ0mzt1DrHCMx4pTS4yOhv4RkXBS/rub4VhVIsOGOGar5ZYtH47 +uBbdw3NC05JIFM7lI31d0s1fvvkTUR7eaqRW+SnR2c2oHpWlSO+Q0mrzx+vvOTdj +xa713YtklBvyUUQr2SIbsXGpFnwjn+sXK1onAavp/tEax8sNZvxg5yeseFcWn+gD +4rjk9FiSd1wp4fTDQFJ19evqruqKlq6k18l/ZAyUcEbIWSz2s3HfAAoAQyFPX1Q2 +95gVhRRw6lP4S6VPCfn/f+5jV4TcT6W/giRaHIk9Hty+g8bx1bFXaKVkQZ5R2Vmk +qsZ65ZgCrYQJmcErPmYybvP7NBeDS4AOSgBQAGMQF4xywdNm6bniWWo3N/xkFv32 +/25x8okGgD8QcYKmhzieLSSzOvM/exB14RO84YZOkZzm01Jll0nac/LEazKoVWbn +0VdcQ7pYEOqeMBXipsicNVYA/uhonp6op9cpIVYafPr0npCGwwhwcRuOrgSaZyCn +VG2tPkEOv9LKmUbhnaDA2YUSzOOjcCpIVvTSBnUEiorYpfRYgQLrbcd2qhVvNCLX +8ujZfMqXQXK8n5BK8JxNtczvaf+/2dfv1dQl0lHEAQhbNcsJ0t5GPhsSCC5oMBJl +ZJuOEO/8PBWKEnMZOM+Dz7gEgsBhGyMFFrKpiwQRpyEshSD2QpnK6Lp0t5C8Za2G +lhyZsEr+93AYOb5mm5+z02B4Yq9+RpepvjoqVeq/2uywZNq9MS98zVgNsmpryvTZ +3HJHHB20u2jcVu0G3Nhiv22lD70JWCYFAOupjgVcUcaBxjxwUMAvgHg7JZqs6mC6 +tvTKwQ4NtDhoAhARlDeWSwCWb2vPH2H7Lmqokif1RfvJ0hrLzkJuHdWrzIYzXpPs ++v9XJxLvbdKi9KU1Halq9S8dXT1fvs9DJTpUV/KW7QkRsTQJhTJBkQ07WUSJ4gBS +Qp4efxSRNIfMj7DR6qLLf13RpIPTJO9/+gNuBIFcupWVfUL7tJZt8Qsf9eGwZfP+ +YyhjC8AyZjH4/9RzLHSjuq6apgw3Mzw0j572Xg6xDLMK8C3Tn/vrLOvAd96b9MkF +3+ZHSLW3IgOiy+1jvK/20CZxNWc+pey8v4zji1hI17iohsipX/uZKRxhxF6+Xn2R +UQp6qoxHAspNXgWQ57xg7C3+gmi4ciVr0fT9pg54ogcowrRH+I6wd0EpeWPbzfnQ +pRmMVN+YtRsrEHwH3ToQ/i4vrtgA+eONuKT2uKZFikxA+VNmeeGdhkgqETMihQ== + """) + prv_key_our = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1] + + def keker(curve, prv, pub, ukm): + return kek_34102012256( + curve, + prv_unmarshal(prv), + pub_unmarshal(pub), + ukm_unmarshal(ukm), + ) + + self.process_cms( + content_info_raw, + prv_key_our, + "id-GostR3410-2001-CryptoPro-XchA-ParamSet", + keker, + b"Test data to encrypt.\n" * 100, + ) + + def test_512(self): + content_info_raw = b64decode(""" +MIIB0gYJKoZIhvcNAQcDoIIBwzCCAb8CAQAxggF8MIIBeAIBADBbMFYxKTAnBgkq +hkiG9w0BCQEWGkdvc3RSMzQxMC0yMDEyQGV4YW1wbGUuY29tMSkwJwYDVQQDEyBH +b3N0UjM0MTAtMjAxMiA1MTIgYml0cyBleGNoYW5nZQIBATAhBggqhQMHAQEBAjAV +BgkqhQMHAQIBAgIGCCqFAwcBAQIDBIHyMIHvMCgEIIsYzbVLn33aLinQ7SLNA7y+ +Lrm02khqDCfXrNS9iiMhBATerS8zoIHCBgkqhQMHAQIFAQGggaowIQYIKoUDBwEB +AQIwFQYJKoUDBwECAQICBggqhQMHAQECAwOBhAAEgYAYiTVLKpSGaAvjJEDQ0hdK +qR/jek5Q9Q2pXC+NkOimQh7dpCi+wcaHlPcBk96hmpnOFvLaiokX8V6jqtBl5gdk +M40kOXv8kcDdTzEVKA/ZLxA8xanL+gTD6ZjaPsUu06nsA2MoMBWcHLUzueaP3bGT +/yHTV+Za5xdcQehag/lNBgQIvCw4uUl0XC4wOgYJKoZIhvcNAQcBMB8GBiqFAwIC +FTAVBAj+1QzaXaN9FwYJKoUDBwECBQEBgAyK54euw0sHhEVEkA0= + """) + prv_key_our = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1] + + def keker(curve, prv, pub, ukm): + return kek_34102012256( + curve, + prv_unmarshal(prv), + pub_unmarshal(pub), + ukm_unmarshal(ukm), + ) + + self.process_cms( + content_info_raw, + prv_key_our, + "id-tc26-gost-3410-12-512-paramSetB", + keker, + b"Test message", + ) + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestEnvelopedKARI(TestCase): + """EnvelopedData KeyAgreeRecipientInfo-based test vectors from + "Использование алгоритмов ГОСТ 28147-89, ГОСТ Р 34.11 и ГОСТ Р 34.10 + в криптографических сообщениях формата CMS" (TK26CMS.pdf) + """ + + def process_cms( + self, + content_info_raw, + prv_key_our, + curve_name, + keker, + plaintext_expected, + ): + sbox = "id-tc26-gost-28147-param-Z" + content_info, tail = ContentInfo().decode(content_info_raw, ctx={ + "defines_by_path": [ + ( + ( + "content", + DecodePathDefBy(id_envelopedData), + "recipientInfos", + any, + "kari", + "originator", + "originatorKey", + "algorithm", + "algorithm", + ), + ( + ( + ("..", "publicKey"), + { + id_tc26_gost3410_2012_256: OctetString(), + id_tc26_gost3410_2012_512: OctetString(), + }, + ), + ), + ) for _ in ( + id_tc26_gost3410_2012_256, + id_tc26_gost3410_2012_512, + ) + ], + }) + self.assertSequenceEqual(tail, b"") + self.assertIsNotNone(content_info["content"].defined) + _, enveloped_data = content_info["content"].defined + eci = enveloped_data["encryptedContentInfo"] + kari = enveloped_data["recipientInfos"][0]["kari"] + self.assertIsNotNone(kari["originator"]["originatorKey"]["publicKey"].defined) + _, pub_key_their = kari["originator"]["originatorKey"]["publicKey"].defined + ukm = bytes(kari["ukm"]) + rek = kari["recipientEncryptedKeys"][0] + curve = CURVES[curve_name] + kek = keker(curve, prv_key_our, bytes(pub_key_their), ukm) + self.assertIsNotNone(rek["encryptedKey"].defined) + _, encrypted_key = rek["encryptedKey"].defined + key_wrapped = bytes(encrypted_key["encryptedKey"]) + mac = bytes(encrypted_key["macKey"]) + cek = unwrap_gost(kek, ukm + key_wrapped + mac, sbox=sbox) + ciphertext = bytes(eci["encryptedContent"]) + self.assertIsNotNone(eci["contentEncryptionAlgorithm"]["parameters"].defined) + _, encryption_params = eci["contentEncryptionAlgorithm"]["parameters"].defined + iv = bytes(encryption_params["iv"]) + self.assertSequenceEqual( + cfb_decrypt(cek, ciphertext, iv, sbox=sbox, mesh=True), + plaintext_expected, + ) + + def test_256(self): + content_info_raw = b64decode(""" +MIIBhgYJKoZIhvcNAQcDoIIBdzCCAXMCAQIxggEwoYIBLAIBA6BooWYwHwYIKoUD +BwEBAQEwEwYHKoUDAgIkAAYIKoUDBwEBAgIDQwAEQPAdWM4pO38iZ49UjaXQpq+a +jhTa4KwY4B9TFMK7AiYmbFKE0eX/wvu69kFMQ2o3OJTnMOlr1WHiPYOmNO6C5hOh +CgQIX+vNomZakEIwIgYIKoUDBwEBAQEwFgYHKoUDAgINADALBgkqhQMHAQIFAQEw +gYwwgYkwWzBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxl +LmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgMjU2IGJpdHMgZXhjaGFuZ2UC +AQEEKjAoBCCNhrZOr7x2fsjjQAeDMv/tSoNRQSSQzzxgqdnYxJ3fIAQEgYLqVDA6 +BgkqhkiG9w0BBwEwHwYGKoUDAgIVMBUECHVmR/S+hlYiBgkqhQMHAQIFAQGADEI9 +UNjyuY+54uVcHw== + """) + prv_key_our = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1] + + def keker(curve, prv, pub, ukm): + return kek_34102012256( + curve, + prv_unmarshal(prv), + pub_unmarshal(pub), + ukm_unmarshal(ukm), + ) + + self.process_cms( + content_info_raw, + prv_key_our, + "id-GostR3410-2001-CryptoPro-XchA-ParamSet", + keker, + b"Test message", + ) + + def test_512(self): + content_info_raw = b64decode(""" +MIIBzAYJKoZIhvcNAQcDoIIBvTCCAbkCAQIxggF2oYIBcgIBA6CBraGBqjAhBggq +hQMHAQEBAjAVBgkqhQMHAQIBAgIGCCqFAwcBAQIDA4GEAASBgCB0nQy/Ljva/mRj +w6o+eDKIvnxwYIQB5XCHhZhCpHNZiWcFxFpYXZLWRPKifOxV7NStvqGE1+fkfhBe +btkQu0tdC1XL3LO2Cp/jX16XhW/IP5rKV84qWr1Owy/6tnSsNRb+ez6IttwVvaVV +pA6ONFy9p9gawoC8nitvAVJkWW0PoQoECDVfxzxgMTAHMCIGCCqFAwcBAQECMBYG +ByqFAwICDQAwCwYJKoUDBwECBQEBMIGMMIGJMFswVjEpMCcGCSqGSIb3DQEJARYa +R29zdFIzNDEwLTIwMTJAZXhhbXBsZS5jb20xKTAnBgNVBAMTIEdvc3RSMzQxMC0y +MDEyIDUxMiBiaXRzIGV4Y2hhbmdlAgEBBCowKAQg8C/OcxRR0Uq8nDjHrQlayFb3 +WFUZEnEuAKcuG6dTOawEBLhi9hIwOgYJKoZIhvcNAQcBMB8GBiqFAwICFTAVBAiD +1wH+CX6CwgYJKoUDBwECBQEBgAzUvQI4H2zRfgNgdlY= + """) + prv_key_our = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1] + + def keker(curve, prv, pub, ukm): + return kek_34102012256( + curve, + prv_unmarshal(prv), + pub_unmarshal(pub), + ukm_unmarshal(ukm), + ) + + self.process_cms( + content_info_raw, + prv_key_our, + "id-tc26-gost-3410-12-512-paramSetB", + keker, + b"Test message", + ) + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestR132356510252019(TestCase): + """Test vectors from Р 1323565.1.025-2019 + """ + def setUp(self): + self.curve256 = CURVES["id-tc26-gost-3410-2012-256-paramSetA"] + self.curve512 = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + self.psk = hexdec("8F5EEF8814D228FB2BBC5612323730CFA33DB7263CC2C0A01A6C6953F33D61D5")[::-1] + + self.ca_prv = prv_unmarshal(hexdec("092F8D059E97E22B90B1AE99F0087FC4D26620B91550CBB437C191005A290810")[::-1]) + self.ca_pub = public_key(self.curve256, self.ca_prv) + self.ca_cert = Certificate().decod(b64decode(""" +MIIB8DCCAZ2gAwIBAgIEAYy6gTAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2 +MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw +MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA4MQ0wCwYDVQQKEwRUSzI2MScwJQYD +VQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwaDAhBggqhQMHAQEB +ATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABEAaSoKcjw54UACci6svELNF0IYM +RIW8urUsqamIpoG46XCqrVOuI6Q13N4dwcRsbZdqByf+GC2f5ZfO3baN5bTKo4GF +MIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzESoTowODENMAsGA1UE +ChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0 +ggQBjLqBMB0GA1UdDgQWBBSA2Qz3mfhmTZNTiY7AnnEtp6cxEjAKBggqhQMHAQED +AgNBAAgv248F4OeNCkhlzJWec0evHYnMBlSzk1lDm0F875B7CqMrKh2MtJHXenbj +Gc2uRn2IwgmSf/LZDrYsKKqZSxk= +""")) + + self.sender256_prv = prv_unmarshal(hexdec("0B20810E449978C7C3B76C6FF77A16C532421139344A058EF56310B6B6F377E8")[::-1]) + self.sender256_pub = public_key(self.curve256, self.sender256_prv) + self.sender256_cert = Certificate().decod(b64decode(""" +MIIB8zCCAaCgAwIBAgIEAYy6gjAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2 +MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw +MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYD +VQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwaDAhBggqhQMH +AQEBATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABECWKQ0TYllqg4GmY3tBJiyz +pXUN+aOV9WbmTUinqrmEHP7KCNzoAzFg+04SSQpNNSHpQnm+jLAZhuJaJfqZ6VbT +o4GFMIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzESoTowODENMAsG +A1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYt +Yml0ggQBjLqBMB0GA1UdDgQWBBTRnChHSWbQYwnJC62n2zu5Njd03zAKBggqhQMH +AQEDAgNBAB41oijaXSEn58l78y2rhxY35/lKEq4XWZ70FtsNlVxWATyzgO5Wliwn +t1O4GoZsxx8r6T/i7VG65UNmQlwdOKQ= +""")) + + self.recipient256_prv = prv_unmarshal(hexdec("0DC8DC1FF2BC114BABC3F1CA8C51E4F58610427E197B1C2FBDBA4AE58CBFB7CE")[::-1]) + self.recipient256_pub = public_key(self.curve256, self.recipient256_prv) + self.recipient256_cert = Certificate().decod(b64decode(""" +MIIB8jCCAZ+gAwIBAgIEAYy6gzAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2 +MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw +MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA6MQ0wCwYDVQQKEwRUSzI2MSkwJwYD +VQQDEyBSRUNJUElFTlQ6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdDBoMCEGCCqFAwcB +AQEBMBUGCSqFAwcBAgEBAQYIKoUDBwEBAgIDQwAEQL8nghlzLGMKWHuWhNMPMN5u +L6SkGqRiJ6qZxZb+4dPKbBT9LNVvNKtwUed+BeE5kfqOfolPgFusnL1rnO9yREOj +gYUwgYIwYQYDVR0BBFowWIAUgNkM95n4Zk2TU4mOwJ5xLaenMRKhOjA4MQ0wCwYD +VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1i +aXSCBAGMuoEwHQYDVR0OBBYEFLue+PUb9Oe+pziBU+MvNejjgrzFMAoGCCqFAwcB +AQMCA0EAPP9Oad1/5jwokSjPpccsQ0xCdVYM+mGQ0IbpiZxQj8gnkt8sq4jR6Ya+ +I/BDkbZNDNE27TU1p3t5rE9NMEeViA== +""")) + + self.sender512_prv = prv_unmarshal(hexdec("F95A5D44C5245F63F2E7DF8E782C1924EADCB8D06C52D91023179786154CBDB1561B4DF759D69F67EE1FBD5B68800E134BAA12818DA4F3AC75B0E5E6F9256911")[::-1]) + self.sender512_pub = public_key(self.curve512, self.sender512_prv) + self.sender512_cert = Certificate().decod(b64decode(""" +MIICNjCCAeOgAwIBAgIEAYy6hDAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2 +MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw +MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYD +VQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDUxMi1iaXQwgaowIQYIKoUD +BwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwOBhAAEgYC0i7davCkOGGVcYqFP +tS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO+K21LDpYVfDPs2Sqa13ZN+Ts +/JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0EmZf8T3ae/J1Jo6xGunecH1/G4 +hMts9HYLnxbwJDMNVGuIHV6gzqOBhTCBgjBhBgNVHQEEWjBYgBSA2Qz3mfhmTZNT +iY7AnnEtp6cxEqE6MDgxDTALBgNVBAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6 +IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6gTAdBgNVHQ4EFgQUK+l9HAscONGx +zCcRpxRAmFHvlXowCgYIKoUDBwEBAwIDQQAbjA0Q41/rIKOOvjHKsAsoEJM+WJf6 +/PKXg2JaStthmw99bdtwwkU/qDbcje2tF6mt+XWyQBXwvfeES1GFY9fJ +""")) + + self.recipient512_prv = prv_unmarshal(hexdec("A50315981F0A7C7FC05B4EB9591A62B1F84BD6FD518ACFCEDF0A7C9CF388D1F18757C056ADA5B38CBF24CDDB0F1519EF72DB1712CEF1920952E94AF1F9C575DC")[::-1]) + self.recipient512_pub = public_key(self.curve512, self.recipient512_prv) + self.recipient512_cert = Certificate().decod(b64decode(""" +MIICNTCCAeKgAwIBAgIEAYy6hTAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2 +MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw +MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA6MQ0wCwYDVQQKEwRUSzI2MSkwJwYD +VQQDEyBSRUNJUElFTlQ6IEdPU1QgMzQuMTAtMTIgNTEyLWJpdDCBqjAhBggqhQMH +AQEBAjAVBgkqhQMHAQIBAgEGCCqFAwcBAQIDA4GEAASBgKauwGYvUkzz19g0LP/p +zeRdmwy1m+QSy9W5ZrL/AGuJofm2ARjz40ozNbW6bp9hkHu8x66LX7u5zz+QeS2+ +X5om18UXriComgO0+qhZbc+Hzu0eQ8FjOd8LpLk3TzzfBltfLOX5IiPLjeum+pSP +0QjoXAVcrop//B4yvZIukvROo4GFMIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJ +jsCecS2npzESoTowODENMAsGA1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjog +R09TVCAzNC4xMC0xMiAyNTYtYml0ggQBjLqBMB0GA1UdDgQWBBSrXT5VKhm/5uff +kwW0XpG19k6AajAKBggqhQMHAQEDAgNBAAJBpsHRrQKZGb22LOzaReEB8rl2MbIR +ja64NaM5h+cAFoHm6t/k+ziLh2A11rTakR+5of4NQ3EjEhuPtomP2tc= +""")) + + def test_certs(self): + """Certificates signatures + """ + for prv, pub, curve, cert in ( + (self.ca_prv, self.ca_pub, self.curve256, self.ca_cert), + (self.sender256_prv, self.sender256_pub, self.curve256, self.sender256_cert), + (self.recipient256_prv, self.recipient256_pub, self.curve256, self.recipient256_cert), + (self.sender512_prv, self.sender512_pub, self.curve512, self.sender512_cert), + (self.recipient512_prv, self.recipient512_pub, self.curve512, self.recipient512_cert), + ): + pub_our = public_key(curve, prv) + self.assertEqual(pub_our, pub) + self.assertSequenceEqual( + pub_marshal(pub_our), + bytes(OctetString().decod(bytes( + cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"] + ))), + ) + + for cert in ( + self.ca_cert, + self.sender256_cert, + self.recipient256_cert, + self.sender512_cert, + self.recipient512_cert, + ): + self.assertTrue(verify( + self.curve256, + self.ca_pub, + GOST34112012256(cert["tbsCertificate"].encode()).digest()[::-1], + bytes(cert["signatureValue"]), + )) + + def test_signed_with_attrs(self): + ci = ContentInfo().decod(b64decode(""" +MIIENwYJKoZIhvcNAQcCoIIEKDCCBCQCAQExDDAKBggqhQMHAQECAzA7BgkqhkiG +9w0BBwGgLgQsyu7t8vDu6/zt++kg7/Do7OXwIOTr/yDx8vDz6vLz8PsgU2lnbmVk +RGF0YS6gggI6MIICNjCCAeOgAwIBAgIEAYy6hDAKBggqhQMHAQEDAjA4MQ0wCwYD +VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1i +aXQwHhcNMDEwMTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRU +SzI2MSowKAYDVQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDUxMi1iaXQw +gaowIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwOBhAAEgYC0i7da +vCkOGGVcYqFPtS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO+K21LDpYVfDP +s2Sqa13ZN+Ts/JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0EmZf8T3ae/J1Jo +6xGunecH1/G4hMts9HYLnxbwJDMNVGuIHV6gzqOBhTCBgjBhBgNVHQEEWjBYgBSA +2Qz3mfhmTZNTiY7AnnEtp6cxEqE6MDgxDTALBgNVBAoTBFRLMjYxJzAlBgNVBAMT +HkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6gTAdBgNVHQ4EFgQU +K+l9HAscONGxzCcRpxRAmFHvlXowCgYIKoUDBwEBAwIDQQAbjA0Q41/rIKOOvjHK +sAsoEJM+WJf6/PKXg2JaStthmw99bdtwwkU/qDbcje2tF6mt+XWyQBXwvfeES1GF +Y9fJMYIBlDCCAZACAQEwQDA4MQ0wCwYDVQQKEwRUSzI2MScwJQYDVQQDEx5DQSBU +SzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQCBAGMuoQwCgYIKoUDBwEBAgOgga0w +GAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTkwMzIw +MTk1NTIyWjAiBgkqhkiG9w0BCWIxFQQTU2lnbmVkIGF0dHIncyB2YWx1ZTBPBgkq +hkiG9w0BCQQxQgRAUdPHEukF5BIfo9DoQIMdnB0ZLkzq0RueEUZSNv07A7C+GKWi +G62fueArg8uPCHPTUN6d/42p33fgMkEwH7f7cDAKBggqhQMHAQEBAgSBgGUnVka8 +FvTlClmOtj/FUUacBdE/nEBeMLOO/535VDYrXlftPE6zQf/4ghS7TQG2VRGQ3GWD ++L3+W09A7d5uyyTEbvgtdllUG0OyqFwKmJEaYsMin87SFVs0cn1PGV1fOKeLluZa +bLx5whxd+mzlpekL5i6ImRX+TpERxrA/xSe5 +""")) + _, sd = ci["content"].defined + content = bytes(sd["encapContentInfo"]["eContent"]) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры SignedData."), + ) + si = sd["signerInfos"][0] + self.assertEqual( + si["digestAlgorithm"]["algorithm"], + id_tc26_gost3411_2012_512, + ) + digest = [ + bytes(attr["attrValues"][0].defined[1]) for attr in si["signedAttrs"] + if attr["attrType"] == id_messageDigest + ][0] + self.assertSequenceEqual(digest, GOST34112012512(content).digest()) + self.assertTrue(verify( + self.curve512, + self.sender512_pub, + GOST34112012512( + SignedAttributes(si["signedAttrs"]).encode() + ).digest()[::-1], + bytes(si["signature"]), + )) + + def test_signed_without_attrs(self): + ci = ContentInfo().decod(b64decode(""" +MIIDAQYJKoZIhvcNAQcCoIIC8jCCAu4CAQExDDAKBggqhQMHAQECAjA7BgkqhkiG +9w0BBwGgLgQsyu7t8vDu6/zt++kg7/Do7OXwIOTr/yDx8vDz6vLz8PsgU2lnbmVk +RGF0YS6gggH3MIIB8zCCAaCgAwIBAgIEAYy6gjAKBggqhQMHAQEDAjA4MQ0wCwYD +VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1i +aXQwHhcNMDEwMTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRU +SzI2MSowKAYDVQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQw +aDAhBggqhQMHAQEBATAVBgkqhQMHAQIBAQEGCCqFAwcBAQICA0MABECWKQ0TYllq +g4GmY3tBJiyzpXUN+aOV9WbmTUinqrmEHP7KCNzoAzFg+04SSQpNNSHpQnm+jLAZ +huJaJfqZ6VbTo4GFMIGCMGEGA1UdAQRaMFiAFIDZDPeZ+GZNk1OJjsCecS2npzES +oTowODENMAsGA1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4x +MC0xMiAyNTYtYml0ggQBjLqBMB0GA1UdDgQWBBTRnChHSWbQYwnJC62n2zu5Njd0 +3zAKBggqhQMHAQEDAgNBAB41oijaXSEn58l78y2rhxY35/lKEq4XWZ70FtsNlVxW +ATyzgO5Wliwnt1O4GoZsxx8r6T/i7VG65UNmQlwdOKQxgaIwgZ8CAQEwQDA4MQ0w +CwYDVQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1 +Ni1iaXQCBAGMuoIwCgYIKoUDBwEBAgIwCgYIKoUDBwEBAQEEQC6jZPA59szL9FiA +0wC71EBE42ap6gKxklT800cu2FvbLu972GJYNSI7+UeanVU37OVWyenEXi2E5HkU +94kBe8Q= +""")) + _, sd = ci["content"].defined + content = bytes(sd["encapContentInfo"]["eContent"]) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры SignedData."), + ) + si = sd["signerInfos"][0] + self.assertEqual( + si["digestAlgorithm"]["algorithm"], + id_tc26_gost3411_2012_256, + ) + self.assertTrue(verify( + self.curve256, + self.sender256_pub, + GOST34112012256(content).digest()[::-1], + bytes(si["signature"]), + )) + + def test_kari_ephemeral(self): + ci = ContentInfo().decod(b64decode(""" +MIIB/gYJKoZIhvcNAQcDoIIB7zCCAesCAQIxggFioYIBXgIBA6CBo6GBoDAXBggq +hQMHAQEBAjALBgkqhQMHAQIBAgEDgYQABIGAe+itJVNbHM35RHfzuwFJPYdPXqtW +8hNEF7Z/XFEE2T71SRkhFX7ozYKQNh/TkVY9D4vG0LnD9Znr/pJyOjpsNb+dPcKX +Kbk/0JQxoPGHxFzASVAFq0ov/yBe2XGFWMeKUqtaAr7SvoYS0oEhT5EuT8BXmecd +nRe7NqOzESpb15ahIgQgsqHxOcdOp03l11S7k3OH1k1HNa5F8m9ctrOzH2846FMw +FwYJKoUDBwEBBwIBMAoGCCqFAwcBAQYCMHYwdDBAMDgxDTALBgNVBAoTBFRLMjYx +JzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdAIEAYy6hQQw +SxLc18zMwzLwXbcKqYhV/VzsdBgVArOHsSBIbaThJWE7zI37VGPMQJM5VXJ7GVcL +MF0GCSqGSIb3DQEHATAfBgkqhQMHAQEFAgIwEgQQ6EeVlADDCz2cdEWKy+tM94Av +yIFl/Ie4VeFFuczTsMsIaOUEe3Jn9GeVp8hZSj3O2q4hslQ/u/+Gj4QkSHm/M0ih +ITAfBgkqhQMHAQAGAQExEgQQs1t6D3J3WCEvxunnEE15NQ== +""")) + _, ed = ci["content"].defined + kari = ed["recipientInfos"][0]["kari"] + orig_key = kari["originator"]["originatorKey"] + self.assertEqual(orig_key["algorithm"]["algorithm"], id_tc26_gost3410_2012_512) + self.assertEqual( + GostR34102012PublicKeyParameters().decod( + bytes(orig_key["algorithm"]["parameters"]) + )["publicKeyParamSet"], + id_tc26_gost3410_2012_512_paramSetA, + ) + orig_pub = pub_unmarshal( + bytes(OctetString().decod(bytes(orig_key["publicKey"]))), + ) + ukm = bytes(kari["ukm"]) + self.assertEqual( + kari["keyEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_kuznyechik_wrap_kexp15, + ) + self.assertEqual( + kari["keyEncryptionAlgorithm"]["parameters"].defined[1]["algorithm"], + id_tc26_agreement_gost3410_2012_512, + ) + kexp = bytes(kari["recipientEncryptedKeys"][0]["encryptedKey"]) + keymat = keg(self.curve512, self.recipient512_prv, orig_pub, ukm) + kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:] + cek = kimp15( + GOST3412Kuznechik(kek).encrypt, + GOST3412Kuznechik(kim).encrypt, + GOST3412Kuznechik.blocksize, + kexp, + ukm[24:24 + GOST3412Kuznechik.blocksize // 2], + ) + eci = ed["encryptedContentInfo"] + self.assertEqual( + eci["contentEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_kuznyechik_ctracpkm_omac, + ) + eci_ukm = bytes( + eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"] + ) + self.assertEqual(ed["unprotectedAttrs"][0]["attrType"], id_cms_mac_attr) + encrypted_mac = bytes(ed["unprotectedAttrs"][0]["attrValues"][0].defined[1]) + encrypted_content = bytes(eci["encryptedContent"]) + cek_enc, cek_mac = kdf_tree_gostr3411_2012_256( + cek, b"kdf tree", eci_ukm[GOST3412Kuznechik.blocksize // 2:], 2, + ) + content_and_tag = ctr_acpkm( + GOST3412Kuznechik, + GOST3412Kuznechik(cek_enc).encrypt, + 256 * 1024, + GOST3412Kuznechik.blocksize, + encrypted_content + encrypted_mac, + eci_ukm[:GOST3412Kuznechik.blocksize // 2], + ) + content = content_and_tag[:-GOST3412Kuznechik.blocksize] + tag_expected = content_and_tag[-GOST3412Kuznechik.blocksize:] + self.assertSequenceEqual( + omac( + GOST3412Kuznechik(cek_mac).encrypt, + GOST3412Kuznechik.blocksize, + content, + ), + tag_expected, + ) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры EnvelopedData."), + ) + + def test_kari_static(self): + ci = ContentInfo().decod(b64decode(""" +MIIBawYJKoZIhvcNAQcDoIIBXDCCAVgCAQIxgfehgfQCAQOgQjBAMDgxDTALBgNV +BAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJp +dAIEAYy6gqEiBCBvcfyuSF57y8vVyaw8Z0ch3wjC4lPKTrpVRXty4Rhk5DAXBgkq +hQMHAQEHAQEwCgYIKoUDBwEBBgEwbjBsMEAwODENMAsGA1UEChMEVEsyNjEnMCUG +A1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0AgQBjLqDBChPbi6B +krXuLPexPAL2oUGCFWDGQHqINL5ExuMBG7/5XQRqriKARVa0MFkGCSqGSIb3DQEH +ATAbBgkqhQMHAQEFAQEwDgQMdNdCKnYAAAAwqTEDgC9O2bYyTGQJ8WUQGq0zHwzX +L0jFhWHTF1tcAxYmd9pX5i89UwIxhtYqyjX1QHju2g== +""")) + _, ed = ci["content"].defined + kari = ed["recipientInfos"][0]["kari"] + ukm = bytes(kari["ukm"]) + self.assertEqual( + kari["keyEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_magma_wrap_kexp15, + ) + self.assertEqual( + kari["keyEncryptionAlgorithm"]["parameters"].defined[1]["algorithm"], + id_tc26_agreement_gost3410_2012_256, + ) + kexp = bytes(kari["recipientEncryptedKeys"][0]["encryptedKey"]) + keymat = keg( + self.curve256, + self.recipient256_prv, + self.sender256_pub, + ukm, + ) + kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:] + cek = kimp15( + GOST3412Magma(kek).encrypt, + GOST3412Magma(kim).encrypt, + GOST3412Magma.blocksize, + kexp, + ukm[24:24 + GOST3412Magma.blocksize // 2], + ) + eci = ed["encryptedContentInfo"] + self.assertEqual( + eci["contentEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_magma_ctracpkm, + ) + eci_ukm = bytes( + eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"] + ) + content = ctr_acpkm( + GOST3412Magma, + GOST3412Magma(cek).encrypt, + 8 * 1024, + GOST3412Magma.blocksize, + bytes(eci["encryptedContent"]), + eci_ukm[:GOST3412Magma.blocksize // 2], + ) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры EnvelopedData."), + ) + + def test_ktri_256(self): + ci = ContentInfo().decod(b64decode(""" +MIIBlQYJKoZIhvcNAQcDoIIBhjCCAYICAQAxggEcMIIBGAIBADBAMDgxDTALBgNV +BAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJp +dAIEAYy6gzAXBgkqhQMHAQEHAgEwCgYIKoUDBwEBBgEEgbcwgbQEMFiMredFR3Mv +3g2wqyVXRnrhYEBMNFaqqgBpHwPQh3bF98tt9HZPxRDCww0OPfxeuTBeMBcGCCqF +AwcBAQEBMAsGCSqFAwcBAgEBAQNDAARAdFJ9ww+3ptvQiaQpizCldNYhl4DB1rl8 +Fx/2FIgnwssCbYRQ+UuRsTk9dfLLTGJG3JIEXKFxXWBgOrK965A5pAQg9f2/EHxG +DfetwCe1a6uUDCWD+wp5dYOpfkry8YRDEJgwXQYJKoZIhvcNAQcBMB8GCSqFAwcB +AQUCATASBBDUHNxmVclO/v3OaY9P7jxOgC+sD9CHGlEMRUpfGn6yfFDMExmYeby8 +LzdPJe1MkYV0qQgdC1zI3nQ7/4taf+4zRA== +""")) + _, ed = ci["content"].defined + ktri = ed["recipientInfos"][0]["ktri"] + self.assertEqual( + ktri["keyEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_kuznyechik_wrap_kexp15, + ) + self.assertEqual( + ktri["keyEncryptionAlgorithm"]["parameters"].defined[1]["algorithm"], + id_tc26_agreement_gost3410_2012_256, + ) + _, encrypted_key = ktri["encryptedKey"].defined + self.assertEqual( + encrypted_key["ephemeralPublicKey"]["algorithm"]["algorithm"], + id_tc26_gost3410_2012_256, + ) + pub = pub_unmarshal(bytes(OctetString().decod( + bytes(encrypted_key["ephemeralPublicKey"]["subjectPublicKey"]) + ))) + ukm = bytes(encrypted_key["ukm"]) + kexp = bytes(encrypted_key["encryptedKey"]) + keymat = keg(self.curve256, self.recipient256_prv, pub, ukm) + kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:] + cek = kimp15( + GOST3412Kuznechik(kek).encrypt, + GOST3412Kuznechik(kim).encrypt, + GOST3412Kuznechik.blocksize, + kexp, + ukm[24:24 + GOST3412Kuznechik.blocksize // 2], + ) + eci = ed["encryptedContentInfo"] + self.assertEqual( + eci["contentEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_kuznyechik_ctracpkm, + ) + eci_ukm = bytes( + eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"] + ) + content = ctr_acpkm( + GOST3412Kuznechik, + GOST3412Kuznechik(cek).encrypt, + 256 * 1024, + GOST3412Kuznechik.blocksize, + bytes(eci["encryptedContent"]), + eci_ukm[:GOST3412Kuznechik.blocksize // 2], + ) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры EnvelopedData."), + ) + + def test_ktri_512(self): + ci = ContentInfo().decod(b64decode(""" +MIIB5wYJKoZIhvcNAQcDoIIB2DCCAdQCAQAxggFXMIIBUwIBADBAMDgxDTALBgNVBAoTBFRL +MjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdAIEAYy6hTAXBgkq +hQMHAQEHAQEwCgYIKoUDBwEBBgIEgfIwge8EKDof9JLTJVuIfP+c+imDCGyOLtAYENkoXpeU +CdiGn0Lt65t3TN9G0bUwgaAwFwYIKoUDBwEBAQIwCwYJKoUDBwECAQIBA4GEAASBgDD9XXHn +0j4EwY3DGB1wzHeThPRDlCwIvpmqWy00QDhS3fLRWiETSe9uMLeg27zI/EiserKMasNZum/i +d09cmP8aTNIDNRtI5H9M0mH7LpEtY8L901MszvOKHLDYdemvz0JUqOvBtvoeQ6sV4Gl45zXx +HTzBWlBw1FLX/ITWLapaBCAa09foTeA+PObBznGuCOPoKy+xz/9IIVmZidI6EYkIrzBZBgkq +hkiG9w0BBwEwGwYJKoUDBwEBBQECMA4EDA4z1UwRL4WYzKFX/oAv8eEX3fWt6hxDpjO0rI7/ +CiJ/CwYGCKODJ9h63vAwlsWwcPwAjxcsLvCNlv6i4NqhGTAXBgkqhQMHAQAGAQExCgQIs2DT +LuZ22Yw= +""")) + _, ed = ci["content"].defined + ktri = ed["recipientInfos"][0]["ktri"] + self.assertEqual( + ktri["keyEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_magma_wrap_kexp15, + ) + self.assertEqual( + ktri["keyEncryptionAlgorithm"]["parameters"].defined[1]["algorithm"], + id_tc26_agreement_gost3410_2012_512, + ) + _, encrypted_key = ktri["encryptedKey"].defined + self.assertEqual( + encrypted_key["ephemeralPublicKey"]["algorithm"]["algorithm"], + id_tc26_gost3410_2012_512, + ) + pub = pub_unmarshal( + bytes(OctetString().decod( + bytes(encrypted_key["ephemeralPublicKey"]["subjectPublicKey"]) + )), + ) + ukm = bytes(encrypted_key["ukm"]) + kexp = bytes(encrypted_key["encryptedKey"]) + keymat = keg(self.curve512, self.recipient512_prv, pub, ukm) + kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:] + cek = kimp15( + GOST3412Magma(kek).encrypt, + GOST3412Magma(kim).encrypt, + GOST3412Magma.blocksize, + kexp, + ukm[24:24 + GOST3412Magma.blocksize // 2], + ) + eci = ed["encryptedContentInfo"] + self.assertEqual( + eci["contentEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_magma_ctracpkm_omac, + ) + eci_ukm = bytes( + eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"] + ) + self.assertEqual(ed["unprotectedAttrs"][0]["attrType"], id_cms_mac_attr) + encrypted_mac = bytes(ed["unprotectedAttrs"][0]["attrValues"][0].defined[1]) + encrypted_content = bytes(eci["encryptedContent"]) + cek_enc, cek_mac = kdf_tree_gostr3411_2012_256( + cek, b"kdf tree", eci_ukm[GOST3412Magma.blocksize // 2:], 2, + ) + content_and_tag = ctr_acpkm( + GOST3412Magma, + GOST3412Magma(cek_enc).encrypt, + 8 * 1024, + GOST3412Magma.blocksize, + encrypted_content + encrypted_mac, + eci_ukm[:GOST3412Magma.blocksize // 2], + ) + content = content_and_tag[:-GOST3412Magma.blocksize] + tag_expected = content_and_tag[-GOST3412Magma.blocksize:] + self.assertSequenceEqual( + omac( + GOST3412Magma(cek_mac).encrypt, + GOST3412Magma.blocksize, + content, + ), + tag_expected, + ) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры EnvelopedData."), + ) + + def test_digested256(self): + ci = ContentInfo().decod(b64decode(""" +MH0GCSqGSIb3DQEHBaBwMG4CAQAwCgYIKoUDBwEBAgIwOwYJKoZIhvcNAQcBoC4ELMru7fLw +7uv87fvpIO/w6Ozl8CDk6/8g8fLw8+ry8/D7IERpZ2VzdERhdGEuBCD/esPQYsGkzxZV8uUM +IAWt6SI8KtxBP8NyG8AGbJ8i/Q== +""")) + _, dd = ci["content"].defined + eci = dd["encapContentInfo"] + self.assertSequenceEqual( + GOST34112012256(bytes(eci["eContent"])).digest(), + bytes(dd["digest"]), + ) + + def test_digested512(self): + ci = ContentInfo().decod(b64decode(""" +MIGfBgkqhkiG9w0BBwWggZEwgY4CAQAwCgYIKoUDBwEBAgMwOwYJKoZIhvcNAQcBoC4ELMru +7fLw7uv87fvpIO/w6Ozl8CDk6/8g8fLw8+ry8/D7IERpZ2VzdERhdGEuBEDe4VUvcKSRvU7R +FVhFjajXY+nJSUkUsoi3oOeJBnru4PErt8RusPrCJs614ciHCM+ehrC4a+M1Nbq77F/Wsa/v +""")) + _, dd = ci["content"].defined + eci = dd["encapContentInfo"] + self.assertSequenceEqual( + GOST34112012512(bytes(eci["eContent"])).digest(), + bytes(dd["digest"]), + ) + + def test_encrypted_kuznechik(self): + ci = ContentInfo().decod(b64decode(""" +MHEGCSqGSIb3DQEHBqBkMGICAQAwXQYJKoZIhvcNAQcBMB8GCSqFAwcBAQUCATASBBBSwX+z +yOEPPuGyfpsRG4AigC/P8ftTdQMStfIThVkE/vpJlwaHgGv83m2bsPayeyuqpoTeEMOaqGcO +0MxHWsC9hQ== +""")) + _, ed = ci["content"].defined + eci = ed["encryptedContentInfo"] + self.assertEqual( + eci["contentEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_kuznyechik_ctracpkm, + ) + ukm = bytes( + eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"] + ) + content = ctr_acpkm( + GOST3412Kuznechik, + GOST3412Kuznechik(self.psk).encrypt, + 256 * 1024, + GOST3412Kuznechik.blocksize, + bytes(eci["encryptedContent"]), + ukm[:GOST3412Kuznechik.blocksize // 2], + ) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры EncryptedData."), + ) + + def test_encrypted_magma(self): + ci = ContentInfo().decod(b64decode(""" +MIGIBgkqhkiG9w0BBwagezB5AgEAMFkGCSqGSIb3DQEHATAbBgkqhQMHAQEFAQIwDgQMuncO +u3uYPbI30vFCgC9Nsws4R09yLp6jUtadncWUPZGmCGpPKnXGgNHvEmUArgKJvu4FPHtLkHuL +eQXZg6EZMBcGCSqFAwcBAAYBATEKBAjCbQoH632oGA== +""")) + _, ed = ci["content"].defined + eci = ed["encryptedContentInfo"] + self.assertEqual( + eci["contentEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_magma_ctracpkm_omac, + ) + ukm = bytes( + eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"] + ) + self.assertEqual(ed["unprotectedAttrs"][0]["attrType"], id_cms_mac_attr) + encrypted_mac = bytes(ed["unprotectedAttrs"][0]["attrValues"][0].defined[1]) + cek_enc, cek_mac = kdf_tree_gostr3411_2012_256( + self.psk, b"kdf tree", ukm[GOST3412Magma.blocksize // 2:], 2, + ) + content_and_tag = ctr_acpkm( + GOST3412Magma, + GOST3412Magma(cek_enc).encrypt, + 8 * 1024, + GOST3412Magma.blocksize, + bytes(eci["encryptedContent"]) + encrypted_mac, + ukm[:GOST3412Magma.blocksize // 2], + ) + content = content_and_tag[:-GOST3412Magma.blocksize] + tag_expected = content_and_tag[-GOST3412Magma.blocksize:] + self.assertSequenceEqual( + omac( + GOST3412Magma(cek_mac).encrypt, + GOST3412Magma.blocksize, + content, + ), + tag_expected, + ) + self.assertEqual( + content.decode("cp1251"), + text_type(u"Контрольный пример для структуры EncryptedData."), + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost28147.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost28147.py new file mode 100644 index 0000000..a83e930 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost28147.py @@ -0,0 +1,384 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import urandom +from unittest import TestCase + +from pygost.gost28147 import block2ns +from pygost.gost28147 import BLOCKSIZE +from pygost.gost28147 import cbc_decrypt +from pygost.gost28147 import cbc_encrypt +from pygost.gost28147 import cfb_decrypt +from pygost.gost28147 import cfb_encrypt +from pygost.gost28147 import cnt +from pygost.gost28147 import DEFAULT_SBOX +from pygost.gost28147 import ecb_decrypt +from pygost.gost28147 import ecb_encrypt +from pygost.gost28147 import encrypt +from pygost.gost28147 import KEYSIZE +from pygost.gost28147 import MESH_MAX_DATA +from pygost.gost28147 import ns2block +from pygost.utils import hexdec +from pygost.utils import strxor + + +class ECBTest(TestCase): + def test_gcl(self): + """Test vectors from libgcl3 + """ + sbox = "id-Gost28147-89-TestParamSet" + key = hexdec(b"0475f6e05038fbfad2c7c390edb3ca3d1547124291ae1e8a2f79cd9ed2bcefbd") + plaintext = bytes(bytearray(( + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, + 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, + 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, + 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, + 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, + 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, + 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, + 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, + 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, + 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, + 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, + 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, + 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, + 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, + 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, + 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, + 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, + 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, + 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, + 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + ))) + ciphertext = bytes(bytearray(( + 0x4b, 0x8c, 0x4c, 0x98, 0x15, 0xf2, 0x4a, 0xea, + 0x1e, 0xc3, 0x57, 0x09, 0xb3, 0xbc, 0x2e, 0xd1, + 0xe0, 0xd1, 0xf2, 0x22, 0x65, 0x2d, 0x59, 0x18, + 0xf7, 0xdf, 0xfc, 0x80, 0x4b, 0xde, 0x5c, 0x68, + 0x46, 0x53, 0x75, 0x53, 0xa7, 0x46, 0x0d, 0xec, + 0x05, 0x1f, 0x1b, 0xd3, 0x0a, 0x63, 0x1a, 0xb7, + 0x78, 0xc4, 0x43, 0xe0, 0x5d, 0x3e, 0xa4, 0x0e, + 0x2d, 0x7e, 0x23, 0xa9, 0x1b, 0xc9, 0x02, 0xbc, + 0x21, 0x0c, 0x84, 0xcb, 0x0d, 0x0a, 0x07, 0xc8, + 0x7b, 0xd0, 0xfb, 0xb5, 0x1a, 0x14, 0x04, 0x5c, + 0xa2, 0x53, 0x97, 0x71, 0x2e, 0x5c, 0xc2, 0x8f, + 0x39, 0x3f, 0x6f, 0x52, 0xf2, 0x30, 0x26, 0x4e, + 0x8c, 0xe0, 0xd1, 0x01, 0x75, 0x6d, 0xdc, 0xd3, + 0x03, 0x79, 0x1e, 0xca, 0xd5, 0xc1, 0x0e, 0x12, + 0x53, 0x0a, 0x78, 0xe2, 0x0a, 0xb1, 0x1c, 0xea, + 0x3a, 0xf8, 0x55, 0xb9, 0x7c, 0xe1, 0x0b, 0xba, + 0xa0, 0xc8, 0x96, 0xeb, 0x50, 0x5a, 0xd3, 0x60, + 0x43, 0xa3, 0x0f, 0x98, 0xdb, 0xd9, 0x50, 0x6d, + 0x63, 0x91, 0xaf, 0x01, 0x40, 0xe9, 0x75, 0x5a, + 0x46, 0x5c, 0x1f, 0x19, 0x4a, 0x0b, 0x89, 0x9b, + 0xc4, 0xf6, 0xf8, 0xf5, 0x2f, 0x87, 0x3f, 0xfa, + 0x26, 0xd4, 0xf8, 0x25, 0xba, 0x1f, 0x98, 0x82, + 0xfc, 0x26, 0xaf, 0x2d, 0xc0, 0xf9, 0xc4, 0x58, + 0x49, 0xfa, 0x09, 0x80, 0x02, 0x62, 0xa4, 0x34, + 0x2d, 0xcb, 0x5a, 0x6b, 0xab, 0x61, 0x5d, 0x08, + 0xd4, 0x26, 0xe0, 0x08, 0x13, 0xd6, 0x2e, 0x02, + 0x2a, 0x37, 0xe8, 0xd0, 0xcf, 0x36, 0xf1, 0xc7, + 0xc0, 0x3f, 0x9b, 0x21, 0x60, 0xbd, 0x29, 0x2d, + 0x2e, 0x01, 0x48, 0x4e, 0xf8, 0x8f, 0x20, 0x16, + 0x8a, 0xbf, 0x82, 0xdc, 0x32, 0x7a, 0xa3, 0x18, + 0x69, 0xd1, 0x50, 0x59, 0x31, 0x91, 0xf2, 0x6c, + 0x5a, 0x5f, 0xca, 0x58, 0x9a, 0xb2, 0x2d, 0xb2, + ))) + encrypted = ecb_encrypt(key, plaintext, sbox=sbox) + self.assertSequenceEqual(encrypted, ciphertext) + decrypted = ecb_decrypt(key, encrypted, sbox=sbox) + self.assertSequenceEqual(decrypted, plaintext) + + def test_cryptopp(self): + """Test vectors from Crypto++ 5.6.2 + """ + sbox = "AppliedCryptography" + data = ( + (b"BE5EC2006CFF9DCF52354959F1FF0CBFE95061B5A648C10387069C25997C0672", b"0DF82802B741A292", b"07F9027DF7F7DF89"), + (b"B385272AC8D72A5A8B344BC80363AC4D09BF58F41F540624CBCB8FDCF55307D7", b"1354EE9C0A11CD4C", b"4FB50536F960A7B1"), + (b"AEE02F609A35660E4097E546FD3026B032CD107C7D459977ADF489BEF2652262", b"6693D492C4B0CC39", b"670034AC0FA811B5"), + (b"320E9D8422165D58911DFC7D8BBB1F81B0ECD924023BF94D9DF7DCF7801240E0", b"99E2D13080928D79", b"8118FF9D3B3CFE7D"), + (b"C9F703BBBFC63691BFA3B7B87EA8FD5E8E8EF384EF733F1A61AEF68C8FFA265F", b"D1E787749C72814C", b"A083826A790D3E0C"), + (b"728FEE32F04B4C654AD7F607D71C660C2C2670D7C999713233149A1C0C17A1F0", b"D4C05323A4F7A7B5", b"4D1F2E6B0D9DE2CE"), + (b"35FC96402209500FCFDEF5352D1ABB038FE33FC0D9D58512E56370B22BAA133B", b"8742D9A05F6A3AF6", b"2F3BB84879D11E52"), + (b"D416F630BE65B7FE150656183370E07018234EE5DA3D89C4CE9152A03E5BFB77", b"F86506DA04E41CB8", b"96F0A5C77A04F5CE"), + ) + for key, pt, ct in data: + key = hexdec(key) + pt = hexdec(pt) + ct = hexdec(ct) + self.assertSequenceEqual(ecb_encrypt(key, pt, sbox=sbox), ct) + + def test_cryptomanager(self): + """Test vector from http://cryptomanager.com/tv.html + """ + sbox = "id-GostR3411-94-TestParamSet" + key = hexdec(b"75713134B60FEC45A607BB83AA3746AF4FF99DA6D1B53B5B1B402A1BAA030D1B") + self.assertSequenceEqual( + ecb_encrypt(key, hexdec(b"1122334455667788"), sbox=sbox), + hexdec(b"03251E14F9D28ACB"), + ) + + +class CFBTest(TestCase): + def test_cryptomanager(self): + """Test vector from http://cryptomanager.com/tv.html + """ + key = hexdec(b"75713134B60FEC45A607BB83AA3746AF4FF99DA6D1B53B5B1B402A1BAA030D1B") + sbox = "id-GostR3411-94-TestParamSet" + self.assertSequenceEqual( + cfb_encrypt( + key, + hexdec(b"112233445566778899AABBCCDD800000"), + iv=hexdec(b"0102030405060708"), + sbox=sbox, + ), + hexdec(b"6EE84586DD2BCA0CAD3616940E164242"), + ) + self.assertSequenceEqual( + cfb_decrypt( + key, + hexdec(b"6EE84586DD2BCA0CAD3616940E164242"), + iv=hexdec(b"0102030405060708"), + sbox=sbox, + ), + hexdec(b"112233445566778899AABBCCDD800000"), + ) + + def test_steps(self): + """Check step-by-step operation manually + """ + key = urandom(KEYSIZE) + iv = urandom(BLOCKSIZE) + plaintext = urandom(20) + ciphertext = cfb_encrypt(key, plaintext, iv) + + # First full block + step = encrypt(DEFAULT_SBOX, key, block2ns(iv)) + step = strxor(plaintext[:8], ns2block(step)) + self.assertSequenceEqual(step, ciphertext[:8]) + + # Second full block + step = encrypt(DEFAULT_SBOX, key, block2ns(step)) + step = strxor(plaintext[8:16], ns2block(step)) + self.assertSequenceEqual(step, ciphertext[8:16]) + + # Third non-full block + step = encrypt(DEFAULT_SBOX, key, block2ns(step)) + step = strxor(plaintext[16:] + 4 * b"\x00", ns2block(step)) + self.assertSequenceEqual(step[:4], ciphertext[16:]) + + def test_random(self): + """Random data with various sizes + """ + key = urandom(KEYSIZE) + iv = urandom(BLOCKSIZE) + for size in (5, 8, 16, 120): + pt = urandom(size) + self.assertSequenceEqual( + cfb_decrypt(key, cfb_encrypt(key, pt, iv), iv), + pt, + ) + + +class CTRTest(TestCase): + def test_gcl(self): + """Test vectors from libgcl3 + """ + sbox = "id-Gost28147-89-TestParamSet" + key = hexdec(b"0475f6e05038fbfad2c7c390edb3ca3d1547124291ae1e8a2f79cd9ed2bcefbd") + plaintext = bytes(bytearray(( + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, + 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, + 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, + 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, + 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, + 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, + 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, + 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, + 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, + 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, + 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, + 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, + 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, + 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, + 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, + 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, + 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, + 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, + 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, + 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, + ))) + ciphertext = bytes(bytearray(( + 0x4a, 0x5e, 0x37, 0x6c, 0xa1, 0x12, 0xd3, 0x55, + 0x09, 0x13, 0x1a, 0x21, 0xac, 0xfb, 0xb2, 0x1e, + 0x8c, 0x24, 0x9b, 0x57, 0x20, 0x68, 0x46, 0xd5, + 0x23, 0x2a, 0x26, 0x35, 0x12, 0x56, 0x5c, 0x69, + 0x2a, 0x2f, 0xd1, 0xab, 0xbd, 0x45, 0xdc, 0x3a, + 0x1a, 0xa4, 0x57, 0x64, 0xd5, 0xe4, 0x69, 0x6d, + 0xb4, 0x8b, 0xf1, 0x54, 0x78, 0x3b, 0x10, 0x8f, + 0x7a, 0x4b, 0x32, 0xe0, 0xe8, 0x4c, 0xbf, 0x03, + 0x24, 0x37, 0x95, 0x6a, 0x55, 0xa8, 0xce, 0x6f, + 0x95, 0x62, 0x12, 0xf6, 0x79, 0xe6, 0xf0, 0x1b, + 0x86, 0xef, 0x36, 0x36, 0x05, 0xd8, 0x6f, 0x10, + 0xa1, 0x41, 0x05, 0x07, 0xf8, 0xfa, 0xa4, 0x0b, + 0x17, 0x2c, 0x71, 0xbc, 0x8b, 0xcb, 0xcf, 0x3d, + 0x74, 0x18, 0x32, 0x0b, 0x1c, 0xd2, 0x9e, 0x75, + 0xba, 0x3e, 0x61, 0xe1, 0x61, 0x96, 0xd0, 0xee, + 0x8f, 0xf2, 0x9a, 0x5e, 0xb7, 0x7a, 0x15, 0xaa, + 0x4e, 0x1e, 0x77, 0x7c, 0x99, 0xe1, 0x41, 0x13, + 0xf4, 0x60, 0x39, 0x46, 0x4c, 0x35, 0xde, 0x95, + 0xcc, 0x4f, 0xd5, 0xaf, 0xd1, 0x4d, 0x84, 0x1a, + 0x45, 0xc7, 0x2a, 0xf2, 0x2c, 0xc0, 0xb7, 0x94, + 0xa3, 0x08, 0xb9, 0x12, 0x96, 0xb5, 0x97, 0x99, + 0x3a, 0xb7, 0x0c, 0x14, 0x56, 0xb9, 0xcb, 0x49, + 0x44, 0xa9, 0x93, 0xa9, 0xfb, 0x19, 0x10, 0x8c, + 0x6a, 0x68, 0xe8, 0x7b, 0x06, 0x57, 0xf0, 0xef, + 0x88, 0x44, 0xa6, 0xd2, 0x98, 0xbe, 0xd4, 0x07, + 0x41, 0x37, 0x45, 0xa6, 0x71, 0x36, 0x76, 0x69, + 0x4b, 0x75, 0x15, 0x33, 0x90, 0x29, 0x6e, 0x33, + 0xcb, 0x96, 0x39, 0x78, 0x19, 0x2e, 0x96, 0xf3, + 0x49, 0x4c, 0x89, 0x3d, 0xa1, 0x86, 0x82, 0x00, + 0xce, 0xbd, 0x54, 0x29, 0x65, 0x00, 0x1d, 0x16, + 0x13, 0xc3, 0xfe, 0x1f, 0x8c, 0x55, 0x63, 0x09, + 0x1f, 0xcd, 0xd4, 0x28, 0xca, + ))) + iv = b"\x02\x01\x01\x01\x01\x01\x01\x01" + encrypted = cnt(key, plaintext, iv=iv, sbox=sbox) + self.assertSequenceEqual(encrypted, ciphertext) + decrypted = cnt(key, encrypted, iv=iv, sbox=sbox) + self.assertSequenceEqual(decrypted, plaintext) + + def test_gcl2(self): + """Test vectors 2 from libgcl3 + """ + sbox = "id-Gost28147-89-TestParamSet" + key = hexdec(b"fc7ad2886f455b50d29008fa622b57d5c65b3c637202025799cadf0768519e8a") + plaintext = bytes(bytearray(( + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, + 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, + ))) + ciphertext = bytes(bytearray(( + 0xd0, 0xbe, 0x60, 0x1a, 0x2c, 0xf1, 0x90, 0x26, + 0x9b, 0x7b, 0x23, 0xb4, 0xd2, 0xcc, 0xe1, 0x15, + 0xf6, 0x05, 0x57, 0x28, 0x88, 0x75, 0xeb, 0x1e, + 0xd3, 0x62, 0xdc, 0xda, 0x9b, 0x62, 0xee, 0x9a, + 0x57, 0x87, 0x8a, 0xf1, 0x82, 0x37, 0x9c, 0x7f, + 0x13, 0xcc, 0x55, 0x38, 0xb5, 0x63, 0x32, 0xc5, + 0x23, 0xa4, 0xcb, 0x7d, 0x51, + ))) + iv = BLOCKSIZE * b"\x00" + encrypted = cnt(key, plaintext, iv=iv, sbox=sbox) + self.assertSequenceEqual(encrypted, ciphertext) + decrypted = cnt(key, encrypted, iv=iv, sbox=sbox) + self.assertSequenceEqual(decrypted, plaintext) + + +class CBCTest(TestCase): + def test_pad_requirement(self): + key = KEYSIZE * b"x" + for s in (b"", b"foo", b"foobarbaz"): + with self.assertRaises(ValueError): + cbc_encrypt(key, s, pad=False) + with self.assertRaises(ValueError): + cbc_decrypt(key, s, pad=False) + + def test_passes(self): + iv = urandom(BLOCKSIZE) + key = KEYSIZE * b"x" + for pt in (b"foo", b"foobarba", b"foobarbaz", 16 * b"x"): + ct = cbc_encrypt(key, pt, iv) + dt = cbc_decrypt(key, ct) + self.assertSequenceEqual(pt, dt) + + def test_iv_existence_check(self): + key = KEYSIZE * b"x" + with self.assertRaises(ValueError): + cbc_decrypt(key, BLOCKSIZE * b"x") + iv = urandom(BLOCKSIZE) + cbc_decrypt(key, cbc_encrypt(key, BLOCKSIZE * b"x", iv)) + + def test_meshing(self): + pt = urandom(MESH_MAX_DATA * 3) + key = urandom(KEYSIZE) + ct = cbc_encrypt(key, pt) + dt = cbc_decrypt(key, ct) + self.assertSequenceEqual(pt, dt) + + +class CFBMeshingTest(TestCase): + def setUp(self): + self.key = urandom(KEYSIZE) + self.iv = urandom(BLOCKSIZE) + + def test_single(self): + pt = b"\x00" + ct = cfb_encrypt(self.key, pt, mesh=True) + dec = cfb_decrypt(self.key, ct, mesh=True) + self.assertSequenceEqual(pt, dec) + + def test_short(self): + pt = urandom(MESH_MAX_DATA - 1) + ct = cfb_encrypt(self.key, pt, mesh=True) + dec = cfb_decrypt(self.key, ct, mesh=True) + dec_plain = cfb_decrypt(self.key, ct) + self.assertSequenceEqual(pt, dec) + self.assertSequenceEqual(pt, dec_plain) + + def test_short_iv(self): + pt = urandom(MESH_MAX_DATA - 1) + ct = cfb_encrypt(self.key, pt, iv=self.iv, mesh=True) + dec = cfb_decrypt(self.key, ct, iv=self.iv, mesh=True) + dec_plain = cfb_decrypt(self.key, ct, iv=self.iv) + self.assertSequenceEqual(pt, dec) + self.assertSequenceEqual(pt, dec_plain) + + def test_longer_iv(self): + pt = urandom(MESH_MAX_DATA * 3) + ct = cfb_encrypt(self.key, pt, iv=self.iv, mesh=True) + dec = cfb_decrypt(self.key, ct, iv=self.iv, mesh=True) + dec_plain = cfb_decrypt(self.key, ct, iv=self.iv) + self.assertSequenceEqual(pt, dec) + self.assertNotEqual(pt, dec_plain) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost28147_mac.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost28147_mac.py new file mode 100644 index 0000000..ec1af3f --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost28147_mac.py @@ -0,0 +1,63 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from unittest import TestCase + +from pygost.gost28147_mac import MAC + + +class TestMAC(TestCase): + """Test vectors generated with libgcl3 library + """ + k = b"This is message\xFF length\x0032 bytes" + + def test_a(self): + self.assertSequenceEqual( + MAC(self.k, b"a").hexdigest(), + "bd5d3b5b2b7b57af", + ) + + def test_abc(self): + self.assertSequenceEqual( + MAC(self.k, b"abc").hexdigest(), + "28661e40805b1ff9", + ) + + def test_128U(self): + self.assertSequenceEqual( + MAC(self.k, 128 * b"U").hexdigest(), + "1a06d1bad74580ef", + ) + + def test_13x(self): + self.assertSequenceEqual( + MAC(self.k, 13 * b"x").hexdigest(), + "917ee1f1a668fbd3", + ) + + def test_parts(self): + m = MAC(self.k) + m.update(b"foo") + m.update(b"bar") + self.assertSequenceEqual(m.digest(), MAC(self.k, b"foobar").digest()) + + def test_copy(self): + m = MAC(self.k, b"foo") + c = m.copy() + m.update(b"barbaz") + c.update(b"bar") + c.update(b"baz") + self.assertSequenceEqual(m.digest(), c.digest()) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3410.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3410.py new file mode 100644 index 0000000..cd71535 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3410.py @@ -0,0 +1,495 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import urandom +from unittest import TestCase + +from pygost.gost3410 import CURVES +from pygost.gost3410 import GOST3410Curve +from pygost.gost3410 import prv_marshal +from pygost.gost3410 import prv_unmarshal +from pygost.gost3410 import public_key +from pygost.gost3410 import sign +from pygost.gost3410 import uv2xy +from pygost.gost3410 import verify +from pygost.gost3410 import xy2uv +from pygost.utils import bytes2long +from pygost.utils import hexdec +from pygost.utils import hexenc +from pygost.utils import long2bytes + + +class Test341001(TestCase): + def test_rfc(self): + """Test vector from :rfc:`5832` + """ + prv = bytes(bytearray(( + 0x7A, 0x92, 0x9A, 0xDE, 0x78, 0x9B, 0xB9, 0xBE, + 0x10, 0xED, 0x35, 0x9D, 0xD3, 0x9A, 0x72, 0xC1, + 0x1B, 0x60, 0x96, 0x1F, 0x49, 0x39, 0x7E, 0xEE, + 0x1D, 0x19, 0xCE, 0x98, 0x91, 0xEC, 0x3B, 0x28 + ))) + pub_x = bytes(bytearray(( + 0x7F, 0x2B, 0x49, 0xE2, 0x70, 0xDB, 0x6D, 0x90, + 0xD8, 0x59, 0x5B, 0xEC, 0x45, 0x8B, 0x50, 0xC5, + 0x85, 0x85, 0xBA, 0x1D, 0x4E, 0x9B, 0x78, 0x8F, + 0x66, 0x89, 0xDB, 0xD8, 0xE5, 0x6F, 0xD8, 0x0B + ))) + pub_y = bytes(bytearray(( + 0x26, 0xF1, 0xB4, 0x89, 0xD6, 0x70, 0x1D, 0xD1, + 0x85, 0xC8, 0x41, 0x3A, 0x97, 0x7B, 0x3C, 0xBB, + 0xAF, 0x64, 0xD1, 0xC5, 0x93, 0xD2, 0x66, 0x27, + 0xDF, 0xFB, 0x10, 0x1A, 0x87, 0xFF, 0x77, 0xDA + ))) + digest = bytes(bytearray(( + 0x2D, 0xFB, 0xC1, 0xB3, 0x72, 0xD8, 0x9A, 0x11, + 0x88, 0xC0, 0x9C, 0x52, 0xE0, 0xEE, 0xC6, 0x1F, + 0xCE, 0x52, 0x03, 0x2A, 0xB1, 0x02, 0x2E, 0x8E, + 0x67, 0xEC, 0xE6, 0x67, 0x2B, 0x04, 0x3E, 0xE5 + ))) + signature = bytes(bytearray(( + 0x41, 0xAA, 0x28, 0xD2, 0xF1, 0xAB, 0x14, 0x82, + 0x80, 0xCD, 0x9E, 0xD5, 0x6F, 0xED, 0xA4, 0x19, + 0x74, 0x05, 0x35, 0x54, 0xA4, 0x27, 0x67, 0xB8, + 0x3A, 0xD0, 0x43, 0xFD, 0x39, 0xDC, 0x04, 0x93, + 0x01, 0x45, 0x6C, 0x64, 0xBA, 0x46, 0x42, 0xA1, + 0x65, 0x3C, 0x23, 0x5A, 0x98, 0xA6, 0x02, 0x49, + 0xBC, 0xD6, 0xD3, 0xF7, 0x46, 0xB6, 0x31, 0xDF, + 0x92, 0x80, 0x14, 0xF6, 0xC5, 0xBF, 0x9C, 0x40 + ))) + prv = bytes2long(prv) + signature = signature[32:] + signature[:32] + + c = CURVES["id-GostR3410-2001-TestParamSet"] + pubX, pubY = public_key(c, prv) + self.assertSequenceEqual(long2bytes(pubX), pub_x) + self.assertSequenceEqual(long2bytes(pubY), pub_y) + s = sign(c, prv, digest) + self.assertTrue(verify(c, (pubX, pubY), digest, s)) + self.assertTrue(verify(c, (pubX, pubY), digest, signature)) + + def test_sequence(self): + c = CURVES["id-GostR3410-2001-TestParamSet"] + prv = prv_unmarshal(urandom(32)) + pubX, pubY = public_key(c, prv_unmarshal(prv_marshal(c, prv))) + for _ in range(20): + digest = urandom(32) + s = sign(c, prv, digest) + self.assertTrue(verify(c, (pubX, pubY), digest, s)) + + +class Test34102012(TestCase): + def test_1(self): + """Test vector from 34.10-2012 standard itself + """ + curve = CURVES["id-GostR3410-2001-TestParamSet"] + prv = bytes2long(hexdec("7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28")) + digest = hexdec("2DFBC1B372D89A1188C09C52E0EEC61FCE52032AB1022E8E67ECE6672B043EE5") + rand = hexdec("77105C9B20BCD3122823C8CF6FCC7B956DE33814E95B7FE64FED924594DCEAB3") + signature = sign(curve, prv, digest, rand) + r = "41aa28d2f1ab148280cd9ed56feda41974053554a42767b83ad043fd39dc0493" + s = "01456c64ba4642a1653c235a98a60249bcd6d3f746b631df928014f6c5bf9c40" + self.assertSequenceEqual(hexenc(signature), s + r) + + def test_2(self): + """Test vector from 34.10-2012 standard itself + """ + curve = GOST3410Curve( + p=3623986102229003635907788753683874306021320925534678605086546150450856166624002482588482022271496854025090823603058735163734263822371964987228582907372403, + q=3623986102229003635907788753683874306021320925534678605086546150450856166623969164898305032863068499961404079437936585455865192212970734808812618120619743, + a=7, + b=1518655069210828534508950034714043154928747527740206436194018823352809982443793732829756914785974674866041605397883677596626326413990136959047435811826396, + x=1928356944067022849399309401243137598997786635459507974357075491307766592685835441065557681003184874819658004903212332884252335830250729527632383493573274, + y=2288728693371972859970012155529478416353562327329506180314497425931102860301572814141997072271708807066593850650334152381857347798885864807605098724013854, + ) + prv = bytes2long(hexdec("0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4")) + digest = hexdec("3754F3CFACC9E0615C4F4A7C4D8DAB531B09B6F9C170C533A71D147035B0C5917184EE536593F4414339976C647C5D5A407ADEDB1D560C4FC6777D2972075B8C") + rand = hexdec("0359E7F4B1410FEACC570456C6801496946312120B39D019D455986E364F365886748ED7A44B3E794434006011842286212273A6D14CF70EA3AF71BB1AE679F1") + signature = sign(curve, prv, digest, rand) + r = "2f86fa60a081091a23dd795e1e3c689ee512a3c82ee0dcc2643c78eea8fcacd35492558486b20f1c9ec197c90699850260c93bcbcd9c5c3317e19344e173ae36" + s = "1081b394696ffe8e6585e7a9362d26b6325f56778aadbc081c0bfbe933d52ff5823ce288e8c4f362526080df7f70ce406a6eeb1f56919cb92a9853bde73e5b4a" + self.assertSequenceEqual(hexenc(signature), s + r) + + def test_gcl3(self): + """Test vector from libgcl3 + """ + p = bytes2long(bytes(bytearray(( + 0x45, 0x31, 0xAC, 0xD1, 0xFE, 0x00, 0x23, 0xC7, + 0x55, 0x0D, 0x26, 0x7B, 0x6B, 0x2F, 0xEE, 0x80, + 0x92, 0x2B, 0x14, 0xB2, 0xFF, 0xB9, 0x0F, 0x04, + 0xD4, 0xEB, 0x7C, 0x09, 0xB5, 0xD2, 0xD1, 0x5D, + 0xF1, 0xD8, 0x52, 0x74, 0x1A, 0xF4, 0x70, 0x4A, + 0x04, 0x58, 0x04, 0x7E, 0x80, 0xE4, 0x54, 0x6D, + 0x35, 0xB8, 0x33, 0x6F, 0xAC, 0x22, 0x4D, 0xD8, + 0x16, 0x64, 0xBB, 0xF5, 0x28, 0xBE, 0x63, 0x73, + )))) + q = bytes2long(bytes(bytearray(( + 0x45, 0x31, 0xAC, 0xD1, 0xFE, 0x00, 0x23, 0xC7, + 0x55, 0x0D, 0x26, 0x7B, 0x6B, 0x2F, 0xEE, 0x80, + 0x92, 0x2B, 0x14, 0xB2, 0xFF, 0xB9, 0x0F, 0x04, + 0xD4, 0xEB, 0x7C, 0x09, 0xB5, 0xD2, 0xD1, 0x5D, + 0xA8, 0x2F, 0x2D, 0x7E, 0xCB, 0x1D, 0xBA, 0xC7, + 0x19, 0x90, 0x5C, 0x5E, 0xEC, 0xC4, 0x23, 0xF1, + 0xD8, 0x6E, 0x25, 0xED, 0xBE, 0x23, 0xC5, 0x95, + 0xD6, 0x44, 0xAA, 0xF1, 0x87, 0xE6, 0xE6, 0xDF, + )))) + a = bytes2long(bytes(bytearray(( + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + )))) + b = bytes2long(bytes(bytearray(( + 0x1C, 0xFF, 0x08, 0x06, 0xA3, 0x11, 0x16, 0xDA, + 0x29, 0xD8, 0xCF, 0xA5, 0x4E, 0x57, 0xEB, 0x74, + 0x8B, 0xC5, 0xF3, 0x77, 0xE4, 0x94, 0x00, 0xFD, + 0xD7, 0x88, 0xB6, 0x49, 0xEC, 0xA1, 0xAC, 0x43, + 0x61, 0x83, 0x40, 0x13, 0xB2, 0xAD, 0x73, 0x22, + 0x48, 0x0A, 0x89, 0xCA, 0x58, 0xE0, 0xCF, 0x74, + 0xBC, 0x9E, 0x54, 0x0C, 0x2A, 0xDD, 0x68, 0x97, + 0xFA, 0xD0, 0xA3, 0x08, 0x4F, 0x30, 0x2A, 0xDC, + )))) + x = bytes2long(bytes(bytearray(( + 0x24, 0xD1, 0x9C, 0xC6, 0x45, 0x72, 0xEE, 0x30, + 0xF3, 0x96, 0xBF, 0x6E, 0xBB, 0xFD, 0x7A, 0x6C, + 0x52, 0x13, 0xB3, 0xB3, 0xD7, 0x05, 0x7C, 0xC8, + 0x25, 0xF9, 0x10, 0x93, 0xA6, 0x8C, 0xD7, 0x62, + 0xFD, 0x60, 0x61, 0x12, 0x62, 0xCD, 0x83, 0x8D, + 0xC6, 0xB6, 0x0A, 0xA7, 0xEE, 0xE8, 0x04, 0xE2, + 0x8B, 0xC8, 0x49, 0x97, 0x7F, 0xAC, 0x33, 0xB4, + 0xB5, 0x30, 0xF1, 0xB1, 0x20, 0x24, 0x8A, 0x9A, + )))) + y = bytes2long(bytes(bytearray(( + 0x2B, 0xB3, 0x12, 0xA4, 0x3B, 0xD2, 0xCE, 0x6E, + 0x0D, 0x02, 0x06, 0x13, 0xC8, 0x57, 0xAC, 0xDD, + 0xCF, 0xBF, 0x06, 0x1E, 0x91, 0xE5, 0xF2, 0xC3, + 0xF3, 0x24, 0x47, 0xC2, 0x59, 0xF3, 0x9B, 0x2C, + 0x83, 0xAB, 0x15, 0x6D, 0x77, 0xF1, 0x49, 0x6B, + 0xF7, 0xEB, 0x33, 0x51, 0xE1, 0xEE, 0x4E, 0x43, + 0xDC, 0x1A, 0x18, 0xB9, 0x1B, 0x24, 0x64, 0x0B, + 0x6D, 0xBB, 0x92, 0xCB, 0x1A, 0xDD, 0x37, 0x1E, + )))) + prv = bytes(bytearray(( + 0x0B, 0xA6, 0x04, 0x8A, 0xAD, 0xAE, 0x24, 0x1B, + 0xA4, 0x09, 0x36, 0xD4, 0x77, 0x56, 0xD7, 0xC9, + 0x30, 0x91, 0xA0, 0xE8, 0x51, 0x46, 0x69, 0x70, + 0x0E, 0xE7, 0x50, 0x8E, 0x50, 0x8B, 0x10, 0x20, + 0x72, 0xE8, 0x12, 0x3B, 0x22, 0x00, 0xA0, 0x56, + 0x33, 0x22, 0xDA, 0xD2, 0x82, 0x7E, 0x27, 0x14, + 0xA2, 0x63, 0x6B, 0x7B, 0xFD, 0x18, 0xAA, 0xDF, + 0xC6, 0x29, 0x67, 0x82, 0x1F, 0xA1, 0x8D, 0xD4, + ))) + pub_x = bytes(bytearray(( + 0x11, 0x5D, 0xC5, 0xBC, 0x96, 0x76, 0x0C, 0x7B, + 0x48, 0x59, 0x8D, 0x8A, 0xB9, 0xE7, 0x40, 0xD4, + 0xC4, 0xA8, 0x5A, 0x65, 0xBE, 0x33, 0xC1, 0x81, + 0x5B, 0x5C, 0x32, 0x0C, 0x85, 0x46, 0x21, 0xDD, + 0x5A, 0x51, 0x58, 0x56, 0xD1, 0x33, 0x14, 0xAF, + 0x69, 0xBC, 0x5B, 0x92, 0x4C, 0x8B, 0x4D, 0xDF, + 0xF7, 0x5C, 0x45, 0x41, 0x5C, 0x1D, 0x9D, 0xD9, + 0xDD, 0x33, 0x61, 0x2C, 0xD5, 0x30, 0xEF, 0xE1, + ))) + pub_y = bytes(bytearray(( + 0x37, 0xC7, 0xC9, 0x0C, 0xD4, 0x0B, 0x0F, 0x56, + 0x21, 0xDC, 0x3A, 0xC1, 0xB7, 0x51, 0xCF, 0xA0, + 0xE2, 0x63, 0x4F, 0xA0, 0x50, 0x3B, 0x3D, 0x52, + 0x63, 0x9F, 0x5D, 0x7F, 0xB7, 0x2A, 0xFD, 0x61, + 0xEA, 0x19, 0x94, 0x41, 0xD9, 0x43, 0xFF, 0xE7, + 0xF0, 0xC7, 0x0A, 0x27, 0x59, 0xA3, 0xCD, 0xB8, + 0x4C, 0x11, 0x4E, 0x1F, 0x93, 0x39, 0xFD, 0xF2, + 0x7F, 0x35, 0xEC, 0xA9, 0x36, 0x77, 0xBE, 0xEC, + ))) + digest = bytes(bytearray(( + 0x37, 0x54, 0xF3, 0xCF, 0xAC, 0xC9, 0xE0, 0x61, + 0x5C, 0x4F, 0x4A, 0x7C, 0x4D, 0x8D, 0xAB, 0x53, + 0x1B, 0x09, 0xB6, 0xF9, 0xC1, 0x70, 0xC5, 0x33, + 0xA7, 0x1D, 0x14, 0x70, 0x35, 0xB0, 0xC5, 0x91, + 0x71, 0x84, 0xEE, 0x53, 0x65, 0x93, 0xF4, 0x41, + 0x43, 0x39, 0x97, 0x6C, 0x64, 0x7C, 0x5D, 0x5A, + 0x40, 0x7A, 0xDE, 0xDB, 0x1D, 0x56, 0x0C, 0x4F, + 0xC6, 0x77, 0x7D, 0x29, 0x72, 0x07, 0x5B, 0x8C, + ))) + signature = bytes(bytearray(( + 0x2F, 0x86, 0xFA, 0x60, 0xA0, 0x81, 0x09, 0x1A, + 0x23, 0xDD, 0x79, 0x5E, 0x1E, 0x3C, 0x68, 0x9E, + 0xE5, 0x12, 0xA3, 0xC8, 0x2E, 0xE0, 0xDC, 0xC2, + 0x64, 0x3C, 0x78, 0xEE, 0xA8, 0xFC, 0xAC, 0xD3, + 0x54, 0x92, 0x55, 0x84, 0x86, 0xB2, 0x0F, 0x1C, + 0x9E, 0xC1, 0x97, 0xC9, 0x06, 0x99, 0x85, 0x02, + 0x60, 0xC9, 0x3B, 0xCB, 0xCD, 0x9C, 0x5C, 0x33, + 0x17, 0xE1, 0x93, 0x44, 0xE1, 0x73, 0xAE, 0x36, + 0x10, 0x81, 0xB3, 0x94, 0x69, 0x6F, 0xFE, 0x8E, + 0x65, 0x85, 0xE7, 0xA9, 0x36, 0x2D, 0x26, 0xB6, + 0x32, 0x5F, 0x56, 0x77, 0x8A, 0xAD, 0xBC, 0x08, + 0x1C, 0x0B, 0xFB, 0xE9, 0x33, 0xD5, 0x2F, 0xF5, + 0x82, 0x3C, 0xE2, 0x88, 0xE8, 0xC4, 0xF3, 0x62, + 0x52, 0x60, 0x80, 0xDF, 0x7F, 0x70, 0xCE, 0x40, + 0x6A, 0x6E, 0xEB, 0x1F, 0x56, 0x91, 0x9C, 0xB9, + 0x2A, 0x98, 0x53, 0xBD, 0xE7, 0x3E, 0x5B, 0x4A, + ))) + prv = bytes2long(prv) + signature = signature[64:] + signature[:64] + c = GOST3410Curve(p, q, a, b, x, y) + pubX, pubY = public_key(c, prv) + self.assertSequenceEqual(long2bytes(pubX), pub_x) + self.assertSequenceEqual(long2bytes(pubY), pub_y) + s = sign(c, prv, digest) + self.assertTrue(verify(c, (pubX, pubY), digest, s)) + self.assertTrue(verify(c, (pubX, pubY), digest, signature)) + + def test_sequence(self): + c = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + prv = bytes2long(urandom(64)) + pubX, pubY = public_key(c, prv_unmarshal(prv_marshal(c, prv))) + for _ in range(20): + digest = urandom(64) + s = sign(c, prv, digest) + self.assertTrue(verify(c, (pubX, pubY), digest, s)) + self.assertNotIn(b"\x00" * 8, s) + + +class TestUVXYConversion(TestCase): + """Twisted Edwards to Weierstrass coordinates conversion and vice versa + """ + def test_curve1(self): + c = CURVES["id-tc26-gost-3410-2012-256-paramSetA"] + u, v = (0x0D, bytes2long(hexdec("60CA1E32AA475B348488C38FAB07649CE7EF8DBE87F22E81F92B2592DBA300E7"))) + self.assertEqual(uv2xy(c, u, v), (c.x, c.y)) + self.assertEqual(xy2uv(c, c.x, c.y), (u, v)) + + def test_curve2(self): + c = CURVES["id-tc26-gost-3410-2012-512-paramSetC"] + u, v = (0x12, bytes2long(hexdec("469AF79D1FB1F5E16B99592B77A01E2A0FDFB0D01794368D9A56117F7B38669522DD4B650CF789EEBF068C5D139732F0905622C04B2BAAE7600303EE73001A3D"))) + self.assertEqual(uv2xy(c, u, v), (c.x, c.y)) + self.assertEqual(xy2uv(c, c.x, c.y), (u, v)) + + +class Test34102012SESPAKE(TestCase): + """Test vectors for multiplication from :rfc:`8133` + """ + def test_curve1(self): + c = CURVES["id-GostR3410-2001-CryptoPro-A-ParamSet"] + q_ind = ( + 0xA69D51CAF1A309FA9E9B66187759B0174C274E080356F23CFCBFE84D396AD7BB, + 0x5D26F29ECC2E9AC0404DCF7986FA55FE94986362170F54B9616426A659786DAC, + ) + self.assertEqual( + c.exp(bytes2long(hexdec( + "BD04673F7149B18E98155BD1E2724E71D0099AA25174F792D3326C6F18127067" + )[::-1]), x=q_ind[0], y=q_ind[1]), + ( + 0x59495655D1E7C7424C622485F575CCF121F3122D274101E8AB734CC9C9A9B45E, + 0x48D1C311D33C9B701F3B03618562A4A07A044E3AF31E3999E67B487778B53C62, + ) + ) + self.assertEqual( + c.exp(0x1F2538097D5A031FA68BBB43C84D12B3DE47B7061C0D5E24993E0C873CDBA6B3), + ( + 0xBBC77CF42DC1E62D06227935379B4AA4D14FEA4F565DDF4CB4FA4D31579F9676, + 0x8E16604A4AFDF28246684D4996274781F6CB80ABBBA1414C1513EC988509DABF, + ) + ) + self.assertEqual( + c.exp(0xDC497D9EF6324912FD367840EE509A2032AEDB1C0A890D133B45F596FCCBD45D), + ( + 0x6097341C1BE388E83E7CA2DF47FAB86E2271FD942E5B7B2EB2409E49F742BC29, + 0xC81AA48BDB4CA6FA0EF18B9788AE25FE30857AA681B3942217F9FED151BAB7D0, + ), + ) + + def test_curve2(self): + c = CURVES["id-GostR3410-2001-CryptoPro-B-ParamSet"] + q_ind = ( + 0x3D715A874A4B17CB3B517893A9794A2B36C89D2FFC693F01EE4CC27E7F49E399, + 0x1C5A641FCF7CE7E87CDF8CEA38F3DB3096EACE2FAD158384B53953365F4FE7FE, + ) + self.assertEqual( + c.exp(bytes2long(hexdec( + "BD04673F7149B18E98155BD1E2724E71D0099AA25174F792D3326C6F18127067" + )[::-1]), x=q_ind[0], y=q_ind[1]), + ( + 0x6DC2AE26BC691FCA5A73D9C452790D15E34BA5404D92955B914C8D2662ABB985, + 0x3B02AAA9DD65AE30C335CED12F3154BBAC059F66B088306747453EDF6E5DB077, + ) + ) + self.assertEqual( + c.exp(0x499D72B90299CAB0DA1F8BE19D9122F622A13B32B730C46BD0664044F2144FAD), + ( + 0x61D6F916DB717222D74877F179F7EBEF7CD4D24D8C1F523C048E34A1DF30F8DD, + 0x3EC48863049CFCFE662904082E78503F4973A4E105E2F1B18C69A5E7FB209000, + ) + ) + self.assertEqual( + c.exp(0x0F69FF614957EF83668EDC2D7ED614BE76F7B253DB23C5CC9C52BF7DF8F4669D), + ( + 0x33BC6F7E9C0BA10CFB2B72546C327171295508EA97F8C8BA9F890F2478AB4D6C, + 0x75D57B396C396F492F057E9222CCC686437A2AAD464E452EF426FC8EEED1A4A6, + ), + ) + + def test_curve3(self): + c = CURVES["id-GostR3410-2001-CryptoPro-C-ParamSet"] + q_ind = ( + 0x1E36383E43BB6CFA2917167D71B7B5DD3D6D462B43D7C64282AE67DFBEC2559D, + 0x137478A9F721C73932EA06B45CF72E37EB78A63F29A542E563C614650C8B6399, + ) + self.assertEqual( + c.exp(bytes2long(hexdec( + "BD04673F7149B18E98155BD1E2724E71D0099AA25174F792D3326C6F18127067" + )[::-1]), x=q_ind[0], y=q_ind[1]), + ( + 0x945821DAF91E158B839939630655A3B21FF3E146D27041E86C05650EB3B46B59, + 0x3A0C2816AC97421FA0E879605F17F0C9C3EB734CFF196937F6284438D70BDC48, + ) + ) + self.assertEqual( + c.exp(0x3A54AC3F19AD9D0B1EAC8ACDCEA70E581F1DAC33D13FEAFD81E762378639C1A8), + ( + 0x96B7F09C94D297C257A7DA48364C0076E59E48D221CBA604AE111CA3933B446A, + 0x54E4953D86B77ECCEB578500931E822300F7E091F79592CA202A020D762C34A6, + ) + ) + self.assertEqual( + c.exp(0x448781782BF7C0E52A1DD9E6758FD3482D90D3CFCCF42232CF357E59A4D49FD4), + ( + 0x4B9C0AB55A938121F282F48A2CC4396EB16E7E0068B495B0C1DD4667786A3EB7, + 0x223460AA8E09383E9DF9844C5A0F2766484738E5B30128A171B69A77D9509B96, + ), + ) + + def test_curve4(self): + c = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + q_ind = ( + 0x2A17F8833A32795327478871B5C5E88AEFB91126C64B4B8327289BEA62559425D18198F133F400874328B220C74497CD240586CB249E158532CB8090776CD61C, + 0x728F0C4A73B48DA41CE928358FAD26B47A6E094E9362BAE82559F83CDDC4EC3A4676BD3707EDEAF4CD85E99695C64C241EDC622BE87DC0CF87F51F4367F723C5, + ) + self.assertEqual( + c.exp(bytes2long(hexdec( + "BD04673F7149B18E98155BD1E2724E71D0099AA25174F792D3326C6F181270671C6213E3930EFDDA26451792C6208122EE60D200520D695DFD9F5F0FD5ABA702" + )[::-1]), x=q_ind[0], y=q_ind[1]), + ( + 0x0C0AB53D0E0A9C607CAD758F558915A0A7DC5DC87B45E9A58FDDF30EC3385960283E030CD322D9E46B070637785FD49D2CD711F46807A24C40AF9A42C8E2D740, + 0xDF93A8012B86D3A3D4F8A4D487DA15FC739EB31B20B3B0E8C8C032AAF8072C6337CF7D5B404719E5B4407C41D9A3216A08CA69C271484E9ED72B8AAA52E28B8B, + ) + ) + self.assertEqual( + c.exp(0x3CE54325DB52FE798824AEAD11BB16FA766857D04A4AF7D468672F16D90E7396046A46F815693E85B1CE5464DA9270181F82333B0715057BBE8D61D400505F0E), + ( + 0xB93093EB0FCC463239B7DF276E09E592FCFC9B635504EA4531655D76A0A3078E2B4E51CFE2FA400CC5DE9FBE369DB204B3E8ED7EDD85EE5CCA654C1AED70E396, + 0x809770B8D910EA30BD2FA89736E91DC31815D2D9B31128077EEDC371E9F69466F497DC64DD5B1FADC587F860EE256109138C4A9CD96B628E65A8F590520FC882, + ) + ) + self.assertEqual( + c.exp(0xB5C286A79AA8E97EC0E19BC1959A1D15F12F8C97870BA9D68CC12811A56A3BB11440610825796A49D468CDC9C2D02D76598A27973D5960C5F50BCE28D8D345F4), + ( + 0x238B38644E440452A99FA6B93D9FD7DA0CB83C32D3C1E3CFE5DF5C3EB0F9DB91E588DAEDC849EA2FB867AE855A21B4077353C0794716A6480995113D8C20C7AF, + 0xB2273D5734C1897F8D15A7008B862938C8C74CA7E877423D95243EB7EBD02FD2C456CF9FC956F078A59AA86F19DD1075E5167E4ED35208718EA93161C530ED14, + ), + ) + + def test_curve5(self): + c = CURVES["id-tc26-gost-3410-12-512-paramSetB"] + q_ind = ( + 0x7E1FAE8285E035BEC244BEF2D0E5EBF436633CF50E55231DEA9C9CF21D4C8C33DF85D4305DE92971F0A4B4C07E00D87BDBC720EB66E49079285AAF12E0171149, + 0x2CC89998B875D4463805BA0D858A196592DB20AB161558FF2F4EF7A85725D20953967AE621AFDEAE89BB77C83A2528EF6FCE02F68BDA4679D7F2704947DBC408, + ) + self.assertEqual( + c.exp(bytes2long(hexdec( + "BD04673F7149B18E98155BD1E2724E71D0099AA25174F792D3326C6F181270671C6213E3930EFDDA26451792C6208122EE60D200520D695DFD9F5F0FD5ABA702" + )[::-1]), x=q_ind[0], y=q_ind[1]), + ( + 0x7D03E65B8050D1E12CBB601A17B9273B0E728F5021CD47C8A4DD822E4627BA5F9C696286A2CDDA9A065509866B4DEDEDC4A118409604AD549F87A60AFA621161, + 0x16037DAD45421EC50B00D50BDC6AC3B85348BC1D3A2F85DB27C3373580FEF87C2C743B7ED30F22BE22958044E716F93A61CA3213A361A2797A16A3AE62957377, + ) + ) + self.assertEqual( + c.exp(0x715E893FA639BF341296E0623E6D29DADF26B163C278767A7982A989462A3863FE12AEF8BD403D59C4DC4720570D4163DB0805C7C10C4E818F9CB785B04B9997), + ( + 0x10C479EA1C04D3C2C02B0576A9C42D96226FF033C1191436777F66916030D87D02FB93738ED7669D07619FFCE7C1F3C4DB5E5DF49E2186D6FA1E2EB5767602B9, + 0x039F6044191404E707F26D59D979136A831CCE43E1C5F0600D1DDF8F39D0CA3D52FBD943BF04DDCED1AA2CE8F5EBD7487ACDEF239C07D015084D796784F35436, + ) + ) + self.assertEqual( + c.exp(0x30FA8C2B4146C2DBBE82BED04D7378877E8C06753BD0A0FF71EBF2BEFE8DA8F3DC0836468E2CE7C5C961281B6505140F8407413F03C2CB1D201EA1286CE30E6D), + ( + 0x34C0149E7BB91AE377B02573FCC48AF7BFB7B16DEB8F9CE870F384688E3241A3A868588CC0EF4364CCA67D17E3260CD82485C202ADC76F895D5DF673B1788E67, + 0x608E944929BD643569ED5189DB871453F13333A1EAF82B2FE1BE8100E775F13DD9925BD317B63BFAF05024D4A738852332B64501195C1B2EF789E34F23DDAFC5, + ), + ) + + def test_curve6(self): + c = CURVES["id-tc26-gost-3410-2012-256-paramSetA"] + q_ind = ( + 0xB51ADF93A40AB15792164FAD3352F95B66369EB2A4EF5EFAE32829320363350E, + 0x74A358CC08593612F5955D249C96AFB7E8B0BB6D8BD2BBE491046650D822BE18, + ) + self.assertEqual( + c.exp(bytes2long(hexdec( + "BD04673F7149B18E98155BD1E2724E71D0099AA25174F792D3326C6F18127067" + )[::-1]), x=q_ind[0], y=q_ind[1]), + ( + 0xDBF99827078956812FA48C6E695DF589DEF1D18A2D4D35A96D75BF6854237629, + 0x9FDDD48BFBC57BEE1DA0CFF282884F284D471B388893C48F5ECB02FC18D67589, + ) + ) + self.assertEqual( + c.exp(0x147B72F6684FB8FD1B418A899F7DBECAF5FCE60B13685BAA95328654A7F0707F), + ( + 0x33FBAC14EAE538275A769417829C431BD9FA622B6F02427EF55BD60EE6BC2888, + 0x22F2EBCF960A82E6CDB4042D3DDDA511B2FBA925383C2273D952EA2D406EAE46, + ) + ) + self.assertEqual( + c.exp(0x30D5CFADAA0E31B405E6734C03EC4C5DF0F02F4BA25C9A3B320EE6453567B4CB), + ( + 0x2B2D89FAB735433970564F2F28CFA1B57D640CB902BC6334A538F44155022CB2, + 0x10EF6A82EEF1E70F942AA81D6B4CE5DEC0DDB9447512962874870E6F2849A96F, + ), + ) + + def test_curve7(self): + c = CURVES["id-tc26-gost-3410-2012-512-paramSetC"] + q_ind = ( + 0x489C91784E02E98F19A803ABCA319917F37689E5A18965251CE2FF4E8D8B298F5BA7470F9E0E713487F96F4A8397B3D09A270C9D367EB5E0E6561ADEEB51581D, + 0x684EA885ACA64EAF1B3FEE36C0852A3BE3BD8011B0EF18E203FF87028D6EB5DB2C144A0DCC71276542BFD72CA2A43FA4F4939DA66D9A60793C704A8C94E16F18, + ) + self.assertEqual( + c.exp(bytes2long(hexdec( + "BD04673F7149B18E98155BD1E2724E71D0099AA25174F792D3326C6F181270671C6213E3930EFDDA26451792C6208122EE60D200520D695DFD9F5F0FD5ABA702" + )[::-1]), x=q_ind[0], y=q_ind[1]), + ( + 0x0185AE6271A81BB7F236A955F7CAA26FB63849813C0287D96C83A15AE6B6A86467AB13B6D88CE8CD7DC2E5B97FF5F28FAC2C108F2A3CF3DB5515C9E6D7D210E8, + 0xED0220F92EF771A71C64ECC77986DB7C03D37B3E2AB3E83F32CE5E074A762EC08253C9E2102B87532661275C4B1D16D2789CDABC58ACFDF7318DE70AB64F09B8, + ) + ) + self.assertEqual( + c.exp(0x332F930421D14CFE260042159F18E49FD5A54167E94108AD80B1DE60B13DE7999A34D611E63F3F870E5110247DF8EC7466E648ACF385E52CCB889ABF491EDFF0), + ( + 0x561655966D52952E805574F4281F1ED3A2D498932B00CBA9DECB42837F09835BFFBFE2D84D6B6B242FE7B57F92E1A6F2413E12DDD6383E4437E13D72693469AD, + 0xF6B18328B2715BD7F4178615273A36135BC0BF62F7D8BB9F080164AD36470AD03660F51806C64C6691BADEF30F793720F8E3FEAED631D6A54A4C372DCBF80E82, + ) + ) + self.assertEqual( + c.exp(0x38481771E7D054F96212686B613881880BD8A6C89DDBC656178F014D2C093432A033EE10415F13A160D44C2AD61E6E2E05A7F7EC286BCEA3EA4D4D53F8634FA2), + ( + 0xB7C5818687083433BC1AFF61CB5CA79E38232025E0C1F123B8651E62173CE6873F3E6FFE7281C2E45F4F524F66B0C263616ED08FD210AC4355CA3292B51D71C3, + 0x497F14205DBDC89BDDAF50520ED3B1429AD30777310186BE5E68070F016A44E0C766DB08E8AC23FBDFDE6D675AA4DF591EB18BA0D348DF7AA40973A2F1DCFA55, + ), + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3410_vko.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3410_vko.py new file mode 100644 index 0000000..a8e298e --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3410_vko.py @@ -0,0 +1,125 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import urandom +from unittest import TestCase + +from pygost.gost3410 import CURVES +from pygost.gost3410 import prv_unmarshal +from pygost.gost3410 import pub_unmarshal +from pygost.gost3410 import public_key +from pygost.gost3410_vko import kek_34102001 +from pygost.gost3410_vko import kek_34102012256 +from pygost.gost3410_vko import kek_34102012512 +from pygost.gost3410_vko import ukm_unmarshal +from pygost.utils import bytes2long +from pygost.utils import hexdec + + +class TestVKO34102001(TestCase): + def test_vector(self): + curve = CURVES["id-GostR3410-2001-TestParamSet"] + ukm = ukm_unmarshal(hexdec("5172be25f852a233")) + prv1 = prv_unmarshal(hexdec("1df129e43dab345b68f6a852f4162dc69f36b2f84717d08755cc5c44150bf928")) + prv2 = prv_unmarshal(hexdec("5b9356c6474f913f1e83885ea0edd5df1a43fd9d799d219093241157ac9ed473")) + kek = hexdec("ee4618a0dbb10cb31777b4b86a53d9e7ef6cb3e400101410f0c0f2af46c494a6") + pub1 = public_key(curve, prv1) + pub2 = public_key(curve, prv2) + self.assertSequenceEqual(kek_34102001(curve, prv1, pub2, ukm), kek) + self.assertSequenceEqual(kek_34102001(curve, prv2, pub1, ukm), kek) + + def test_sequence(self): + curve = CURVES["id-GostR3410-2001-TestParamSet"] + for _ in range(10): + ukm = ukm_unmarshal(urandom(8)) + prv1 = bytes2long(urandom(32)) + prv2 = bytes2long(urandom(32)) + pub1 = public_key(curve, prv1) + pub2 = public_key(curve, prv2) + kek1 = kek_34102001(curve, prv1, pub2, ukm) + kek2 = kek_34102001(curve, prv2, pub1, ukm) + self.assertSequenceEqual(kek1, kek2) + kek1 = kek_34102001(curve, prv1, pub1, ukm) + kek2 = kek_34102001(curve, prv2, pub2, ukm) + self.assertNotEqual(kek1, kek2) + + +class TestVKO34102012256(TestCase): + """RFC 7836 + """ + def test_vector(self): + curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + ukm = ukm_unmarshal(hexdec("1d80603c8544c727")) + prvA = prv_unmarshal(hexdec("c990ecd972fce84ec4db022778f50fcac726f46708384b8d458304962d7147f8c2db41cef22c90b102f2968404f9b9be6d47c79692d81826b32b8daca43cb667")) + pubA = pub_unmarshal(hexdec("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a")) + prvB = prv_unmarshal(hexdec("48c859f7b6f11585887cc05ec6ef1390cfea739b1a18c0d4662293ef63b79e3b8014070b44918590b4b996acfea4edfbbbcccc8c06edd8bf5bda92a51392d0db")) + pubB = pub_unmarshal(hexdec("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79")) + vko = hexdec("c9a9a77320e2cc559ed72dce6f47e2192ccea95fa648670582c054c0ef36c221") + self.assertSequenceEqual(kek_34102012256(curve, prvA, pubB, ukm), vko) + self.assertSequenceEqual(kek_34102012256(curve, prvB, pubA, ukm), vko) + + def test_sequence(self): + curve = CURVES["id-tc26-gost-3410-2012-256-paramSetA"] + for _ in range(10): + ukm = ukm_unmarshal(urandom(8)) + prv1 = bytes2long(urandom(32)) + prv2 = bytes2long(urandom(32)) + pub1 = public_key(curve, prv1) + pub2 = public_key(curve, prv2) + kek1 = kek_34102012256(curve, prv1, pub2, ukm) + kek2 = kek_34102012256(curve, prv2, pub1, ukm) + self.assertSequenceEqual(kek1, kek2) + kek1 = kek_34102012256(curve, prv1, pub1, ukm) + kek2 = kek_34102012256(curve, prv2, pub2, ukm) + self.assertNotEqual(kek1, kek2) + + def test_pub_is_not_on_curve(self): + with self.assertRaises(ValueError): + kek_34102012256( + CURVES["id-tc26-gost-3410-2012-256-paramSetA"], + bytes2long(urandom(32)), + pub_unmarshal(urandom(64)), + ) + + +class TestVKO34102012512(TestCase): + """RFC 7836 + """ + def test_vector(self): + curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + ukm = ukm_unmarshal(hexdec("1d80603c8544c727")) + prvA = prv_unmarshal(hexdec("c990ecd972fce84ec4db022778f50fcac726f46708384b8d458304962d7147f8c2db41cef22c90b102f2968404f9b9be6d47c79692d81826b32b8daca43cb667")) + pubA = pub_unmarshal(hexdec("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a")) + prvB = prv_unmarshal(hexdec("48c859f7b6f11585887cc05ec6ef1390cfea739b1a18c0d4662293ef63b79e3b8014070b44918590b4b996acfea4edfbbbcccc8c06edd8bf5bda92a51392d0db")) + pubB = pub_unmarshal(hexdec("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79")) + vko = hexdec("79f002a96940ce7bde3259a52e015297adaad84597a0d205b50e3e1719f97bfa7ee1d2661fa9979a5aa235b558a7e6d9f88f982dd63fc35a8ec0dd5e242d3bdf") + self.assertSequenceEqual(kek_34102012512(curve, prvA, pubB, ukm), vko) + self.assertSequenceEqual(kek_34102012512(curve, prvB, pubA, ukm), vko) + + def test_sequence(self): + curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"] + for _ in range(10): + ukm = ukm_unmarshal(urandom(8)) + prv1 = bytes2long(urandom(32)) + prv2 = bytes2long(urandom(32)) + pub1 = public_key(curve, prv1) + pub2 = public_key(curve, prv2) + kek1 = kek_34102012512(curve, prv1, pub2, ukm) + kek2 = kek_34102012512(curve, prv2, pub1, ukm) + self.assertSequenceEqual(kek1, kek2) + kek1 = kek_34102012512(curve, prv1, pub1, ukm) + kek2 = kek_34102012512(curve, prv2, pub2, ukm) + self.assertNotEqual(kek1, kek2) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost34112012.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost34112012.py new file mode 100644 index 0000000..c7c2df9 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost34112012.py @@ -0,0 +1,159 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import urandom +from random import randint +from unittest import skip +from unittest import TestCase +import hmac + +from pygost import gost34112012256 +from pygost import gost34112012512 +from pygost.gost34112012256 import GOST34112012256 +from pygost.gost34112012512 import GOST34112012512 +from pygost.gost34112012512 import pbkdf2 +from pygost.utils import hexdec +from pygost.utils import hexenc + + +class TestCopy(TestCase): + def runTest(self): + m = GOST34112012256() + c = m.copy() + m.update(b"foobar") + c.update(b"foo") + c.update(b"bar") + self.assertSequenceEqual(m.digest(), c.digest()) + + +class TestSymmetric(TestCase): + def runTest(self): + chunks = [] + for _ in range(randint(1, 10)): + chunks.append(urandom(randint(20, 80))) + m = GOST34112012256() + for chunk in chunks: + m.update(chunk) + self.assertSequenceEqual( + m.hexdigest(), + GOST34112012256(b"".join(chunks)).hexdigest(), + ) + + +class TestHMAC(TestCase): + """RFC 7836 + """ + def test_256(self): + for digestmod in (GOST34112012256, gost34112012256): + self.assertSequenceEqual( + hmac.new( + key=hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + msg=hexdec("0126bdb87800af214341456563780100"), + digestmod=digestmod, + ).hexdigest(), + "a1aa5f7de402d7b3d323f2991c8d4534013137010a83754fd0af6d7cd4922ed9", + ) + + def test_512(self): + for digestmod in (GOST34112012512, gost34112012512): + self.assertSequenceEqual( + hmac.new( + key=hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + msg=hexdec("0126bdb87800af214341456563780100"), + digestmod=digestmod, + ).hexdigest(), + "a59bab22ecae19c65fbde6e5f4e9f5d8549d31f037f9df9b905500e171923a773d5f1530f2ed7e964cb2eedc29e9ad2f3afe93b2814f79f5000ffc0366c251e6", + ) + + +class TestVectors(TestCase): + def test_m1(self): + m = hexdec("323130393837363534333231303938373635343332313039383736353433323130393837363534333231303938373635343332313039383736353433323130")[::-1] + self.assertSequenceEqual( + GOST34112012512(m).digest(), + hexdec("486f64c1917879417fef082b3381a4e211c324f074654c38823a7b76f830ad00fa1fbae42b1285c0352f227524bc9ab16254288dd6863dccd5b9f54a1ad0541b")[::-1] + ) + self.assertSequenceEqual( + GOST34112012256(m).digest(), + hexdec("00557be5e584fd52a449b16b0251d05d27f94ab76cbaa6da890b59d8ef1e159d")[::-1] + ) + + def test_m2(self): + m = u"Се ветри, Стрибожи внуци, веютъ с моря стрелами на храбрыя плъкы Игоревы".encode("cp1251") + self.assertSequenceEqual(m, hexdec("fbe2e5f0eee3c820fbeafaebef20fffbf0e1e0f0f520e0ed20e8ece0ebe5f0f2f120fff0eeec20f120faf2fee5e2202ce8f6f3ede220e8e6eee1e8f0f2d1202ce8f0f2e5e220e5d1")[::-1]) + self.assertSequenceEqual( + GOST34112012512(m).digest(), + hexdec("28fbc9bada033b1460642bdcddb90c3fb3e56c497ccd0f62b8a2ad4935e85f037613966de4ee00531ae60f3b5a47f8dae06915d5f2f194996fcabf2622e6881e")[::-1] + ) + self.assertSequenceEqual( + GOST34112012256(m).digest(), + hexdec("508f7e553c06501d749a66fc28c6cac0b005746d97537fa85d9e40904efed29d")[::-1] + ) + + def test_habr144(self): + """Test vector from https://habr.com/ru/post/452200/ + """ + m = hexdec("d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000002400000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + self.assertSequenceEqual( + GOST34112012256(m).hexdigest(), + "c766085540caaa8953bfcf7a1ba220619cee50d65dc242f82f23ba4b180b18e0", + ) + + +class TestPBKDF2(TestCase): + """http://tc26.ru/.../R_50.1.111-2016.pdf + """ + def test_1(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 1, 64)), + "64770af7f748c3b1c9ac831dbcfd85c26111b30a8a657ddc3056b80ca73e040d2854fd36811f6d825cc4ab66ec0a68a490a9e5cf5156b3a2b7eecddbf9a16b47", + ) + + def test_2(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 2, 64)), + "5a585bafdfbb6e8830d6d68aa3b43ac00d2e4aebce01c9b31c2caed56f0236d4d34b2b8fbd2c4e89d54d46f50e47d45bbac301571743119e8d3c42ba66d348de", + ) + + def test_3(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 4096, 64)), + "e52deb9a2d2aaff4e2ac9d47a41f34c20376591c67807f0477e32549dc341bc7867c09841b6d58e29d0347c996301d55df0d34e47cf68f4e3c2cdaf1d9ab86c3", + ) + + @skip("it takes too long") + def test_4(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 1677216, 64)), + "49e4843bba76e300afe24c4d23dc7392def12f2c0e244172367cd70a8982ac361adb601c7e2a314e8cb7b1e9df840e36ab5615be5d742b6cf203fb55fdc48071", + ) + + def test_5(self): + self.assertSequenceEqual( + hexenc(pbkdf2( + b"passwordPASSWORDpassword", + b"saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + 100, + )), + "b2d8f1245fc4d29274802057e4b54e0a0753aa22fc53760b301cf008679e58fe4bee9addcae99ba2b0b20f431a9c5e50f395c89387d0945aedeca6eb4015dfc2bd2421ee9bb71183ba882ceebfef259f33f9e27dc6178cb89dc37428cf9cc52a2baa2d3a", + ) + + def test_6(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"pass\x00word", b"sa\x00lt", 4096, 64)), + "50df062885b69801a3c10248eb0a27ab6e522ffeb20c991c660f001475d73a4e167f782c18e97e92976d9c1d970831ea78ccb879f67068cdac1910740844e830", + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost341194.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost341194.py new file mode 100644 index 0000000..4ffa6d6 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost341194.py @@ -0,0 +1,200 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from unittest import skip +from unittest import TestCase +import hmac + +from pygost import gost341194 +from pygost.gost341194 import GOST341194 +from pygost.gost341194 import pbkdf2 +from pygost.utils import hexenc + + +class TestCopy(TestCase): + def runTest(self): + m = GOST341194() + c = m.copy() + m.update(b"foobar") + c.update(b"foo") + c.update(b"bar") + self.assertSequenceEqual(m.digest(), c.digest()) + + +class TestHMACPEP247(TestCase): + def runTest(self): + h = hmac.new(b"foo", digestmod=gost341194) + h.update(b"foobar") + h.digest() + + +class TestVectors(TestCase): + def test_empty(self): + self.assertSequenceEqual( + GOST341194(b"", "id-GostR3411-94-TestParamSet").hexdigest(), + "ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d", + ) + + def test_a(self): + self.assertSequenceEqual( + GOST341194(b"a", "id-GostR3411-94-TestParamSet").hexdigest(), + "d42c539e367c66e9c88a801f6649349c21871b4344c6a573f849fdce62f314dd", + ) + + def test_abc(self): + self.assertSequenceEqual( + GOST341194(b"abc", "id-GostR3411-94-TestParamSet").hexdigest(), + "f3134348c44fb1b2a277729e2285ebb5cb5e0f29c975bc753b70497c06a4d51d", + ) + + def test_message_digest(self): + self.assertSequenceEqual( + GOST341194(b"message digest", "id-GostR3411-94-TestParamSet").hexdigest(), + "ad4434ecb18f2c99b60cbe59ec3d2469582b65273f48de72db2fde16a4889a4d", + ) + + def test_Us(self): + self.assertSequenceEqual( + GOST341194(128 * b"U", "id-GostR3411-94-TestParamSet").hexdigest(), + "53a3a3ed25180cef0c1d85a074273e551c25660a87062a52d926a9e8fe5733a4", + ) + + def test_dog(self): + self.assertSequenceEqual( + GOST341194(b"The quick brown fox jumps over the lazy dog", "id-GostR3411-94-TestParamSet",).hexdigest(), + "77b7fa410c9ac58a25f49bca7d0468c9296529315eaca76bd1a10f376d1f4294", + ) + + def test_cog(self): + self.assertSequenceEqual( + GOST341194(b"The quick brown fox jumps over the lazy cog", "id-GostR3411-94-TestParamSet",).hexdigest(), + "a3ebc4daaab78b0be131dab5737a7f67e602670d543521319150d2e14eeec445", + ) + + def test_rfc32(self): + self.assertSequenceEqual( + GOST341194(b"This is message, length=32 bytes", "id-GostR3411-94-TestParamSet",).hexdigest(), + "b1c466d37519b82e8319819ff32595e047a28cb6f83eff1c6916a815a637fffa", + ) + + def test_rfc50(self): + self.assertSequenceEqual( + GOST341194(b"Suppose the original message has length = 50 bytes", "id-GostR3411-94-TestParamSet",).hexdigest(), + "471aba57a60a770d3a76130635c1fbea4ef14de51f78b4ae57dd893b62f55208", + ) + + +class TestVectorsCryptoPro(TestCase): + """CryptoPro S-box test vectors + """ + def test_empty(self): + self.assertSequenceEqual( + GOST341194(b"", "id-GostR3411-94-CryptoProParamSet").hexdigest(), + "981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0", + ) + + def test_a(self): + self.assertSequenceEqual( + GOST341194(b"a", "id-GostR3411-94-CryptoProParamSet").hexdigest(), + "e74c52dd282183bf37af0079c9f78055715a103f17e3133ceff1aacf2f403011", + ) + + def test_abc(self): + self.assertSequenceEqual( + GOST341194(b"abc", "id-GostR3411-94-CryptoProParamSet").hexdigest(), + "b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c", + ) + + def test_message_digest(self): + self.assertSequenceEqual( + GOST341194(b"message digest", "id-GostR3411-94-CryptoProParamSet",).hexdigest(), + "bc6041dd2aa401ebfa6e9886734174febdb4729aa972d60f549ac39b29721ba0", + ) + + def test_dog(self): + self.assertSequenceEqual( + GOST341194(b"The quick brown fox jumps over the lazy dog", "id-GostR3411-94-CryptoProParamSet",).hexdigest(), + "9004294a361a508c586fe53d1f1b02746765e71b765472786e4770d565830a76", + ) + + def test_32(self): + self.assertSequenceEqual( + GOST341194(b"This is message, length=32 bytes", "id-GostR3411-94-CryptoProParamSet",).hexdigest(), + "2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb", + ) + + def test_50(self): + self.assertSequenceEqual( + GOST341194(b"Suppose the original message has length = 50 bytes", "id-GostR3411-94-CryptoProParamSet",).hexdigest(), + "c3730c5cbccacf915ac292676f21e8bd4ef75331d9405e5f1a61dc3130a65011", + ) + + def test_Us(self): + self.assertSequenceEqual( + GOST341194(128 * b"U", "id-GostR3411-94-CryptoProParamSet").hexdigest(), + "1c4ac7614691bbf427fa2316216be8f10d92edfd37cd1027514c1008f649c4e8", + ) + + +class TestPBKDF2(TestCase): + """http://tc26.ru/methods/containers_v1/Addition_to_PKCS5_v1_0.pdf test vectors + """ + def test_1(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 1, 32)), + "7314e7c04fb2e662c543674253f68bd0b73445d07f241bed872882da21662d58", + ) + + def test_2(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 2, 32)), + "990dfa2bd965639ba48b07b792775df79f2db34fef25f274378872fed7ed1bb3", + ) + + def test_3(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 4096, 32)), + "1f1829a94bdff5be10d0aeb36af498e7a97467f3b31116a5a7c1afff9deadafe", + ) + + @skip("it takes too long") + def test_4(self): + self.assertSequenceEqual( + hexenc(pbkdf2(b"password", b"salt", 16777216, 32)), + "a57ae5a6088396d120850c5c09de0a525100938a59b1b5c3f7810910d05fcd97", + ) + + def test_5(self): + self.assertSequenceEqual( + hexenc(pbkdf2( + b"passwordPASSWORDpassword", + b"saltSALTsaltSALTsaltSALTsaltSALTsalt", + 4096, + 40, + )), + "788358c69cb2dbe251a7bb17d5f4241f265a792a35becde8d56f326b49c85047b7638acb4764b1fd", + ) + + def test_6(self): + self.assertSequenceEqual( + hexenc(pbkdf2( + b"pass\x00word", + b"sa\x00lt", + 4096, + 20, + )), + "43e06c5590b08c0225242373127edf9c8e9c3291", + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3412.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3412.py new file mode 100644 index 0000000..5dbb200 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3412.py @@ -0,0 +1,137 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from unittest import TestCase + +from pygost.gost3412 import C +from pygost.gost3412 import GOST3412Kuznechik +from pygost.gost3412 import GOST3412Magma +from pygost.gost3412 import L +from pygost.gost3412 import PI +from pygost.utils import hexdec + + +def S(blk): + return bytearray(PI[v] for v in blk) + + +def R(blk): + return L(blk, rounds=1) + + +class STest(TestCase): + def test_vec1(self): + blk = bytearray(hexdec("ffeeddccbbaa99881122334455667700")) + self.assertSequenceEqual(S(blk), hexdec("b66cd8887d38e8d77765aeea0c9a7efc")) + + def test_vec2(self): + blk = bytearray(hexdec("b66cd8887d38e8d77765aeea0c9a7efc")) + self.assertSequenceEqual(S(blk), hexdec("559d8dd7bd06cbfe7e7b262523280d39")) + + def test_vec3(self): + blk = bytearray(hexdec("559d8dd7bd06cbfe7e7b262523280d39")) + self.assertSequenceEqual(S(blk), hexdec("0c3322fed531e4630d80ef5c5a81c50b")) + + def test_vec4(self): + blk = bytearray(hexdec("0c3322fed531e4630d80ef5c5a81c50b")) + self.assertSequenceEqual(S(blk), hexdec("23ae65633f842d29c5df529c13f5acda")) + + +class RTest(TestCase): + def test_vec1(self): + blk = bytearray(hexdec("00000000000000000000000000000100")) + self.assertSequenceEqual(R(blk), hexdec("94000000000000000000000000000001")) + + def test_vec2(self): + blk = bytearray(hexdec("94000000000000000000000000000001")) + self.assertSequenceEqual(R(blk), hexdec("a5940000000000000000000000000000")) + + def test_vec3(self): + blk = bytearray(hexdec("a5940000000000000000000000000000")) + self.assertSequenceEqual(R(blk), hexdec("64a59400000000000000000000000000")) + + def test_vec4(self): + blk = bytearray(hexdec("64a59400000000000000000000000000")) + self.assertSequenceEqual(R(blk), hexdec("0d64a594000000000000000000000000")) + + +class LTest(TestCase): + def test_vec1(self): + blk = bytearray(hexdec("64a59400000000000000000000000000")) + self.assertSequenceEqual(L(blk), hexdec("d456584dd0e3e84cc3166e4b7fa2890d")) + + def test_vec2(self): + blk = bytearray(hexdec("d456584dd0e3e84cc3166e4b7fa2890d")) + self.assertSequenceEqual(L(blk), hexdec("79d26221b87b584cd42fbc4ffea5de9a")) + + def test_vec3(self): + blk = bytearray(hexdec("79d26221b87b584cd42fbc4ffea5de9a")) + self.assertSequenceEqual(L(blk), hexdec("0e93691a0cfc60408b7b68f66b513c13")) + + def test_vec4(self): + blk = bytearray(hexdec("0e93691a0cfc60408b7b68f66b513c13")) + self.assertSequenceEqual(L(blk), hexdec("e6a8094fee0aa204fd97bcb0b44b8580")) + + +class KuznechikTest(TestCase): + key = hexdec("8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef") + plaintext = hexdec("1122334455667700ffeeddccbbaa9988") + ciphertext = hexdec("7f679d90bebc24305a468d42b9d4edcd") + + def test_c(self): + self.assertSequenceEqual(C[0], hexdec("6ea276726c487ab85d27bd10dd849401")) + self.assertSequenceEqual(C[1], hexdec("dc87ece4d890f4b3ba4eb92079cbeb02")) + self.assertSequenceEqual(C[2], hexdec("b2259a96b4d88e0be7690430a44f7f03")) + self.assertSequenceEqual(C[3], hexdec("7bcd1b0b73e32ba5b79cb140f2551504")) + self.assertSequenceEqual(C[4], hexdec("156f6d791fab511deabb0c502fd18105")) + self.assertSequenceEqual(C[5], hexdec("a74af7efab73df160dd208608b9efe06")) + self.assertSequenceEqual(C[6], hexdec("c9e8819dc73ba5ae50f5b570561a6a07")) + self.assertSequenceEqual(C[7], hexdec("f6593616e6055689adfba18027aa2a08")) + + def test_roundkeys(self): + ciph = GOST3412Kuznechik(self.key) + self.assertSequenceEqual(ciph.ks[0], hexdec("8899aabbccddeeff0011223344556677")) + self.assertSequenceEqual(ciph.ks[1], hexdec("fedcba98765432100123456789abcdef")) + self.assertSequenceEqual(ciph.ks[2], hexdec("db31485315694343228d6aef8cc78c44")) + self.assertSequenceEqual(ciph.ks[3], hexdec("3d4553d8e9cfec6815ebadc40a9ffd04")) + self.assertSequenceEqual(ciph.ks[4], hexdec("57646468c44a5e28d3e59246f429f1ac")) + self.assertSequenceEqual(ciph.ks[5], hexdec("bd079435165c6432b532e82834da581b")) + self.assertSequenceEqual(ciph.ks[6], hexdec("51e640757e8745de705727265a0098b1")) + self.assertSequenceEqual(ciph.ks[7], hexdec("5a7925017b9fdd3ed72a91a22286f984")) + self.assertSequenceEqual(ciph.ks[8], hexdec("bb44e25378c73123a5f32f73cdb6e517")) + self.assertSequenceEqual(ciph.ks[9], hexdec("72e9dd7416bcf45b755dbaa88e4a4043")) + + def test_encrypt(self): + ciph = GOST3412Kuznechik(self.key) + self.assertSequenceEqual(ciph.encrypt(self.plaintext), self.ciphertext) + + def test_decrypt(self): + ciph = GOST3412Kuznechik(self.key) + self.assertSequenceEqual(ciph.decrypt(self.ciphertext), self.plaintext) + + +class MagmaTest(TestCase): + key = hexdec("ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") + plaintext = hexdec("fedcba9876543210") + ciphertext = hexdec("4ee901e5c2d8ca3d") + + def test_encrypt(self): + ciph = GOST3412Magma(self.key) + self.assertSequenceEqual(ciph.encrypt(self.plaintext), self.ciphertext) + + def test_decrypt(self): + ciph = GOST3412Magma(self.key) + self.assertSequenceEqual(ciph.decrypt(self.ciphertext), self.plaintext) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3413.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3413.py new file mode 100644 index 0000000..0098513 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_gost3413.py @@ -0,0 +1,766 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import urandom +from random import randint +from unittest import TestCase + +from pygost.gost3412 import GOST3412Kuznechik +from pygost.gost3412 import GOST3412Magma +from pygost.gost3413 import _mac_ks +from pygost.gost3413 import acpkm +from pygost.gost3413 import acpkm_master +from pygost.gost3413 import cbc_decrypt +from pygost.gost3413 import cbc_encrypt +from pygost.gost3413 import cfb_decrypt +from pygost.gost3413 import cfb_encrypt +from pygost.gost3413 import ctr +from pygost.gost3413 import ctr_acpkm +from pygost.gost3413 import ecb_decrypt +from pygost.gost3413 import ecb_encrypt +from pygost.gost3413 import KEYSIZE +from pygost.gost3413 import mac +from pygost.gost3413 import mac_acpkm_master +from pygost.gost3413 import ofb +from pygost.gost3413 import pad2 +from pygost.gost3413 import pad_iso10126 +from pygost.gost3413 import unpad2 +from pygost.gost3413 import unpad_iso10126 +from pygost.utils import hexdec +from pygost.utils import hexenc +from pygost.utils import strxor + + +class Pad2Test(TestCase): + def test_symmetric(self): + for _ in range(100): + for blocksize in (GOST3412Magma.blocksize, GOST3412Kuznechik.blocksize): + data = urandom(randint(0, blocksize * 3)) + self.assertSequenceEqual( + unpad2(pad2(data, blocksize), blocksize), + data, + ) + + +class GOST3412KuznechikModesTest(TestCase): + key = hexdec("8899aabbccddeeff0011223344556677fedcba98765432100123456789abcdef") + ciph = GOST3412Kuznechik(key) + plaintext = "" + plaintext += "1122334455667700ffeeddccbbaa9988" + plaintext += "00112233445566778899aabbcceeff0a" + plaintext += "112233445566778899aabbcceeff0a00" + plaintext += "2233445566778899aabbcceeff0a0011" + iv = hexdec("1234567890abcef0a1b2c3d4e5f0011223344556677889901213141516171819") + + def test_ecb_vectors(self): + ciphtext = "" + ciphtext += "7f679d90bebc24305a468d42b9d4edcd" + ciphtext += "b429912c6e0032f9285452d76718d08b" + ciphtext += "f0ca33549d247ceef3f5a5313bd4b157" + ciphtext += "d0b09ccde830b9eb3a02c4c5aa8ada98" + self.assertSequenceEqual( + hexenc(ecb_encrypt( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(self.plaintext), + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(ecb_decrypt( + self.ciph.decrypt, + GOST3412Kuznechik.blocksize, + hexdec(ciphtext), + )), + self.plaintext, + ) + + def test_ecb_symmetric(self): + for _ in range(100): + pt = pad2(urandom(randint(0, 16 * 2)), GOST3412Kuznechik.blocksize) + ciph = GOST3412Kuznechik(urandom(KEYSIZE)) + ct = ecb_encrypt(ciph.encrypt, GOST3412Kuznechik.blocksize, pt) + self.assertSequenceEqual(ecb_decrypt( + ciph.decrypt, + GOST3412Kuznechik.blocksize, + ct, + ), pt) + + def test_ctr_vectors(self): + ciphtext = "" + ciphtext += "f195d8bec10ed1dbd57b5fa240bda1b8" + ciphtext += "85eee733f6a13e5df33ce4b33c45dee4" + ciphtext += "a5eae88be6356ed3d5e877f13564a3a5" + ciphtext += "cb91fab1f20cbab6d1c6d15820bdba73" + iv = self.iv[:GOST3412Kuznechik.blocksize // 2] + self.assertSequenceEqual( + hexenc(ctr( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(self.plaintext), + iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(ctr( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(ciphtext), + iv, + )), + self.plaintext, + ) + + def test_ctr_symmetric(self): + for _ in range(100): + pt = urandom(randint(0, 16 * 2)) + iv = urandom(GOST3412Kuznechik.blocksize // 2) + ciph = GOST3412Kuznechik(urandom(KEYSIZE)) + ct = ctr(ciph.encrypt, GOST3412Kuznechik.blocksize, pt, iv) + self.assertSequenceEqual(ctr( + ciph.encrypt, + GOST3412Kuznechik.blocksize, + ct, + iv, + ), pt) + + def test_ofb_vectors(self): + ciphtext = "" + ciphtext += "81800a59b1842b24ff1f795e897abd95" + ciphtext += "ed5b47a7048cfab48fb521369d9326bf" + ciphtext += "66a257ac3ca0b8b1c80fe7fc10288a13" + ciphtext += "203ebbc066138660a0292243f6903150" + self.assertSequenceEqual( + hexenc(ofb( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(self.plaintext), + self.iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(ofb( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(ciphtext), + self.iv, + )), + self.plaintext, + ) + + def test_ofb_symmetric(self): + for _ in range(100): + pt = urandom(randint(0, 16 * 2)) + iv = urandom(GOST3412Kuznechik.blocksize * 2) + ciph = GOST3412Kuznechik(urandom(KEYSIZE)) + ct = ofb(ciph.encrypt, GOST3412Kuznechik.blocksize, pt, iv) + self.assertSequenceEqual(ofb( + ciph.encrypt, + GOST3412Kuznechik.blocksize, + ct, + iv, + ), pt) + + def test_ofb_manual(self): + iv = [urandom(GOST3412Kuznechik.blocksize) for _ in range(randint(2, 10))] + pt = [ + urandom(GOST3412Kuznechik.blocksize) + for _ in range(len(iv), len(iv) + randint(1, 10)) + ] + ciph = GOST3412Kuznechik(urandom(KEYSIZE)) + r = [ciph.encrypt(i) for i in iv] + for i in range(len(pt) - len(iv)): + r.append(ciph.encrypt(r[i])) + ct = [strxor(g, r) for g, r in zip(pt, r)] + self.assertSequenceEqual( + ofb(ciph.encrypt, GOST3412Kuznechik.blocksize, b"".join(pt), b"".join(iv)), + b"".join(ct), + ) + + def test_cbc_vectors(self): + ciphtext = "" + ciphtext += "689972d4a085fa4d90e52e3d6d7dcc27" + ciphtext += "2826e661b478eca6af1e8e448d5ea5ac" + ciphtext += "fe7babf1e91999e85640e8b0f49d90d0" + ciphtext += "167688065a895c631a2d9a1560b63970" + self.assertSequenceEqual( + hexenc(cbc_encrypt( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(self.plaintext), + self.iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(cbc_decrypt( + self.ciph.decrypt, + GOST3412Kuznechik.blocksize, + hexdec(ciphtext), + self.iv, + )), + self.plaintext, + ) + + def test_cbc_symmetric(self): + for _ in range(100): + pt = pad2(urandom(randint(0, 16 * 2)), GOST3412Kuznechik.blocksize) + iv = urandom(GOST3412Kuznechik.blocksize * 2) + ciph = GOST3412Kuznechik(urandom(KEYSIZE)) + ct = cbc_encrypt(ciph.encrypt, GOST3412Kuznechik.blocksize, pt, iv) + self.assertSequenceEqual(cbc_decrypt( + ciph.decrypt, + GOST3412Kuznechik.blocksize, + ct, + iv, + ), pt) + + def test_cfb_vectors(self): + ciphtext = "" + ciphtext += "81800a59b1842b24ff1f795e897abd95" + ciphtext += "ed5b47a7048cfab48fb521369d9326bf" + ciphtext += "79f2a8eb5cc68d38842d264e97a238b5" + ciphtext += "4ffebecd4e922de6c75bd9dd44fbf4d1" + self.assertSequenceEqual( + hexenc(cfb_encrypt( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(self.plaintext), + self.iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(cfb_decrypt( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(ciphtext), + self.iv, + )), + self.plaintext, + ) + + def test_cfb_symmetric(self): + for _ in range(100): + pt = urandom(randint(0, 16 * 2)) + iv = urandom(GOST3412Kuznechik.blocksize * 2) + ciph = GOST3412Kuznechik(urandom(KEYSIZE)) + ct = cfb_encrypt(ciph.encrypt, GOST3412Kuznechik.blocksize, pt, iv) + self.assertSequenceEqual(cfb_decrypt( + ciph.encrypt, + GOST3412Kuznechik.blocksize, + ct, + iv, + ), pt) + + def test_mac_vectors(self): + k1, k2 = _mac_ks(self.ciph.encrypt, GOST3412Kuznechik.blocksize) + self.assertSequenceEqual(hexenc(k1), "297d82bc4d39e3ca0de0573298151dc7") + self.assertSequenceEqual(hexenc(k2), "52fb05789a73c7941bc0ae65302a3b8e") + self.assertSequenceEqual( + hexenc(mac( + self.ciph.encrypt, + GOST3412Kuznechik.blocksize, + hexdec(self.plaintext), + )[:8]), + "336f4d296059fbe3", + ) + + def test_mac_applies(self): + for _ in range(100): + data = urandom(randint(0, 16 * 2)) + ciph = GOST3412Kuznechik(urandom(KEYSIZE)) + mac(ciph.encrypt, GOST3412Kuznechik.blocksize, data) + + +class GOST3412MagmaModesTest(TestCase): + key = hexdec("ffeeddccbbaa99887766554433221100f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") + ciph = GOST3412Magma(key) + plaintext = "" + plaintext += "92def06b3c130a59" + plaintext += "db54c704f8189d20" + plaintext += "4a98fb2e67a8024c" + plaintext += "8912409b17b57e41" + iv = hexdec("1234567890abcdef234567890abcdef134567890abcdef12") + + def test_ecb_vectors(self): + ciphtext = "" + ciphtext += "2b073f0494f372a0" + ciphtext += "de70e715d3556e48" + ciphtext += "11d8d9e9eacfbc1e" + ciphtext += "7c68260996c67efb" + self.assertSequenceEqual( + hexenc(ecb_encrypt( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(self.plaintext), + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(ecb_decrypt( + self.ciph.decrypt, + GOST3412Magma.blocksize, + hexdec(ciphtext), + )), + self.plaintext, + ) + + def test_ecb_symmetric(self): + for _ in range(100): + pt = pad2(urandom(randint(0, 16 * 2)), 16) + ciph = GOST3412Magma(urandom(KEYSIZE)) + ct = ecb_encrypt(ciph.encrypt, GOST3412Magma.blocksize, pt) + self.assertSequenceEqual(ecb_decrypt( + ciph.decrypt, + GOST3412Magma.blocksize, + ct, + ), pt) + + def test_ctr_vectors(self): + ciphtext = "" + ciphtext += "4e98110c97b7b93c" + ciphtext += "3e250d93d6e85d69" + ciphtext += "136d868807b2dbef" + ciphtext += "568eb680ab52a12d" + iv = self.iv[:4] + self.assertSequenceEqual( + hexenc(ctr( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(self.plaintext), + iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(ctr( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(ciphtext), + iv, + )), + self.plaintext, + ) + + def test_ctr_symmetric(self): + for _ in range(100): + pt = urandom(randint(0, 16 * 2)) + iv = urandom(GOST3412Magma.blocksize // 2) + ciph = GOST3412Magma(urandom(KEYSIZE)) + ct = ctr(ciph.encrypt, GOST3412Magma.blocksize, pt, iv) + self.assertSequenceEqual(ctr( + ciph.encrypt, + GOST3412Magma.blocksize, + ct, + iv, + ), pt) + + def test_ofb_vectors(self): + iv = self.iv[:16] + ciphtext = "" + ciphtext += "db37e0e266903c83" + ciphtext += "0d46644c1f9a089c" + ciphtext += "a0f83062430e327e" + ciphtext += "c824efb8bd4fdb05" + self.assertSequenceEqual( + hexenc(ofb( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(self.plaintext), + iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(ofb( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(ciphtext), + iv, + )), + self.plaintext, + ) + + def test_ofb_symmetric(self): + for _ in range(100): + pt = urandom(randint(0, 16 * 2)) + iv = urandom(GOST3412Magma.blocksize * 2) + ciph = GOST3412Magma(urandom(KEYSIZE)) + ct = ofb(ciph.encrypt, GOST3412Magma.blocksize, pt, iv) + self.assertSequenceEqual(ofb( + ciph.encrypt, + GOST3412Magma.blocksize, + ct, + iv, + ), pt) + + def test_cbc_vectors(self): + ciphtext = "" + ciphtext += "96d1b05eea683919" + ciphtext += "aff76129abb937b9" + ciphtext += "5058b4a1c4bc0019" + ciphtext += "20b78b1a7cd7e667" + self.assertSequenceEqual( + hexenc(cbc_encrypt( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(self.plaintext), + self.iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(cbc_decrypt( + self.ciph.decrypt, + GOST3412Magma.blocksize, + hexdec(ciphtext), + self.iv, + )), + self.plaintext, + ) + + def test_cbc_symmetric(self): + for _ in range(100): + pt = pad2(urandom(randint(0, 16 * 2)), 16) + iv = urandom(GOST3412Magma.blocksize * 2) + ciph = GOST3412Magma(urandom(KEYSIZE)) + ct = cbc_encrypt(ciph.encrypt, GOST3412Magma.blocksize, pt, iv) + self.assertSequenceEqual(cbc_decrypt( + ciph.decrypt, + GOST3412Magma.blocksize, + ct, + iv, + ), pt) + + def test_cfb_vectors(self): + iv = self.iv[:16] + ciphtext = "" + ciphtext += "db37e0e266903c83" + ciphtext += "0d46644c1f9a089c" + ciphtext += "24bdd2035315d38b" + ciphtext += "bcc0321421075505" + self.assertSequenceEqual( + hexenc(cfb_encrypt( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(self.plaintext), + iv, + )), + ciphtext, + ) + self.assertSequenceEqual( + hexenc(cfb_decrypt( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(ciphtext), + iv, + )), + self.plaintext, + ) + + def test_cfb_symmetric(self): + for _ in range(100): + pt = urandom(randint(0, 16 * 2)) + iv = urandom(GOST3412Magma.blocksize * 2) + ciph = GOST3412Magma(urandom(KEYSIZE)) + ct = cfb_encrypt(ciph.encrypt, GOST3412Magma.blocksize, pt, iv) + self.assertSequenceEqual(cfb_decrypt( + ciph.encrypt, + GOST3412Magma.blocksize, + ct, + iv, + ), pt) + + def test_mac_vectors(self): + k1, k2 = _mac_ks(self.ciph.encrypt, GOST3412Magma.blocksize) + self.assertSequenceEqual(hexenc(k1), "5f459b3342521424") + self.assertSequenceEqual(hexenc(k2), "be8b366684a42848") + self.assertSequenceEqual( + hexenc(mac( + self.ciph.encrypt, + GOST3412Magma.blocksize, + hexdec(self.plaintext), + )[:4]), + "154e7210", + ) + + def test_mac_applies(self): + for _ in range(100): + data = urandom(randint(0, 16 * 2)) + ciph = GOST3412Magma(urandom(KEYSIZE)) + mac(ciph.encrypt, GOST3412Magma.blocksize, data) + + +class TestVectorACPKM(TestCase): + """Test vectors from Р 1323565.1.017-2018 + """ + key = hexdec("8899AABBCCDDEEFF0011223344556677FEDCBA98765432100123456789ABCDEF") + + def test_magma_ctr_acpkm(self): + key = acpkm(GOST3412Magma(self.key).encrypt, GOST3412Magma.blocksize) + self.assertSequenceEqual(key, hexdec("863EA017842C3D372B18A85A28E2317D74BEFC107720DE0C9E8AB974ABD00CA0")) + key = acpkm(GOST3412Magma(key).encrypt, GOST3412Magma.blocksize) + self.assertSequenceEqual(key, hexdec("49A5E2677DE555982B8AD5E826652D17EEC847BF5B3997A81CF7FE7F1187BD27")) + key = acpkm(GOST3412Magma(key).encrypt, GOST3412Magma.blocksize) + self.assertSequenceEqual(key, hexdec("3256BF3F97B5667426A9FB1C5EAABE41893CCDD5A868F9B63B0AA90720FA43C4")) + + def test_magma_ctr(self): + encrypter = GOST3412Magma(self.key).encrypt + plaintext = hexdec(""" +11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88 +00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A +11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 +22 33 44 55 66 77 88 99 + """.replace("\n", "").replace(" ", "")) + iv = hexdec("12345678") + ciphertext = hexdec(""" +2A B8 1D EE EB 1E 4C AB 68 E1 04 C4 BD 6B 94 EA +C7 2C 67 AF 6C 2E 5B 6B 0E AF B6 17 70 F1 B3 2E +A1 AE 71 14 9E ED 13 82 AB D4 67 18 06 72 EC 6F +84 A2 F1 5B 3F CA 72 C1 + """.replace("\n", "").replace(" ", "")) + self.assertSequenceEqual( + ctr_acpkm( + GOST3412Magma, + encrypter, + bs=GOST3412Magma.blocksize, + section_size=GOST3412Magma.blocksize * 2, + data=plaintext, + iv=iv + ), + ciphertext, + ) + self.assertSequenceEqual( + ctr_acpkm( + GOST3412Magma, + encrypter, + bs=GOST3412Magma.blocksize, + section_size=GOST3412Magma.blocksize * 2, + data=ciphertext, + iv=iv + ), + plaintext, + ) + + def test_kuznechik_ctr_acpkm(self): + key = acpkm(GOST3412Kuznechik(self.key).encrypt, GOST3412Kuznechik.blocksize) + self.assertSequenceEqual(key, hexdec("2666ED40AE687811745CA0B448F57A7B390ADB5780307E8E9659AC403AE60C60")) + key = acpkm(GOST3412Kuznechik(key).encrypt, GOST3412Kuznechik.blocksize) + self.assertSequenceEqual(key, hexdec("BB3DD5402E999B7A3DEBB0DB45448EC530F07365DFEE3ABA8415F77AC8F34CE8")) + key = acpkm(GOST3412Kuznechik(key).encrypt, GOST3412Kuznechik.blocksize) + self.assertSequenceEqual(key, hexdec("23362FD553CAD2178299A5B5A2D4722E3BB83C730A8BF57CE2DD004017F8C565")) + + def test_kuznechik_ctr(self): + encrypter = GOST3412Kuznechik(self.key).encrypt + iv = hexdec("1234567890ABCEF0") + plaintext = hexdec(""" +11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88 +00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A +11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 +22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 +33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 +44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33 +55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 33 44 + """.replace("\n", "").replace(" ", "")) + ciphertext = hexdec(""" +F1 95 D8 BE C1 0E D1 DB D5 7B 5F A2 40 BD A1 B8 +85 EE E7 33 F6 A1 3E 5D F3 3C E4 B3 3C 45 DE E4 +4B CE EB 8F 64 6F 4C 55 00 17 06 27 5E 85 E8 00 +58 7C 4D F5 68 D0 94 39 3E 48 34 AF D0 80 50 46 +CF 30 F5 76 86 AE EC E1 1C FC 6C 31 6B 8A 89 6E +DF FD 07 EC 81 36 36 46 0C 4F 3B 74 34 23 16 3E +64 09 A9 C2 82 FA C8 D4 69 D2 21 E7 FB D6 DE 5D + """.replace("\n", "").replace(" ", "")) + self.assertSequenceEqual( + ctr_acpkm( + GOST3412Kuznechik, + encrypter, + bs=GOST3412Kuznechik.blocksize, + section_size=GOST3412Kuznechik.blocksize * 2, + data=plaintext, + iv=iv, + ), + ciphertext, + ) + self.assertSequenceEqual( + ctr_acpkm( + GOST3412Kuznechik, + encrypter, + bs=GOST3412Kuznechik.blocksize, + section_size=GOST3412Kuznechik.blocksize * 2, + data=ciphertext, + iv=iv, + ), + plaintext, + ) + + def test_magma_omac_1_5_blocks(self): + encrypter = GOST3412Magma(self.key).encrypt + key_section_size = 640 // 8 + self.assertSequenceEqual( + acpkm_master( + GOST3412Magma, + encrypter, + key_section_size=key_section_size, + bs=GOST3412Magma.blocksize, + keymat_len=KEYSIZE + GOST3412Magma.blocksize, + ), + hexdec("0DF2F5273DA328932AC49D81D36B2558A50DBF9BBCAC74A614B2CCB2F1CBCD8A70638E3DE8B3571E"), + ) + text = hexdec("1122334455667700FFEEDDCC") + self.assertSequenceEqual( + mac_acpkm_master( + GOST3412Magma, + encrypter, + key_section_size, + section_size=GOST3412Magma.blocksize * 2, + bs=GOST3412Magma.blocksize, + data=text, + ), + hexdec("A0540E3730ACBCF3"), + ) + + def test_magma_omac_5_blocks(self): + encrypter = GOST3412Magma(self.key).encrypt + key_section_size = 640 // 8 + self.assertSequenceEqual( + acpkm_master( + GOST3412Magma, + encrypter, + key_section_size=key_section_size, + bs=GOST3412Magma.blocksize, + keymat_len=3 * (KEYSIZE + GOST3412Magma.blocksize), + ), + hexdec(""" +0D F2 F5 27 3D A3 28 93 2A C4 9D 81 D3 6B 25 58 +A5 0D BF 9B BC AC 74 A6 14 B2 CC B2 F1 CB CD 8A +70 63 8E 3D E8 B3 57 1E 8D 38 26 D5 5E 63 A1 67 +E2 40 66 40 54 7B 9F 1F 5F 2B 43 61 2A AE AF DA +18 0B AC 86 04 DF A6 FE 53 C2 CE 27 0E 9C 9F 52 +68 D0 FD BF E1 A3 BD D9 BE 5B 96 D0 A1 20 23 48 +6E F1 71 0F 92 4A E0 31 30 52 CB 5F CA 0B 79 1E +1B AB E8 57 6D 0F E3 A8 + """.replace("\n", "").replace(" ", "")), + ) + text = hexdec(""" +11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88 +00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A +11 22 33 44 55 66 77 88 + """.replace("\n", "").replace(" ", "")) + self.assertSequenceEqual( + mac_acpkm_master( + GOST3412Magma, + encrypter, + key_section_size, + section_size=GOST3412Magma.blocksize * 2, + bs=GOST3412Magma.blocksize, + data=text, + ), + hexdec("34008DAD5496BB8E"), + ) + + def test_kuznechik_omac_1_5_blocks(self): + encrypter = GOST3412Kuznechik(self.key).encrypt + key_section_size = 768 // 8 + self.assertSequenceEqual( + acpkm_master( + GOST3412Kuznechik, + encrypter, + key_section_size=key_section_size, + bs=GOST3412Kuznechik.blocksize, + keymat_len=KEYSIZE + GOST3412Kuznechik.blocksize, + ), + hexdec(""" +0C AB F1 F2 EF BC 4A C1 60 48 DF 1A 24 C6 05 B2 +C0 D1 67 3D 75 86 A8 EC 0D D4 2C 45 A4 F9 5B AE +0F 2E 26 17 E4 71 48 68 0F C3 E6 17 8D F2 C1 37 + """.replace("\n", "").replace(" ", "")) + ) + text = hexdec(""" +11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88 +00 11 22 33 44 55 66 77 + """.replace("\n", "").replace(" ", "")) + self.assertSequenceEqual( + mac_acpkm_master( + GOST3412Kuznechik, + encrypter, + key_section_size, + section_size=GOST3412Kuznechik.blocksize * 2, + bs=GOST3412Kuznechik.blocksize, + data=text, + ), + hexdec("B5367F47B62B995EEB2A648C5843145E"), + ) + + def test_kuznechik_omac_5_blocks(self): + encrypter = GOST3412Kuznechik(self.key).encrypt + key_section_size = 768 // 8 + self.assertSequenceEqual( + acpkm_master( + GOST3412Kuznechik, + encrypter, + key_section_size=key_section_size, + bs=GOST3412Kuznechik.blocksize, + keymat_len=3 * (KEYSIZE + GOST3412Kuznechik.blocksize), + ), + hexdec(""" +0C AB F1 F2 EF BC 4A C1 60 48 DF 1A 24 C6 05 B2 +C0 D1 67 3D 75 86 A8 EC 0D D4 2C 45 A4 F9 5B AE +0F 2E 26 17 E4 71 48 68 0F C3 E6 17 8D F2 C1 37 +C9 DD A8 9C FF A4 91 FE AD D9 B3 EA B7 03 BB 31 +BC 7E 92 7F 04 94 72 9F 51 B4 9D 3D F9 C9 46 08 +00 FB BC F5 ED EE 61 0E A0 2F 01 09 3C 7B C7 42 +D7 D6 27 15 01 B1 77 77 52 63 C2 A3 49 5A 83 18 +A8 1C 79 A0 4F 29 66 0E A3 FD A8 74 C6 30 79 9E +14 2C 57 79 14 FE A9 0D 3B C2 50 2E 83 36 85 D9 + """.replace("\n", "").replace(" ", "")), + ) + text = hexdec(""" +11 22 33 44 55 66 77 00 FF EE DD CC BB AA 99 88 +00 11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A +11 22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 +22 33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 +33 44 55 66 77 88 99 AA BB CC EE FF 0A 00 11 22 + """.replace("\n", "").replace(" ", "")) + self.assertSequenceEqual( + mac_acpkm_master( + GOST3412Kuznechik, + encrypter, + key_section_size, + section_size=GOST3412Kuznechik.blocksize * 2, + bs=GOST3412Kuznechik.blocksize, + data=text, + ), + hexdec("FBB8DCEE45BEA67C35F58C5700898E5D"), + ) + + +class ISO10126Test(TestCase): + def test_symmetric(self): + for _ in range(100): + for blocksize in (GOST3412Magma.blocksize, GOST3412Kuznechik.blocksize): + data = urandom(randint(0, blocksize * 3)) + padded = pad_iso10126(data, blocksize) + self.assertSequenceEqual(unpad_iso10126(padded, blocksize), data) + with self.assertRaises(ValueError): + unpad_iso10126(padded[1:], blocksize) + + def test_small(self): + with self.assertRaises(ValueError): + unpad_iso10126(b"foobar\x00\x09", 8) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_kdf.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_kdf.py new file mode 100644 index 0000000..6921cfc --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_kdf.py @@ -0,0 +1,58 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from unittest import TestCase + +from pygost.kdf import kdf_gostr3411_2012_256 +from pygost.kdf import kdf_tree_gostr3411_2012_256 +from pygost.utils import hexdec + + +class TestKDFGOSTR34112012256(TestCase): + def runTest(self): + self.assertEqual( + kdf_gostr3411_2012_256( + hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + hexdec("26bdb878"), + hexdec("af21434145656378"), + ), + hexdec("a1aa5f7de402d7b3d323f2991c8d4534013137010a83754fd0af6d7cd4922ed9"), + ) + + +class TestKDFTREEGOSTR34112012256(TestCase): + def runTest(self): + self.assertSequenceEqual( + kdf_tree_gostr3411_2012_256( + hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + hexdec("26bdb878"), + hexdec("af21434145656378"), + 1, + ), + (hexdec("a1aa5f7de402d7b3d323f2991c8d4534013137010a83754fd0af6d7cd4922ed9"),), + ) + self.assertSequenceEqual( + kdf_tree_gostr3411_2012_256( + hexdec("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + hexdec("26bdb878"), + hexdec("af21434145656378"), + 2, + ), + ( + hexdec("22b6837845c6bef65ea71672b265831086d3c76aebe6dae91cad51d83f79d16b"), + hexdec("074c9330599d7f8d712fca54392f4ddde93751206b3584c8f43f9e6dc51531f9"), + ), + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_mgm.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_mgm.py new file mode 100644 index 0000000..e70a7f5 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_mgm.py @@ -0,0 +1,75 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import urandom +from random import randint +from unittest import TestCase + +from pygost.gost3412 import GOST3412Kuznechik +from pygost.gost3412 import GOST3412Magma +from pygost.gost3412 import KEYSIZE +from pygost.mgm import MGM +from pygost.mgm import nonce_prepare +from pygost.utils import hexdec + + +class TestVector(TestCase): + def runTest(self): + key = hexdec("8899AABBCCDDEEFF0011223344556677FEDCBA98765432100123456789ABCDEF") + ad = hexdec("0202020202020202010101010101010104040404040404040303030303030303EA0505050505050505") + plaintext = hexdec("1122334455667700FFEEDDCCBBAA998800112233445566778899AABBCCEEFF0A112233445566778899AABBCCEEFF0A002233445566778899AABBCCEEFF0A0011AABBCC") + mgm = MGM(GOST3412Kuznechik(key).encrypt, GOST3412Kuznechik.blocksize) + ciphertext = mgm.seal(plaintext[:16], plaintext, ad) + self.assertSequenceEqual(ciphertext[:len(plaintext)], hexdec("A9757B8147956E9055B8A33DE89F42FC8075D2212BF9FD5BD3F7069AADC16B39497AB15915A6BA85936B5D0EA9F6851CC60C14D4D3F883D0AB94420695C76DEB2C7552")) + self.assertSequenceEqual(ciphertext[len(plaintext):], hexdec("CF5D656F40C34F5C46E8BB0E29FCDB4C")) + self.assertSequenceEqual(mgm.open(plaintext[:16], ciphertext, ad), plaintext) + + +class TestSymmetric(TestCase): + def _itself(self, mgm, bs, tag_size): + for _ in range(1000): + nonce = nonce_prepare(urandom(bs)) + ad = urandom(randint(0, 20)) + pt = urandom(randint(0, 20)) + if len(ad) + len(pt) == 0: + continue + ct = mgm.seal(nonce, pt, ad) + self.assertEqual(len(ct) - tag_size, len(pt)) + self.assertSequenceEqual(mgm.open(nonce, ct, ad), pt) + + def test_magma(self): + for tag_size in ( + GOST3412Magma.blocksize, + GOST3412Magma.blocksize - 2, + ): + mgm = MGM( + GOST3412Magma(urandom(KEYSIZE)).encrypt, + GOST3412Magma.blocksize, + tag_size, + ) + self._itself(mgm, GOST3412Magma.blocksize, tag_size) + + def test_kuznechik(self): + for tag_size in ( + GOST3412Kuznechik.blocksize, + GOST3412Kuznechik.blocksize - 2, + ): + mgm = MGM( + GOST3412Kuznechik(urandom(KEYSIZE)).encrypt, + GOST3412Kuznechik.blocksize, + tag_size, + ) + self._itself(mgm, GOST3412Kuznechik.blocksize, tag_size) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_pfx.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_pfx.py new file mode 100644 index 0000000..a2760bf --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_pfx.py @@ -0,0 +1,680 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base64 import b64decode +from hmac import new as hmac_new +from unittest import skipIf +from unittest import TestCase + +from pygost import gost3410 +from pygost.gost28147 import cfb_decrypt +from pygost.gost34112012256 import GOST34112012256 +from pygost.gost34112012512 import GOST34112012512 +from pygost.gost34112012512 import pbkdf2 as gost34112012_pbkdf2 +from pygost.gost3412 import GOST3412Kuznechik +from pygost.gost3412 import GOST3412Magma +from pygost.gost3412 import KEYSIZE +from pygost.gost3413 import ctr_acpkm +from pygost.gost3413 import mac as omac +from pygost.kdf import kdf_tree_gostr3411_2012_256 +from pygost.kdf import keg +from pygost.utils import hexdec +from pygost.wrap import kimp15 + + +try: + from pyderasn import OctetString + + from pygost.asn1schemas.cms import EncryptedData + from pygost.asn1schemas.cms import EnvelopedData + from pygost.asn1schemas.cms import SignedAttributes + from pygost.asn1schemas.cms import SignedData + from pygost.asn1schemas.oids import id_data + from pygost.asn1schemas.oids import id_envelopedData + from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_ctracpkm + from pygost.asn1schemas.oids import id_gostr3412_2015_kuznyechik_wrap_kexp15 + from pygost.asn1schemas.oids import id_messageDigest + from pygost.asn1schemas.oids import id_pbes2 + from pygost.asn1schemas.oids import id_pkcs12_bagtypes_certBag + from pygost.asn1schemas.oids import id_pkcs12_bagtypes_keyBag + from pygost.asn1schemas.oids import id_pkcs12_bagtypes_pkcs8ShroudedKeyBag + from pygost.asn1schemas.oids import id_pkcs9_certTypes_x509Certificate + from pygost.asn1schemas.oids import id_signedData + from pygost.asn1schemas.oids import id_tc26_agreement_gost3410_2012_256 + from pygost.asn1schemas.oids import id_tc26_gost3411_2012_256 + from pygost.asn1schemas.pfx import CertBag + from pygost.asn1schemas.pfx import KeyBag + from pygost.asn1schemas.pfx import OctetStringSafeContents + from pygost.asn1schemas.pfx import PBES2Params + from pygost.asn1schemas.pfx import PFX + from pygost.asn1schemas.pfx import PKCS8ShroudedKeyBag + from pygost.asn1schemas.pfx import SafeContents + from pygost.asn1schemas.x509 import Certificate +except ImportError: + pyderasn_exists = False +else: + pyderasn_exists = True + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestPFX(TestCase): + """PFX test vectors from "Транспортный ключевой контейнер" (R50.1.112-2016.pdf) + """ + pfx_raw = b64decode(""" +MIIFqgIBAzCCBSsGCSqGSIb3DQEHAaCCBRwEggUYMIIFFDCCASIGCSqGSIb3DQEH +AaCCARMEggEPMIIBCzCCAQcGCyqGSIb3DQEMCgECoIHgMIHdMHEGCSqGSIb3DQEF +DTBkMEEGCSqGSIb3DQEFDDA0BCD5qZr0TTIsBvdgUoq/zFwOzdyJohj6/4Wiyccg +j9AK/QICB9AwDAYIKoUDBwEBBAIFADAfBgYqhQMCAhUwFQQI3Ip/Vp0IsyIGCSqF +AwcBAgUBAQRoSfLhgx9s/zn+BjnhT0ror07vS55Ys5hgvVpWDx4mXGWWyez/2sMc +aFgSr4H4UTGGwoMynGLpF1IOVo+bGJ0ePqHB+gS5OL9oV+PUmZ/ELrRENKlCDqfY +WvpSystX29CvCFrnTnDsbBYxFTATBgkqhkiG9w0BCRUxBgQEAQAAADCCA+oGCSqG +SIb3DQEHBqCCA9swggPXAgEAMIID0AYJKoZIhvcNAQcBMHEGCSqGSIb3DQEFDTBk +MEEGCSqGSIb3DQEFDDA0BCCJTJLZQRi1WIpQHzyjXbq7+Vw2+1280C45x8ff6kMS +VAICB9AwDAYIKoUDBwEBBAIFADAfBgYqhQMCAhUwFQQIxepowwvS11MGCSqFAwcB +AgUBAYCCA06n09P/o+eDEKoSWpvlpOLKs7dKmVquKzJ81nCngvLQ5fEWL1WkxwiI +rEhm53JKLD0wy4hekalEk011Bvc51XP9gkDkmaoBpnV/TyKIY35wl6ATfeGXno1M +KoA+Ktdhv4gLnz0k2SXdkUj11JwYskXue+REA0p4m2ZsoaTmvoODamh9JeY/5Qjy +Xe58CGnyXFzX3eU86qs4WfdWdS3NzYYOk9zzVl46le9u79O/LnW2j4n2of/Jpk/L +YjrRmz5oYeQOqKOKhEyhpO6e+ejr6laduEv7TwJQKRNiygogbVvkNn3VjHTSOUG4 +W+3NRPhjb0jD9obdyx6MWa6O3B9bUzFMNav8/gYn0vTDxqXMLy/92oTngNrVx6Gc +cNl128ISrDS6+RxtAMiEBRK6xNkemqX5yNXG5GrLQQFGP6mbs2nNpjKlgj3pljmX +Eky2/G78XiJrv02OgGs6CKnI9nMpa6N7PBHV34MJ6EZzWOWDRQ420xk63mnicrs0 +WDVJ0xjdu4FW3iEk02EaiRTvGBpa6GL7LBp6QlaXSSwONx725cyRsL9cTlukqXER +WHDlMpjYLbkGZRrCc1myWgEfsputfSIPNF/oLv9kJNWacP3uuDOfecg3us7eg2OA +xo5zrYfn39GcBMF1WHAYRO/+PnJb9jrDuLAE8+ONNqjNulWNK9CStEhb6Te+yE6q +oeP6hJjFLi+nFLE9ymIo0A7gLQD5vzFvl+7v1ZNVnQkwRUsWoRiEVVGnv3Z1iZU6 +xStxgoHMl62V/P5cz4dr9vJM2adEWNZcVXl6mk1H8DRc1sRGnvs2l237oKWRVntJ +hoWnZ8qtD+3ZUqsX79QhVzUQBzKuBt6jwNhaHLGl5B+Or/zA9FezsOh6+Uc+fZaV +W7fFfeUyWwGy90XD3ybTrjzep9f3nt55Z2c+fu2iEwhoyImWLuC3+CVhf9Af59j9 +8/BophMJuATDJEtgi8rt4vLnfxKu250Mv2ZpbfF69EGTgFYbwc55zRfaUG9zlyCu +1YwMJ6HC9FUVtJp9gObSrirbzTH7mVaMjQkBLotazWbegzI+be8V3yT06C+ehD+2 +GdLWAVs9hp8gPHEUShb/XrgPpDSJmFlOiyeOFBO/j4edDACKqVcwdjBOMAoGCCqF +AwcBAQIDBEAIFX0fyZe20QKKhWm6WYX+S92Gt6zaXroXOvAmayzLfZ5Sd9C2t9zZ +JSg6M8RBUYpw/8ym5ou1o2nDa09M5zF3BCCpzyCQBI+rzfISeKvPV1ROfcXiYU93 +mwcl1xQV2G5/fgICB9A= + """) + password = u"Пароль для PFX" + + def test_shrouded_key_bag(self): + private_key_info_expected = b64decode(b""" +MGYCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEQEYbRu86z+1JFKDcPDN9UbTG +G2ki9enTqos4KpUU0j9IDpl1UXiaA1YDIwUjlAp+81GkLmyt8Fw6Gt/X5JZySAY= + """) + + pfx, tail = PFX().decode(self.pfx_raw) + self.assertSequenceEqual(tail, b"") + _, outer_safe_contents = pfx["authSafe"]["content"].defined + safe_contents, tail = OctetStringSafeContents().decode( + bytes(outer_safe_contents[0]["bagValue"]), + ) + self.assertSequenceEqual(tail, b"") + safe_bag = safe_contents[0] + shrouded_key_bag, tail = PKCS8ShroudedKeyBag().decode( + bytes(safe_bag["bagValue"]), + ) + self.assertSequenceEqual(tail, b"") + _, pbes2_params = shrouded_key_bag["encryptionAlgorithm"]["parameters"].defined + _, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined + _, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined + + key = gost34112012_pbkdf2( + password=self.password.encode("utf-8"), + salt=bytes(pbkdf2_params["salt"]["specified"]), + iterations=int(pbkdf2_params["iterationCount"]), + dklen=32, + ) + # key = hexdec("309dd0354c5603739403f2335e9e2055138f8b5c98b63009de0635eea1fd7ba8") + self.assertSequenceEqual( + cfb_decrypt( + key, + bytes(shrouded_key_bag["encryptedData"]), + iv=bytes(enc_scheme_params["iv"]), + sbox="id-tc26-gost-28147-param-Z", + ), + private_key_info_expected, + ) + + def test_encrypted_data(self): + cert_bag_expected = b64decode(b""" +MIIDSjCCA0YGCyqGSIb3DQEMCgEDoIIDHjCCAxoGCiqGSIb3DQEJFgGgggMKBIIDBjCCAwIwggKt +oAMCAQICEAHQaF8xH5bAAAAACycJAAEwDAYIKoUDBwEBAwIFADBgMQswCQYDVQQGEwJSVTEVMBMG +A1UEBwwM0JzQvtGB0LrQstCwMQ8wDQYDVQQKDAbQotCaMjYxKTAnBgNVBAMMIENBIGNlcnRpZmlj +YXRlIChQS0NTIzEyIGV4YW1wbGUpMB4XDTE1MDMyNzA3MjUwMFoXDTIwMDMyNzA3MjMwMFowZDEL +MAkGA1UEBhMCUlUxFTATBgNVBAcMDNCc0L7RgdC60LLQsDEPMA0GA1UECgwG0KLQmjI2MS0wKwYD +VQQDDCRUZXN0IGNlcnRpZmljYXRlIDEgKFBLQ1MjMTIgZXhhbXBsZSkwZjAfBggqhQMHAQEBATAT +BgcqhQMCAiMBBggqhQMHAQECAgNDAARA1xzymkpvr2dYJT8WTOX3Dt96/+hGsXNytUQpkWB5ImJM +4tg9AsC4RIUwV5H41MhG0uBRFweTzN6AsAdBvhTClYEJADI3MDkwMDAxo4IBKTCCASUwKwYDVR0Q +BCQwIoAPMjAxNTAzMjcwNzI1MDBagQ8yMDE2MDMyNzA3MjUwMFowDgYDVR0PAQH/BAQDAgTwMB0G +A1UdDgQWBBQhWOsRQ68yYN2Utg/owHoWcqsVbTAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH +AwQwDAYDVR0TAQH/BAIwADCBmQYDVR0jBIGRMIGOgBQmnc7Xh5ykb5t/BMwOkxA4drfEmqFkpGIw +YDELMAkGA1UEBhMCUlUxFTATBgNVBAcMDNCc0L7RgdC60LLQsDEPMA0GA1UECgwG0KLQmjI2MSkw +JwYDVQQDDCBDQSBjZXJ0aWZpY2F0ZSAoUEtDUyMxMiBleGFtcGxlKYIQAdBoXvL8TSAAAAALJwkA +ATAMBggqhQMHAQEDAgUAA0EA9oq0Vvk8kkgIwkp0x0J5eKtia4MNTiwKAm7jgnCZIx3O98BThaTX +3ZQhEo2RL9pTCPr6wFMheeJ+YdGMReXvsjEVMBMGCSqGSIb3DQEJFTEGBAQBAAAA + """) + + pfx, tail = PFX().decode(self.pfx_raw) + self.assertSequenceEqual(tail, b"") + _, outer_safe_contents = pfx["authSafe"]["content"].defined + _, encrypted_data = outer_safe_contents[1]["bagValue"].defined + _, pbes2_params = encrypted_data["encryptedContentInfo"]["contentEncryptionAlgorithm"]["parameters"].defined + _, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined + _, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined + key = gost34112012_pbkdf2( + password=self.password.encode("utf-8"), + salt=bytes(pbkdf2_params["salt"]["specified"]), + iterations=int(pbkdf2_params["iterationCount"]), + dklen=32, + ) + # key = hexdec("0e93d71339e7f53b79a0bc41f9109dd4fb60b30ae10736c1bb77b84c07681cfc") + self.assertSequenceEqual( + cfb_decrypt( + key, + bytes(encrypted_data["encryptedContentInfo"]["encryptedContent"]), + iv=bytes(enc_scheme_params["iv"]), + sbox="id-tc26-gost-28147-param-Z", + ), + cert_bag_expected, + ) + + def test_mac(self): + pfx, tail = PFX().decode(self.pfx_raw) + self.assertSequenceEqual(tail, b"") + _, outer_safe_contents = pfx["authSafe"]["content"].defined + mac_data = pfx["macData"] + mac_key = gost34112012_pbkdf2( + password=self.password.encode("utf-8"), + salt=bytes(mac_data["macSalt"]), + iterations=int(mac_data["iterations"]), + dklen=96, + )[-32:] + # mac_key = hexdec("cadbfbf3bceaa9b79f651508fac5abbeb4a13d0bd0e1876bd3c3efb2112128a5") + self.assertSequenceEqual( + hmac_new( + key=mac_key, + msg=SafeContents(outer_safe_contents).encode(), + digestmod=GOST34112012512, + ).digest(), + bytes(mac_data["mac"]["digest"]), + ) + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestPFX2020(TestCase): + """PFX test vectors from newer PKCS#12 update + """ + ca_prv_raw = hexdec("092F8D059E97E22B90B1AE99F0087FC4D26620B91550CBB437C191005A290810") + ca_curve = gost3410.CURVES["id-tc26-gost-3410-12-256-paramSetA"] + ca_cert = Certificate().decod(b64decode(b""" + MIIB+TCCAaagAwIBAgIEAYy6gTAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2MS + cwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEwMTAx + MDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA4MQ0wCwYDVQQKEwRUSzI2MScwJQYDVQQDEx + 5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwXjAXBggqhQMHAQEBATALBgkq + hQMHAQIBAQEDQwAEQBpKgpyPDnhQAJyLqy8Qs0XQhgxEhby6tSypqYimgbjpcKqtU6 + 4jpDXc3h3BxGxtl2oHJ/4YLZ/ll87dto3ltMqjgZgwgZUwYwYDVR0jBFwwWoAUrGwO + TERmokKW4p8JOyVm88ukUyqhPKQ6MDgxDTALBgNVBAoTBFRLMjYxJzAlBgNVBAMTHk + NBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6gTAdBgNVHQ4EFgQUrGwO + TERmokKW4p8JOyVm88ukUyowDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNBAB + Gg3nhgQ5oCKbqlEdVaRxH+1WX4wVkawGXuTYkr1AC2OWw3ZC14Vvg3nazm8UMWUZtk + vu1kJcHQ4jFKkjUeg2E= + """)) + ca_pub = gost3410.pub_unmarshal(bytes(OctetString().decod(bytes( + ca_cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"] + )))) + password = u"Пароль для PFX".encode("utf-8") + cert_test = Certificate().decod(b64decode(b""" + MIICLjCCAdugAwIBAgIEAYy6hDAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2MS + cwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEwMTAx + MDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYDVQQDEy + FPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDUxMi1iaXQwgaAwFwYIKoUDBwEBAQIw + CwYJKoUDBwECAQIBA4GEAASBgLSLt1q8KQ4YZVxioU+1LV9QhE7MHR9gBEh7S1yVNG + lqt7+rNG5VFqmrPM74rbUsOlhV8M+zZKprXdk35Oz8lSW/n2oIUHZxikXIH/SSHj4r + v3K/Puvz7hYTQSZl/xPdp78nUmjrEa6d5wfX8biEy2z0dgufFvAkMw1Ua4gdXqDOo4 + GHMIGEMGMGA1UdIwRcMFqAFKxsDkxEZqJCluKfCTslZvPLpFMqoTykOjA4MQ0wCwYD + VQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaX + SCBAGMuoEwHQYDVR0OBBYEFH4GVwmYDK1rCKhX7nkAWDrJ16CkMAoGCCqFAwcBAQMC + A0EACl6p8dAbpi9Hk+3mgMyI0WIh17IrlrSp/mB0F7ZzMt8XUD1Dwz3JrrnxeXnfMv + OA5BdUJ9hCyDgMVAGs/IcEEA== + """)) + prv_test_raw = b64decode(""" + MIHiAgEBMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAQRAEWkl+eblsHWs86SNgRKq + SxMOgGhbvR/uZ5/WWfdNG1axvUwVhpcXIxDZUmzQuNzqJBkseI7f5/JjXyTFRF1a + +YGBgQG0i7davCkOGGVcYqFPtS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO + +K21LDpYVfDPs2Sqa13ZN+Ts/JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0Em + Zf8T3ae/J1Jo6xGunecH1/G4hMts9HYLnxbwJDMNVGuIHV6gzg== + """) + + def test_cert_and_encrypted_key(self): + pfx_raw = b64decode(b""" + MIIFKwIBAzCCBMQGCSqGSIb3DQEHAaCCBLUEggSxMIIErTCCAswGCSqGSIb3DQEH + AaCCAr0EggK5MIICtTCCArEGCyqGSIb3DQEMCgEDoIICSjCCAkYGCiqGSIb3DQEJ + FgGgggI2BIICMjCCAi4wggHboAMCAQICBAGMuoQwCgYIKoUDBwEBAwIwODENMAsG + A1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYt + Yml0MB4XDTAxMDEwMTAwMDAwMFoXDTQ5MTIzMTAwMDAwMFowOzENMAsGA1UEChME + VEsyNjEqMCgGA1UEAxMhT1JJR0lOQVRPUjogR09TVCAzNC4xMC0xMiA1MTItYml0 + MIGgMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAQOBhAAEgYC0i7davCkOGGVcYqFP + tS1fUIROzB0fYARIe0tclTRpare/qzRuVRapqzzO+K21LDpYVfDPs2Sqa13ZN+Ts + /JUlv59qCFB2cYpFyB/0kh4+K79yvz7r8+4WE0EmZf8T3ae/J1Jo6xGunecH1/G4 + hMts9HYLnxbwJDMNVGuIHV6gzqOBhzCBhDBjBgNVHSMEXDBagBSsbA5MRGaiQpbi + nwk7JWbzy6RTKqE8pDowODENMAsGA1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsy + NjogR09TVCAzNC4xMC0xMiAyNTYtYml0ggQBjLqBMB0GA1UdDgQWBBR+BlcJmAyt + awioV+55AFg6ydegpDAKBggqhQMHAQEDAgNBAApeqfHQG6YvR5Pt5oDMiNFiIdey + K5a0qf5gdBe2czLfF1A9Q8M9ya658Xl53zLzgOQXVCfYQsg4DFQBrPyHBBAxVDAj + BgkqhkiG9w0BCRUxFgQUeVV0+dS25MICJChpmGc/8AoUwE0wLQYJKoZIhvcNAQkU + MSAeHgBwADEAMgBGAHIAaQBlAG4AZABsAHkATgBhAG0AZTCCAdkGCSqGSIb3DQEH + AaCCAcoEggHGMIIBwjCCAb4GCyqGSIb3DQEMCgECoIIBVzCCAVMwWQYJKoZIhvcN + AQUNMEwwKQYJKoZIhvcNAQUMMBwECKf4N7NMwugqAgIIADAMBggqhQMHAQEEAgUA + MB8GCSqFAwcBAQUCAjASBBAlmt2WDfaPJlsAs0mLKglzBIH1DMvEacbbWRNDVSnX + JLWygYrKoipdOjDA/2HEnBZ34uFOLNheUqiKpCPoFpbR2GBiVYVTVK9ibiczgaca + EQYzDXtcS0QCZOxpKWfteAlbdJLC/SqPurPYyKi0MVRUPROhbisFASDT38HDH1Dh + 0dL5f6ga4aPWLrWbbgWERFOoOPyh4DotlPF37AQOwiEjsbyyRHq3HgbWiaxQRuAh + eqHOn4QVGY92/HFvJ7u3TcnQdLWhTe/lh1RHLNF3RnXtN9if9zC23laDZOiWZplU + yLrUiTCbHrtn1RppPDmLFNMt9dJ7KKgCkOi7Zm5nhqPChbywX13wcfYxVDAjBgkq + hkiG9w0BCRUxFgQUeVV0+dS25MICJChpmGc/8AoUwE0wLQYJKoZIhvcNAQkUMSAe + HgBwADEAMgBGAHIAaQBlAG4AZABsAHkATgBhAG0AZTBeME4wCgYIKoUDBwEBAgME + QAkBKw4ihn7pSIYTEhu0bcvTPZjI3WgVxCkUVlOsc80G69EKFEOTnObGJGSKJ51U + KkOsXF0a7+VBZf3BcVVQh9UECIVEtO+VpuskAgIIAA== + """) + pfx = PFX().decod(pfx_raw) + _, outer_safe_contents = pfx["authSafe"]["content"].defined + + safe_contents = OctetStringSafeContents().decod(bytes( + outer_safe_contents[0]["bagValue"] + )) + safe_bag = safe_contents[0] + self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_certBag) + cert_bag = CertBag().decod(bytes(safe_bag["bagValue"])) + self.assertEqual(cert_bag["certId"], id_pkcs9_certTypes_x509Certificate) + _, cert = cert_bag["certValue"].defined + self.assertEqual(Certificate(cert), self.cert_test) + + safe_contents = OctetStringSafeContents().decod(bytes( + outer_safe_contents[1]["bagValue"] + )) + safe_bag = safe_contents[0] + self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_pkcs8ShroudedKeyBag) + shrouded_key_bag = PKCS8ShroudedKeyBag().decod(bytes(safe_bag["bagValue"])) + _, pbes2_params = shrouded_key_bag["encryptionAlgorithm"]["parameters"].defined + _, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined + _, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined + ukm = bytes(enc_scheme_params["ukm"]) + key = gost34112012_pbkdf2( + password=self.password, + salt=bytes(pbkdf2_params["salt"]["specified"]), + iterations=int(pbkdf2_params["iterationCount"]), + dklen=32, + ) + # key = hexdec("4b7ae649ca31dd5fe3243a91a5188c03f1d7049bec8e0d241c0e1e8c39ea4c1f") + key_enc, key_mac = kdf_tree_gostr3411_2012_256( + key, b"kdf tree", ukm[GOST3412Kuznechik.blocksize // 2:], 2, + ) + ciphertext = bytes(shrouded_key_bag["encryptedData"]) + plaintext = ctr_acpkm( + GOST3412Kuznechik, + GOST3412Kuznechik(key_enc).encrypt, + section_size=256 * 1024, + bs=GOST3412Kuznechik.blocksize, + data=ciphertext, + iv=ukm[:GOST3412Kuznechik.blocksize // 2], + ) + mac_expected = plaintext[-GOST3412Kuznechik.blocksize:] + plaintext = plaintext[:-GOST3412Kuznechik.blocksize] + mac = omac( + GOST3412Kuznechik(key_mac).encrypt, + GOST3412Kuznechik.blocksize, + plaintext, + ) + self.assertSequenceEqual(mac, mac_expected) + self.assertSequenceEqual(plaintext, self.prv_test_raw) + + mac_data = pfx["macData"] + mac_key = gost34112012_pbkdf2( + password=self.password, + salt=bytes(mac_data["macSalt"]), + iterations=int(mac_data["iterations"]), + dklen=96, + )[-32:] + # mac_key = hexdec("a81d1bc91a4a5cf1fd7320f92dda7e5b285816c3b20826a382d7ed0cbf3a9bf4") + self.assertSequenceEqual( + hmac_new( + key=mac_key, + msg=SafeContents(outer_safe_contents).encode(), + digestmod=GOST34112012512, + ).digest(), + bytes(mac_data["mac"]["digest"]), + ) + self.assertTrue(gost3410.verify( + self.ca_curve, + self.ca_pub, + GOST34112012256(cert["tbsCertificate"].encode()).digest()[::-1], + bytes(cert["signatureValue"]), + )) + + def test_encrypted_cert_and_key(self): + pfx_raw = b64decode(b""" + MIIFjAIBAzCCBSUGCSqGSIb3DQEHAaCCBRYEggUSMIIFDjCCA0EGCSqGSIb3DQEH + BqCCAzIwggMuAgEAMIIDJwYJKoZIhvcNAQcBMFUGCSqGSIb3DQEFDTBIMCkGCSqG + SIb3DQEFDDAcBAgUuSVGsSwGjQICCAAwDAYIKoUDBwEBBAIFADAbBgkqhQMHAQEF + AQIwDgQM9Hk3dagtS48+G/x+gIICwWGPqxxN+sTrKbruRf9R5Ya9cf5AtO1frqMn + f1eULfmZmTg/BdE51QQ+Vbnh3v1kmspr6h2+e4Wli+ndEeCWG6A6X/G22h/RAHW2 + YrVmf6cCWxW+YrqzT4h/8RQL/9haunD5LmHPLVsYrEai0OwbgXayDSwARVJQLQYq + sLNmZK5ViN+fRiS5wszVJ3AtVq8EuPt41aQEKwPy2gmH4S6WmnQRC6W7aoqmIifF + PJENJNn5K2M1J6zNESs6bFtYNKMArNqtvv3rioY6eAaaLy6AV6ljsekmqodHmQjv + Y4eEioJs0xhpXhZY69PXT+ZBeHv6MSheBhwXqxAd1DqtPTafMjNK8rqKCap9TtPG + vONvo5W9dgwegxRRQzlum8dzV4m1W9Aq4W7t8/UcxDWRz3k6ijFPlGaA9+8ZMTEO + RHhBRvM6OY2/VNNxbgxWfGYuPxpSi3YnCZIPmBEe5lU/Xv7KjzFusGM38F8YR61k + 4/QNpKI1QUv714YKfaUQznshGGzILv1NGID62pl1+JI3vuawi2mDMrmkuM9QFU9v + /kRP+c2uBHDuOGEUUSNhF08p7+w3vxplatGWXH9fmIsPBdk2f3wkn+rwoqrEuijM + I/bCAylU/M0DMKhAo9j31UYSZdi4fsfRWYDJMq/8FPn96tuo+oCpbqv3NUwpZM/8 + Li4xqgTHtYw/+fRG0/P6XadNEiII/TYjenLfVHXjAHOVJsVeCu/t3EsMYHQddNCh + rFk/Ic2PdIQOyB4/enpW0qrKegSbyZNuF1WI4zl4mI89L8dTQBUkhy45yQXZlDD8 + k1ErYdtdEsPtz/4zuSpbnmwCEIRoOuSXtGuJP+tbcWEXRKM2UBgi3qBjpn7DU18M + tsrRM9pDdadl8mT/Vfh9+B8dZBZVxgQu70lMPEGexbUkYHuFCCnyi9J0V92StbIz + Elxla1VebjCCAcUGCSqGSIb3DQEHAaCCAbYEggGyMIIBrjCCAaoGCyqGSIb3DQEM + CgECoIIBQzCCAT8wVQYJKoZIhvcNAQUNMEgwKQYJKoZIhvcNAQUMMBwECP0EQk0O + 1twvAgIIADAMBggqhQMHAQEEAgUAMBsGCSqFAwcBAQUBATAOBAzwxSqgAAAAAAAA + AAAEgeUqj9mI3RDfK5hMd0EeYws7foZK/5ANr2wUhP5qnDjAZgn76lExJ+wuvlnS + 9PChfWVugvdl/9XJgQvvr9Cu4pOh4ICXplchcy0dGk/MzItHRVC5wK2nTxwQ4kKT + kG9xhLFzoD16dhtqX0+/dQg9G8pE5EzCBIYRXLm1Arcz9k7KVsTJuNMjFrr7EQuu + Tr80ATSQOtsq50zpFyrpznVPGCrOdIjpymZxNdvw48bZxqTtRVDxCYATOGqz0pwH + ClWULHD9LIajLMB2GhBKyQw6ujIlltJs0T+WNdX/AT2FLi1LFSS3+Cj9MVQwIwYJ + KoZIhvcNAQkVMRYEFHlVdPnUtuTCAiQoaZhnP/AKFMBNMC0GCSqGSIb3DQEJFDEg + Hh4AcAAxADIARgByAGkAZQBuAGQAbAB5AE4AYQBtAGUwXjBOMAoGCCqFAwcBAQID + BEDp4e22JmXdnvR0xA99yQuzQuJ8pxBeOpsLm2dZQqt3Fje5zqW1uk/7VOcfV5r2 + bKm8nsLOs2rPT8hBOoeAZvOIBAjGIUHw6IjG2QICCAA= + """) + pfx = PFX().decod(pfx_raw) + _, outer_safe_contents = pfx["authSafe"]["content"].defined + + encrypted_data = EncryptedData().decod(bytes( + outer_safe_contents[0]["bagValue"] + )) + eci = encrypted_data["encryptedContentInfo"] + self.assertEqual(eci["contentEncryptionAlgorithm"]["algorithm"], id_pbes2) + pbes2_params = PBES2Params().decod(bytes( + eci["contentEncryptionAlgorithm"]["parameters"] + )) + _, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined + _, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined + ukm = bytes(enc_scheme_params["ukm"]) + key = gost34112012_pbkdf2( + password=self.password, + salt=bytes(pbkdf2_params["salt"]["specified"]), + iterations=int(pbkdf2_params["iterationCount"]), + dklen=32, + ) + # key = hexdec("d066a96fb326ba896a2352d3f40240a4ded6e7e7bd5b4db6b5241d631c8c381c") + key_enc, key_mac = kdf_tree_gostr3411_2012_256( + key, b"kdf tree", ukm[GOST3412Magma.blocksize // 2:], 2, + ) + ciphertext = bytes(eci["encryptedContent"]) + plaintext = ctr_acpkm( + GOST3412Magma, + GOST3412Magma(key_enc).encrypt, + section_size=8 * 1024, + bs=GOST3412Magma.blocksize, + data=ciphertext, + iv=ukm[:GOST3412Magma.blocksize // 2], + ) + mac_expected = plaintext[-GOST3412Magma.blocksize:] + plaintext = plaintext[:-GOST3412Magma.blocksize] + mac = omac( + GOST3412Magma(key_mac).encrypt, + GOST3412Magma.blocksize, + plaintext, + ) + self.assertSequenceEqual(mac, mac_expected) + + safe_contents = SafeContents().decod(plaintext) + safe_bag = safe_contents[0] + self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_certBag) + cert_bag = CertBag().decod(bytes(safe_bag["bagValue"])) + self.assertEqual(cert_bag["certId"], id_pkcs9_certTypes_x509Certificate) + _, cert = cert_bag["certValue"].defined + self.assertEqual(Certificate(cert), self.cert_test) + + safe_contents = OctetStringSafeContents().decod(bytes( + outer_safe_contents[1]["bagValue"] + )) + safe_bag = safe_contents[0] + self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_pkcs8ShroudedKeyBag) + shrouded_key_bag = PKCS8ShroudedKeyBag().decod(bytes(safe_bag["bagValue"])) + _, pbes2_params = shrouded_key_bag["encryptionAlgorithm"]["parameters"].defined + _, pbkdf2_params = pbes2_params["keyDerivationFunc"]["parameters"].defined + _, enc_scheme_params = pbes2_params["encryptionScheme"]["parameters"].defined + ukm = bytes(enc_scheme_params["ukm"]) + key = gost34112012_pbkdf2( + password=self.password, + salt=bytes(pbkdf2_params["salt"]["specified"]), + iterations=int(pbkdf2_params["iterationCount"]), + dklen=32, + ) + # key = hexdec("f840d001fd11441e0fb7ccf48f471915e5bf35275309dbe7ade9da4fe460ba7e") + ciphertext = bytes(shrouded_key_bag["encryptedData"]) + plaintext = ctr_acpkm( + GOST3412Magma, + GOST3412Magma(key).encrypt, + section_size=8 * 1024, + bs=GOST3412Magma.blocksize, + data=ciphertext, + iv=ukm[:GOST3412Magma.blocksize // 2], + ) + self.assertSequenceEqual(plaintext, self.prv_test_raw) + + mac_data = pfx["macData"] + mac_key = gost34112012_pbkdf2( + password=self.password, + salt=bytes(mac_data["macSalt"]), + iterations=int(mac_data["iterations"]), + dklen=96, + )[-32:] + # mac_key = hexdec("084f81782af1534ffd67e3c579c14cb45d7a6f659f46fdbb51a552e874e66fb2") + self.assertSequenceEqual( + hmac_new( + key=mac_key, + msg=SafeContents(outer_safe_contents).encode(), + digestmod=GOST34112012512, + ).digest(), + bytes(mac_data["mac"]["digest"]), + ) + + def test_dh(self): + curve = gost3410.CURVES["id-tc26-gost-3410-12-256-paramSetA"] + # sender_prv_raw = hexdec("0B20810E449978C7C3B76C6FF77A16C532421139344A058EF56310B6B6F377E8") + sender_cert = Certificate().decod(b64decode(""" + MIIB6zCCAZigAwIBAgIEAYy6gjAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2 + MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw + MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA7MQ0wCwYDVQQKEwRUSzI2MSowKAYD + VQQDEyFPUklHSU5BVE9SOiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwXjAXBggqhQMH + AQEBATALBgkqhQMHAQIBAQEDQwAEQJYpDRNiWWqDgaZje0EmLLOldQ35o5X1ZuZN + SKequYQc/soI3OgDMWD7ThJJCk01IelCeb6MsBmG4lol+pnpVtOjgYcwgYQwYwYD + VR0jBFwwWoAUrGwOTERmokKW4p8JOyVm88ukUyqhPKQ6MDgxDTALBgNVBAoTBFRL + MjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdIIEAYy6 + gTAdBgNVHQ4EFgQUPx5RgcjkifhlJm4/jQdkbm30rVQwCgYIKoUDBwEBAwIDQQA6 + 8x7Vk6PvP/8xOGHhf8PuqaXAYskSyJPuBu+3Bo/PEj10devwc1J9uYWIDCGdKKPy + bSlnQHqUPBBPM30YX1YN + """)) + recipient_prv_raw = hexdec("0DC8DC1FF2BC114BABC3F1CA8C51E4F58610427E197B1C2FBDBA4AE58CBFB7CE")[::-1] + recipient_prv = gost3410.prv_unmarshal(recipient_prv_raw) + recipient_cert = Certificate().decod(b64decode(""" + MIIB6jCCAZegAwIBAgIEAYy6gzAKBggqhQMHAQEDAjA4MQ0wCwYDVQQKEwRUSzI2 + MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQwHhcNMDEw + MTAxMDAwMDAwWhcNNDkxMjMxMDAwMDAwWjA6MQ0wCwYDVQQKEwRUSzI2MSkwJwYD + VQQDEyBSRUNJUElFTlQ6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdDBeMBcGCCqFAwcB + AQEBMAsGCSqFAwcBAgEBAQNDAARAvyeCGXMsYwpYe5aE0w8w3m4vpKQapGInqpnF + lv7h08psFP0s1W80q3BR534F4TmR+o5+iU+AW6ycvWuc73JEQ6OBhzCBhDBjBgNV + HSMEXDBagBSsbA5MRGaiQpbinwk7JWbzy6RTKqE8pDowODENMAsGA1UEChMEVEsy + NjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0ggQBjLqB + MB0GA1UdDgQWBBQ35gHPN1bx8l2eEMTbrtIg+5MU0TAKBggqhQMHAQEDAgNBABF2 + RHDaRqQuBS2yu7yGIGFgA6c/LG4GKjSOwYsRVmXJNNkQ4TB7PB8j3q7gx2koPsVB + m90WfMWSL6SNSh3muuM= + """)) + self.assertTrue(gost3410.verify( + self.ca_curve, + self.ca_pub, + GOST34112012256(sender_cert["tbsCertificate"].encode()).digest()[::-1], + bytes(sender_cert["signatureValue"]), + )) + self.assertTrue(gost3410.verify( + self.ca_curve, + self.ca_pub, + GOST34112012256(recipient_cert["tbsCertificate"].encode()).digest()[::-1], + bytes(recipient_cert["signatureValue"]), + )) + + pfx_raw = b64decode(""" + MIIKVwIBAzCCClAGCSqGSIb3DQEHAqCCCkEwggo9AgEBMQwwCgYIKoUDBwEBAgIw + ggcjBgkqhkiG9w0BBwGgggcUBIIHEDCCBwwwggKdBgkqhkiG9w0BBwGgggKOBIIC + ijCCAoYwggKCBgsqhkiG9w0BDAoBA6CCAkowggJGBgoqhkiG9w0BCRYBoIICNgSC + AjIwggIuMIIB26ADAgECAgQBjLqEMAoGCCqFAwcBAQMCMDgxDTALBgNVBAoTBFRL + MjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1QgMzQuMTAtMTIgMjU2LWJpdDAeFw0w + MTAxMDEwMDAwMDBaFw00OTEyMzEwMDAwMDBaMDsxDTALBgNVBAoTBFRLMjYxKjAo + BgNVBAMTIU9SSUdJTkFUT1I6IEdPU1QgMzQuMTAtMTIgNTEyLWJpdDCBoDAXBggq + hQMHAQEBAjALBgkqhQMHAQIBAgEDgYQABIGAtIu3WrwpDhhlXGKhT7UtX1CETswd + H2AESHtLXJU0aWq3v6s0blUWqas8zvittSw6WFXwz7Nkqmtd2Tfk7PyVJb+faghQ + dnGKRcgf9JIePiu/cr8+6/PuFhNBJmX/E92nvydSaOsRrp3nB9fxuITLbPR2C58W + 8CQzDVRriB1eoM6jgYcwgYQwYwYDVR0jBFwwWoAUrGwOTERmokKW4p8JOyVm88uk + UyqhPKQ6MDgxDTALBgNVBAoTBFRLMjYxJzAlBgNVBAMTHkNBIFRLMjY6IEdPU1Qg + MzQuMTAtMTIgMjU2LWJpdIIEAYy6gTAdBgNVHQ4EFgQUfgZXCZgMrWsIqFfueQBY + OsnXoKQwCgYIKoUDBwEBAwIDQQAKXqnx0BumL0eT7eaAzIjRYiHXsiuWtKn+YHQX + tnMy3xdQPUPDPcmuufF5ed8y84DkF1Qn2ELIOAxUAaz8hwQQMSUwIwYJKoZIhvcN + AQkVMRYEFHlVdPnUtuTCAiQoaZhnP/AKFMBNMIIEZwYJKoZIhvcNAQcDoIIEWDCC + BFQCAQKgggHzoIIB7zCCAeswggGYoAMCAQICBAGMuoIwCgYIKoUDBwEBAwIwODEN + MAsGA1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAy + NTYtYml0MB4XDTAxMDEwMTAwMDAwMFoXDTQ5MTIzMTAwMDAwMFowOzENMAsGA1UE + ChMEVEsyNjEqMCgGA1UEAxMhT1JJR0lOQVRPUjogR09TVCAzNC4xMC0xMiAyNTYt + Yml0MF4wFwYIKoUDBwEBAQEwCwYJKoUDBwECAQEBA0MABECWKQ0TYllqg4GmY3tB + JiyzpXUN+aOV9WbmTUinqrmEHP7KCNzoAzFg+04SSQpNNSHpQnm+jLAZhuJaJfqZ + 6VbTo4GHMIGEMGMGA1UdIwRcMFqAFKxsDkxEZqJCluKfCTslZvPLpFMqoTykOjA4 + MQ0wCwYDVQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEy + IDI1Ni1iaXSCBAGMuoEwHQYDVR0OBBYEFD8eUYHI5In4ZSZuP40HZG5t9K1UMAoG + CCqFAwcBAQMCA0EAOvMe1ZOj7z//MThh4X/D7qmlwGLJEsiT7gbvtwaPzxI9dHXr + 8HNSfbmFiAwhnSij8m0pZ0B6lDwQTzN9GF9WDTGB/6GB/AIBA6BCMEAwODENMAsG + A1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYt + Yml0AgQBjLqCoSIEIBt4fjey+k8C1D3OaMca8wl6h3j3C6OAbrx8rmxXktsQMBcG + CSqFAwcBAQcCATAKBggqhQMHAQEGATB2MHQwQDA4MQ0wCwYDVQQKEwRUSzI2MScw + JQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1Ni1iaXQCBAGMuoMEMJkp + Wae6IVfaY3mP0izRY7ifc41fATXdJ2tmTl+1vitkSE2vLCKXDLl90KfHA6gNmDCC + AVQGCSqGSIb3DQEHATAfBgkqhQMHAQEFAgEwEgQQFhEshEBO2LkAAAAAAAAAAICC + ASQYvLpT/8azEXJfekyGuyvE9UkVX+Ao8sfu9My/c4WAVRNMhZkCqD+BbPwBsIzN + sXZIi9rXGAfsPz7xaO9EUFZPjNOWtF/E01oJgG+gYLFn7qAiEFcmRLptSHuanNHn + 7Yol6IHushX4UaW9hEa/L6eFQx/hoDhrNZnWTXNZtNuHuMGC9dzhHhTxfkdjZYXD + v+M7psVj58JutE3U2d4pgxKcBPdMO4vl4+27cIKxQZFZU2zuCVJLYLqmPT5pCBkM + mJqy7bZwHOJ9kBq/TGUf8iJGYSCNre3RTNLbcTTk7rZrbiMkFsG3borzenpouS5E + BcCkBt8Mj0nvsMCu9ipHTuWww7LltlkXCjlNXFUi6ZI3VyHW5CDpghujQWiZxiAc + JuGl6GwZoIIB7zCCAeswggGYoAMCAQICBAGMuoIwCgYIKoUDBwEBAwIwODENMAsG + A1UEChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYt + Yml0MB4XDTAxMDEwMTAwMDAwMFoXDTQ5MTIzMTAwMDAwMFowOzENMAsGA1UEChME + VEsyNjEqMCgGA1UEAxMhT1JJR0lOQVRPUjogR09TVCAzNC4xMC0xMiAyNTYtYml0 + MF4wFwYIKoUDBwEBAQEwCwYJKoUDBwECAQEBA0MABECWKQ0TYllqg4GmY3tBJiyz + pXUN+aOV9WbmTUinqrmEHP7KCNzoAzFg+04SSQpNNSHpQnm+jLAZhuJaJfqZ6VbT + o4GHMIGEMGMGA1UdIwRcMFqAFKxsDkxEZqJCluKfCTslZvPLpFMqoTykOjA4MQ0w + CwYDVQQKEwRUSzI2MScwJQYDVQQDEx5DQSBUSzI2OiBHT1NUIDM0LjEwLTEyIDI1 + Ni1iaXSCBAGMuoEwHQYDVR0OBBYEFD8eUYHI5In4ZSZuP40HZG5t9K1UMAoGCCqF + AwcBAQMCA0EAOvMe1ZOj7z//MThh4X/D7qmlwGLJEsiT7gbvtwaPzxI9dHXr8HNS + fbmFiAwhnSij8m0pZ0B6lDwQTzN9GF9WDTGCAQ4wggEKAgEBMEAwODENMAsGA1UE + ChMEVEsyNjEnMCUGA1UEAxMeQ0EgVEsyNjogR09TVCAzNC4xMC0xMiAyNTYtYml0 + AgQBjLqCMAoGCCqFAwcBAQICoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAc + BgkqhkiG9w0BCQUxDxcNMjEwNDE0MTkyMTEyWjAvBgkqhkiG9w0BCQQxIgQg1XOA + zNa710QuXsn5+yIf3cNTiFOQMgTiBRJBz8Tr4I0wCgYIKoUDBwEBAQEEQALINal9 + 7wHXYiG+w0yzSkKOs0jRZew0S73r/cfk/sUoM3HKKIEbKruvlAdiOqX/HLFSEx/s + kxFG6QUFH8uuoX8= + """) + pfx = PFX().decod(pfx_raw) + self.assertEqual(pfx["authSafe"]["contentType"], id_signedData) + + sd = SignedData().decod(bytes(pfx["authSafe"]["content"])) + self.assertEqual(sd["certificates"][0]["certificate"], sender_cert) + si = sd["signerInfos"][0] + self.assertEqual( + si["digestAlgorithm"]["algorithm"], + id_tc26_gost3411_2012_256, + ) + digest = [ + bytes(attr["attrValues"][0].defined[1]) for attr in si["signedAttrs"] + if attr["attrType"] == id_messageDigest + ][0] + sender_pub = gost3410.pub_unmarshal(bytes(OctetString().decod(bytes( + sender_cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"] + )))) + content = bytes(sd["encapContentInfo"]["eContent"]) + self.assertSequenceEqual(digest, GOST34112012256(content).digest()) + self.assertTrue(gost3410.verify( + curve, + sender_pub, + GOST34112012256( + SignedAttributes(si["signedAttrs"]).encode() + ).digest()[::-1], + bytes(si["signature"]), + )) + + outer_safe_contents = SafeContents().decod(content) + + safe_bag = outer_safe_contents[0] + self.assertEqual(safe_bag["bagId"], id_data) + safe_contents = OctetStringSafeContents().decod(bytes(safe_bag["bagValue"])) + safe_bag = safe_contents[0] + self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_certBag) + cert_bag = CertBag().decod(bytes(safe_bag["bagValue"])) + self.assertEqual(cert_bag["certId"], id_pkcs9_certTypes_x509Certificate) + _, cert = cert_bag["certValue"].defined + self.assertEqual(Certificate(cert), self.cert_test) + + safe_bag = outer_safe_contents[1] + self.assertEqual(safe_bag["bagId"], id_envelopedData) + ed = EnvelopedData().decod(bytes(safe_bag["bagValue"])) + kari = ed["recipientInfos"][0]["kari"] + ukm = bytes(kari["ukm"]) + self.assertEqual( + kari["keyEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_kuznyechik_wrap_kexp15, + ) + self.assertEqual( + kari["keyEncryptionAlgorithm"]["parameters"].defined[1]["algorithm"], + id_tc26_agreement_gost3410_2012_256, + ) + kexp = bytes(kari["recipientEncryptedKeys"][0]["encryptedKey"]) + keymat = keg(curve, recipient_prv, sender_pub, ukm) + kim, kek = keymat[:KEYSIZE], keymat[KEYSIZE:] + cek = kimp15( + GOST3412Kuznechik(kek).encrypt, + GOST3412Kuznechik(kim).encrypt, + GOST3412Kuznechik.blocksize, + kexp, + ukm[24:24 + GOST3412Kuznechik.blocksize // 2], + ) + eci = ed["encryptedContentInfo"] + self.assertEqual( + eci["contentEncryptionAlgorithm"]["algorithm"], + id_gostr3412_2015_kuznyechik_ctracpkm, + ) + eci_ukm = bytes( + eci["contentEncryptionAlgorithm"]["parameters"].defined[1]["ukm"] + ) + content = ctr_acpkm( + GOST3412Kuznechik, + GOST3412Kuznechik(cek).encrypt, + 256 * 1024, + GOST3412Kuznechik.blocksize, + bytes(eci["encryptedContent"]), + eci_ukm[:GOST3412Kuznechik.blocksize // 2], + ) + + safe_contents = SafeContents().decod(content) + safe_bag = safe_contents[0] + self.assertEqual(safe_bag["bagId"], id_pkcs12_bagtypes_keyBag) + KeyBag().decod(bytes(safe_bag["bagValue"])) + self.assertSequenceEqual(bytes(safe_bag["bagValue"]), self.prv_test_raw) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_wrap.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_wrap.py new file mode 100644 index 0000000..7ecf8ee --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_wrap.py @@ -0,0 +1,111 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from os import urandom +from unittest import TestCase + +from pygost.gost28147 import DEFAULT_SBOX +from pygost.gost3412 import GOST3412Kuznechik +from pygost.gost3412 import GOST3412Magma +from pygost.utils import hexdec +from pygost.wrap import kexp15 +from pygost.wrap import kimp15 +from pygost.wrap import unwrap_cryptopro +from pygost.wrap import unwrap_gost +from pygost.wrap import wrap_cryptopro +from pygost.wrap import wrap_gost + + +class WrapGostTest(TestCase): + def test_symmetric(self): + for sbox in (DEFAULT_SBOX, "id-tc26-gost-28147-param-Z"): + for _ in range(1 << 8): + kek = urandom(32) + cek = urandom(32) + ukm = urandom(8) + wrapped = wrap_gost(ukm, kek, cek, sbox=sbox) + unwrapped = unwrap_gost(kek, wrapped, sbox=sbox) + self.assertSequenceEqual(unwrapped, cek) + + def test_invalid_length(self): + with self.assertRaises(ValueError): + unwrap_gost(urandom(32), urandom(41)) + with self.assertRaises(ValueError): + unwrap_gost(urandom(32), urandom(45)) + + +class WrapCryptoproTest(TestCase): + def test_symmetric(self): + for sbox in (DEFAULT_SBOX, "id-tc26-gost-28147-param-Z"): + for _ in range(1 << 8): + kek = urandom(32) + cek = urandom(32) + ukm = urandom(8) + wrapped = wrap_cryptopro(ukm, kek, cek, sbox=sbox) + unwrapped = unwrap_cryptopro(kek, wrapped, sbox=sbox) + self.assertSequenceEqual(unwrapped, cek) + + +class TestVectorKExp15(TestCase): + """Test vectors from Р 1323565.1.017-2018 + """ + key = hexdec("8899AABBCCDDEEFF0011223344556677FEDCBA98765432100123456789ABCDEF") + key_enc = hexdec("202122232425262728292A2B2C2D2E2F38393A3B3C3D3E3F3031323334353637") + key_mac = hexdec("08090A0B0C0D0E0F0001020304050607101112131415161718191A1B1C1D1E1F") + + def test_magma(self): + iv = hexdec("67BED654") + kexp = kexp15( + GOST3412Magma(self.key_enc).encrypt, + GOST3412Magma(self.key_mac).encrypt, + GOST3412Magma.blocksize, + self.key, + iv, + ) + self.assertSequenceEqual(kexp, hexdec(""" +CF D5 A1 2D 5B 81 B6 E1 E9 9C 91 6D 07 90 0C 6A +C1 27 03 FB 3A BD ED 55 56 7B F3 74 2C 89 9C 75 +5D AF E7 B4 2E 3A 8B D9 + """.replace("\n", "").replace(" ", ""))) + self.assertSequenceEqual(kimp15( + GOST3412Magma(self.key_enc).encrypt, + GOST3412Magma(self.key_mac).encrypt, + GOST3412Magma.blocksize, + kexp, + iv, + ), self.key) + + def test_kuznechik(self): + iv = hexdec("0909472DD9F26BE8") + kexp = kexp15( + GOST3412Kuznechik(self.key_enc).encrypt, + GOST3412Kuznechik(self.key_mac).encrypt, + GOST3412Kuznechik.blocksize, + self.key, + iv, + ) + self.assertSequenceEqual(kexp, hexdec(""" +E3 61 84 E8 4E 8D 73 6F F3 6C C2 E5 AE 06 5D C6 +56 B2 3C 20 F5 49 B0 2F DF F8 8E 1F 3F 30 D8 C2 +9A 53 F3 CA 55 4D BA D8 0D E1 52 B9 A4 62 5B 32 + """.replace("\n", "").replace(" ", ""))) + self.assertSequenceEqual(kimp15( + GOST3412Kuznechik(self.key_enc).encrypt, + GOST3412Kuznechik(self.key_mac).encrypt, + GOST3412Kuznechik.blocksize, + kexp, + iv, + ), self.key) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/test_x509.py b/xmlrpcserver/deps/pygost-5.12/pygost/test_x509.py new file mode 100644 index 0000000..e9fccb7 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/test_x509.py @@ -0,0 +1,433 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from base64 import b64decode +from unittest import skipIf +from unittest import TestCase + +from pygost.gost3410 import CURVES +from pygost.gost3410 import prv_unmarshal +from pygost.gost3410 import pub_marshal +from pygost.gost3410 import pub_unmarshal +from pygost.gost3410 import public_key +from pygost.gost3410 import verify +from pygost.gost34112012256 import GOST34112012256 +from pygost.gost34112012512 import GOST34112012512 +from pygost.utils import hexdec + +try: + + from pyderasn import Any + from pyderasn import BitString + from pyderasn import Boolean + from pyderasn import GeneralizedTime + from pyderasn import Integer + from pyderasn import OctetString + from pyderasn import PrintableString + from pyderasn import UTCTime + + from pygost.asn1schemas.oids import id_at_commonName + from pygost.asn1schemas.oids import id_ce_basicConstraints + from pygost.asn1schemas.oids import id_GostR3410_2001_TestParamSet + from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256 + from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetA + from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512 + from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetTest + from pygost.asn1schemas.oids import id_tc26_gost3411_2012_256 + from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_256 + from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_512 + from pygost.asn1schemas.pkcs10 import Attributes + from pygost.asn1schemas.pkcs10 import CertificationRequest + from pygost.asn1schemas.pkcs10 import CertificationRequestInfo + from pygost.asn1schemas.x509 import AlgorithmIdentifier + from pygost.asn1schemas.x509 import AttributeType + from pygost.asn1schemas.x509 import AttributeTypeAndValue + from pygost.asn1schemas.x509 import AttributeValue + from pygost.asn1schemas.x509 import BasicConstraints + from pygost.asn1schemas.x509 import Certificate + from pygost.asn1schemas.x509 import CertificateList + from pygost.asn1schemas.x509 import CertificateSerialNumber + from pygost.asn1schemas.x509 import Extension + from pygost.asn1schemas.x509 import Extensions + from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters + from pygost.asn1schemas.x509 import Name + from pygost.asn1schemas.x509 import RDNSequence + from pygost.asn1schemas.x509 import RelativeDistinguishedName + from pygost.asn1schemas.x509 import SubjectPublicKeyInfo + from pygost.asn1schemas.x509 import TBSCertificate + from pygost.asn1schemas.x509 import TBSCertList + from pygost.asn1schemas.x509 import Time + from pygost.asn1schemas.x509 import Validity + from pygost.asn1schemas.x509 import Version + +except ImportError: + pyderasn_exists = False +else: + pyderasn_exists = True + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestCertificate(TestCase): + """Certificate test vectors from "Использования алгоритмов ГОСТ Р + 34.10, ГОСТ Р 34.11 в профиле сертификата и списке отзыва + сертификатов (CRL) инфраструктуры открытых ключей X.509" + (TK26IOK.pdf) + """ + + def process_cert(self, curve_name, hasher, prv_key_raw, cert_raw): + cert, tail = Certificate().decode(cert_raw, ctx={ + "defines_by_path": ( + ( + ( + "tbsCertificate", + "subjectPublicKeyInfo", + "algorithm", + "algorithm", + ), + ( + ( + ("..", "subjectPublicKey"), + { + id_tc26_gost3410_2012_256: OctetString(), + id_tc26_gost3410_2012_512: OctetString(), + }, + ), + ), + ), + ), + }) + self.assertSequenceEqual(tail, b"") + curve = CURVES[curve_name] + prv_key = prv_unmarshal(prv_key_raw) + spk = cert["tbsCertificate"]["subjectPublicKeyInfo"]["subjectPublicKey"] + self.assertIsNotNone(spk.defined) + _, pub_key_raw = spk.defined + pub_key = pub_unmarshal(bytes(pub_key_raw)) + self.assertSequenceEqual(pub_key, public_key(curve, prv_key)) + self.assertTrue(verify( + curve, + pub_key, + hasher(cert["tbsCertificate"].encode()).digest()[::-1], + bytes(cert["signatureValue"]), + )) + + def test_256(self): + cert_raw = b64decode(""" +MIICYjCCAg+gAwIBAgIBATAKBggqhQMHAQEDAjBWMSkwJwYJKoZIhvcNAQkBFhpH +b3N0UjM0MTAtMjAxMkBleGFtcGxlLmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIw +MTIgKDI1NiBiaXQpIGV4YW1wbGUwHhcNMTMxMTA1MTQwMjM3WhcNMzAxMTAxMTQw +MjM3WjBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxlLmNv +bTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgKDI1NiBiaXQpIGV4YW1wbGUwZjAf +BggqhQMHAQEBATATBgcqhQMCAiQABggqhQMHAQECAgNDAARAut/Qw1MUq9KPqkdH +C2xAF3K7TugHfo9n525D2s5mFZdD5pwf90/i4vF0mFmr9nfRwMYP4o0Pg1mOn5Rl +aXNYraOBwDCBvTAdBgNVHQ4EFgQU1fIeN1HaPbw+XWUzbkJ+kHJUT0AwCwYDVR0P +BAQDAgHGMA8GA1UdEwQIMAYBAf8CAQEwfgYDVR0BBHcwdYAU1fIeN1HaPbw+XWUz +bkJ+kHJUT0ChWqRYMFYxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDEyQGV4 +YW1wbGUuY29tMSkwJwYDVQQDEyBHb3N0UjM0MTAtMjAxMiAoMjU2IGJpdCkgZXhh +bXBsZYIBATAKBggqhQMHAQEDAgNBAF5bm4BbARR6hJLEoWJkOsYV3Hd7kXQQjz3C +dqQfmHrz6TI6Xojdh/t8ckODv/587NS5/6KsM77vc6Wh90NAT2s= + """) + prv_key_raw = hexdec("BFCF1D623E5CDD3032A7C6EABB4A923C46E43D640FFEAAF2C3ED39A8FA399924")[::-1] + self.process_cert( + "id-GostR3410-2001-CryptoPro-XchA-ParamSet", + GOST34112012256, + prv_key_raw, + cert_raw, + ) + + def test_512(self): + cert_raw = b64decode(""" +MIIC6DCCAlSgAwIBAgIBATAKBggqhQMHAQEDAzBWMSkwJwYJKoZIhvcNAQkBFhpH +b3N0UjM0MTAtMjAxMkBleGFtcGxlLmNvbTEpMCcGA1UEAxMgR29zdFIzNDEwLTIw +MTIgKDUxMiBiaXQpIGV4YW1wbGUwHhcNMTMxMDA0MDczNjA0WhcNMzAxMDAxMDcz +NjA0WjBWMSkwJwYJKoZIhvcNAQkBFhpHb3N0UjM0MTAtMjAxMkBleGFtcGxlLmNv +bTEpMCcGA1UEAxMgR29zdFIzNDEwLTIwMTIgKDUxMiBiaXQpIGV4YW1wbGUwgaow +IQYIKoUDBwEBAQIwFQYJKoUDBwECAQICBggqhQMHAQECAwOBhAAEgYATGQ9VCiM5 +FRGCQ8MEz2F1dANqhaEuywa8CbxOnTvaGJpFQVXQwkwvLFAKh7hk542vOEtxpKtT +CXfGf84nRhMH/Q9bZeAc2eO/yhxrsQhTBufa1Fuou2oe/jUOaG6RAtUUvRzhNTpp +RGGl1+EIY2vzzUua9j9Ol/gAoy/LNKQIfqOBwDCBvTAdBgNVHQ4EFgQUPcbTRXJZ +nHtjj+eBP7b5lcTMekIwCwYDVR0PBAQDAgHGMA8GA1UdEwQIMAYBAf8CAQEwfgYD +VR0BBHcwdYAUPcbTRXJZnHtjj+eBP7b5lcTMekKhWqRYMFYxKTAnBgkqhkiG9w0B +CQEWGkdvc3RSMzQxMC0yMDEyQGV4YW1wbGUuY29tMSkwJwYDVQQDEyBHb3N0UjM0 +MTAtMjAxMiAoNTEyIGJpdCkgZXhhbXBsZYIBATAKBggqhQMHAQEDAwOBgQBObS7o +ppPTXzHyVR1DtPa8b57nudJzI4czhsfeX5HDntOq45t9B/qSs8dC6eGxbhHZ9zCO +SFtxWYdmg0au8XI9Xb8vTC1qdwWID7FFjMWDNQZb6lYh/J+8F2xKylvB5nIlRZqO +o3eUNFkNyHJwQCk2WoOlO16zwGk2tdKH4KmD5w== + """) + prv_key_raw = hexdec("3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B")[::-1] + self.process_cert( + "id-tc26-gost-3410-12-512-paramSetB", + GOST34112012512, + prv_key_raw, + cert_raw, + ) + + +@skipIf(not pyderasn_exists, "PyDERASN dependency is required") +class TestRFC4491bis(TestCase): + """Test vectors from https://tools.ietf.org/html/draft-deremin-rfc4491-bis-02 + """ + + def _test_vector( + self, + curve_name, + hsh, + ai_spki, + ai_sign, + cert_serial, + prv_hex, + cr_sign_hex, + cr_b64, + c_sign_hex, + c_b64, + crl_sign_hex, + crl_b64, + ): + prv_raw = hexdec(prv_hex)[::-1] + prv = prv_unmarshal(prv_raw) + curve = CURVES[curve_name] + pub = public_key(curve, prv) + pub_raw = pub_marshal(pub) + subj = Name(("rdnSequence", RDNSequence([ + RelativeDistinguishedName(( + AttributeTypeAndValue(( + ("type", AttributeType(id_at_commonName)), + ("value", AttributeValue(PrintableString("Example"))), + )), + )) + ]))) + spki = SubjectPublicKeyInfo(( + ("algorithm", ai_spki), + ("subjectPublicKey", BitString(OctetString(pub_raw).encode())), + )) + + # Certification request + cri = CertificationRequestInfo(( + ("version", Integer(0)), + ("subject", subj), + ("subjectPKInfo", spki), + ("attributes", Attributes()), + )) + sign = hexdec(cr_sign_hex) + self.assertTrue(verify( + curve, + pub, + hsh(cri.encode()).digest()[::-1], + sign, + )) + cr = CertificationRequest(( + ("certificationRequestInfo", cri), + ("signatureAlgorithm", ai_sign), + ("signature", BitString(sign)), + )) + self.assertSequenceEqual(cr.encode(), b64decode(cr_b64)) + + # Certificate + tbs = TBSCertificate(( + ("version", Version("v3")), + ("serialNumber", CertificateSerialNumber(cert_serial)), + ("signature", ai_sign), + ("issuer", subj), + ("validity", Validity(( + ("notBefore", Time(("utcTime", UTCTime(b"010101000000Z")))), + ("notAfter", Time(("generalTime", GeneralizedTime(b"20501231000000Z")))), + ))), + ("subject", subj), + ("subjectPublicKeyInfo", spki), + ("extensions", Extensions(( + Extension(( + ("extnID", id_ce_basicConstraints), + ("critical", Boolean(True)), + ("extnValue", OctetString( + BasicConstraints((("cA", Boolean(True)),)).encode() + )), + )), + ))), + )) + sign = hexdec(c_sign_hex) + self.assertTrue(verify( + curve, + pub, + hsh(tbs.encode()).digest()[::-1], + sign, + )) + cert = Certificate(( + ("tbsCertificate", tbs), + ("signatureAlgorithm", ai_sign), + ("signatureValue", BitString(sign)), + )) + self.assertSequenceEqual(cert.encode(), b64decode(c_b64)) + + # CRL + tbs = TBSCertList(( + ("version", Version("v2")), + ("signature", ai_sign), + ("issuer", subj), + ("thisUpdate", Time(("utcTime", UTCTime(b"140101000000Z")))), + ("nextUpdate", Time(("utcTime", UTCTime(b"140102000000Z")))), + )) + sign = hexdec(crl_sign_hex) + self.assertTrue(verify( + curve, + pub, + hsh(tbs.encode()).digest()[::-1], + sign, + )) + crl = CertificateList(( + ("tbsCertList", tbs), + ("signatureAlgorithm", ai_sign), + ("signatureValue", BitString(sign)), + )) + self.assertSequenceEqual(crl.encode(), b64decode(crl_b64)) + + def test_256_test_paramset(self): + self._test_vector( + "id-GostR3410-2001-TestParamSet", + GOST34112012256, + AlgorithmIdentifier(( + ("algorithm", id_tc26_gost3410_2012_256), + ("parameters", Any( + GostR34102012PublicKeyParameters(( + ("publicKeyParamSet", id_GostR3410_2001_TestParamSet), + ("digestParamSet", id_tc26_gost3411_2012_256), + )) + )), + )), + AlgorithmIdentifier(( + ("algorithm", id_tc26_signwithdigest_gost3410_2012_256), + )), + 10, + "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28", + "6AAAB38E35D4AAA517940301799122D855484F579F4CBB96D63CDFDF3ACC432A41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493", + """ +MIHTMIGBAgEAMBIxEDAOBgNVBAMTB0V4YW1wbGUwZjAfBggqhQMHAQEBATATBgcq +hQMCAiMABggqhQMHAQECAgNDAARAC9hv5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3b +cOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7lzpByIXRHXDWibTxJqAAMAoGCCqFAwcB +AQMCA0EAaqqzjjXUqqUXlAMBeZEi2FVIT1efTLuW1jzf3zrMQypBqijS8asUgoDN +ntVv7aQZdAU1VKQnZ7g60EP9OdwEkw== + """, + "4D53F012FE081776507D4D9BB81F00EFDB4EEFD4AB83BAC4BACF735173CFA81C41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493", + """ +MIIBLTCB26ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw +IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4 +YW1wbGUwZjAfBggqhQMHAQEBATATBgcqhQMCAiMABggqhQMHAQECAgNDAARAC9hv +5djbiWaPeJtOHbqFhcVQi0XsW1nYkG3bcOJJK3/ad/+HGhD73ydm0pPF0WSvuzx7 +lzpByIXRHXDWibTxJqMTMBEwDwYDVR0TAQH/BAUwAwEB/zAKBggqhQMHAQEDAgNB +AE1T8BL+CBd2UH1Nm7gfAO/bTu/Uq4O6xLrPc1Fzz6gcQaoo0vGrFIKAzZ7Vb+2k +GXQFNVSkJ2e4OtBD/TncBJM= + """, + "42BF392A14D3EBE957AF3E46CB50BF5F4221A003AD3D172753C94A9C37A31D2041AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493", + """ +MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx +MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBAEK/OSoU0+vpV68+ +RstQv19CIaADrT0XJ1PJSpw3ox0gQaoo0vGrFIKAzZ7Vb+2kGXQFNVSkJ2e4OtBD +/TncBJM= + """, + ) + + def test_256a_paramset(self): + self._test_vector( + "id-tc26-gost-3410-2012-256-paramSetA", + GOST34112012256, + AlgorithmIdentifier(( + ("algorithm", id_tc26_gost3410_2012_256), + ("parameters", Any( + GostR34102012PublicKeyParameters(( + ("publicKeyParamSet", id_tc26_gost3410_2012_256_paramSetA), + )) + )), + )), + AlgorithmIdentifier(( + ("algorithm", id_tc26_signwithdigest_gost3410_2012_256), + )), + 10, + "7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28", + "1BDC2A1317679B66232F63EA16FF7C64CCAAB9AD855FC6E18091661DB79D48121D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769", + """ +MIHKMHkCAQAwEjEQMA4GA1UEAxMHRXhhbXBsZTBeMBcGCCqFAwcBAQEBMAsGCSqF +AwcBAgEBAQNDAARAdCeV1L7ohN3yhQ/sA+o/rxhE4B2dpgtkUJOlXibfw5l49ZbP +TU0MbPHRiUPZRJPRa57AoW1RLS4SfMRpGmMY4qAAMAoGCCqFAwcBAQMCA0EAG9wq +Exdnm2YjL2PqFv98ZMyqua2FX8bhgJFmHbedSBIdDh2lvjR8bxtSVseurCAK1krH +em9bOg4Jcxjnrm7naQ== + """, + "140B4DA9124B09CB0D5CE928EE874273A310129492EC0E29369E3B791248578C1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769", + """ +MIIBJTCB06ADAgECAgEKMAoGCCqFAwcBAQMCMBIxEDAOBgNVBAMTB0V4YW1wbGUw +IBcNMDEwMTAxMDAwMDAwWhgPMjA1MDEyMzEwMDAwMDBaMBIxEDAOBgNVBAMTB0V4 +YW1wbGUwXjAXBggqhQMHAQEBATALBgkqhQMHAQIBAQEDQwAEQHQnldS+6ITd8oUP +7APqP68YROAdnaYLZFCTpV4m38OZePWWz01NDGzx0YlD2UST0WuewKFtUS0uEnzE +aRpjGOKjEzARMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoUDBwEBAwIDQQAUC02pEksJ +yw1c6Sjuh0JzoxASlJLsDik2njt5EkhXjB0OHaW+NHxvG1JWx66sIArWSsd6b1s6 +DglzGOeubudp + """, + "14BD68087C3B903C7AA28B07FEB2E7BD6FE0963F563267359F5CD8EAB45059AD1D0E1DA5BE347C6F1B5256C7AEAC200AD64AC77A6F5B3A0E097318E7AE6EE769", + """ +MIGSMEECAQEwCgYIKoUDBwEBAwIwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx +MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAgNBABS9aAh8O5A8eqKL +B/6y571v4JY/VjJnNZ9c2Oq0UFmtHQ4dpb40fG8bUlbHrqwgCtZKx3pvWzoOCXMY +565u52k= + """, + ) + + def test_512_test_paramset(self): + self._test_vector( + "id-tc26-gost-3410-2012-512-paramSetTest", + GOST34112012512, + AlgorithmIdentifier(( + ("algorithm", id_tc26_gost3410_2012_512), + ("parameters", Any( + GostR34102012PublicKeyParameters(( + ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetTest), + )) + )), + )), + AlgorithmIdentifier(( + ("algorithm", id_tc26_signwithdigest_gost3410_2012_512), + )), + 11, + "0BA6048AADAE241BA40936D47756D7C93091A0E8514669700EE7508E508B102072E8123B2200A0563322DAD2827E2714A2636B7BFD18AADFC62967821FA18DD4", + "433B1D6CE40A51F1E5737EB16AA2C683829A405B9D9127E21260FC9D6AC05D87BF24E26C45278A5C2192A75BA94993ABD6074E7FF1BF03FD2F5397AFA1D945582F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36", + """ +MIIBTzCBvAIBADASMRAwDgYDVQQDEwdFeGFtcGxlMIGgMBcGCCqFAwcBAQECMAsG +CSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz3dmdHVxBRVz3302LTJJbvGmvFDPRVlhR +Wt0hRoUMMlxbgcEzvmVaqMTUQOe5io1ZSHsMdpa8xV0R7L53NqnsNX/y/TmTH04R +TLjNo1knCsfw5/9D2UGUGeph/Sq3f12fY1I9O1CgT2PioM9Rt8E63CFWDwvUDMnH +N6AAMAoGCCqFAwcBAQMDA4GBAEM7HWzkClHx5XN+sWqixoOCmkBbnZEn4hJg/J1q +wF2HvyTibEUnilwhkqdbqUmTq9YHTn/xvwP9L1OXr6HZRVgvhvpgoIEJGiPdeV4e +PGie5RKjyC7g3MJkPHjuqPys01SSVYSGsg8cnsGXyQaZhQJgyTvLzZxcMxfhk0Th +c642 + """, + "415703D892F1A5F3F68C4353189A7EE207B80B5631EF9D49529A4D6B542C2CFA15AA2EACF11F470FDE7D954856903C35FD8F955EF300D95C77534A724A0EEE702F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36", + """ +MIIBqjCCARagAwIBAgIBCzAKBggqhQMHAQEDAzASMRAwDgYDVQQDEwdFeGFtcGxl +MCAXDTAxMDEwMTAwMDAwMFoYDzIwNTAxMjMxMDAwMDAwWjASMRAwDgYDVQQDEwdF +eGFtcGxlMIGgMBcGCCqFAwcBAQECMAsGCSqFAwcBAgECAAOBhAAEgYDh7zDVLGEz +3dmdHVxBRVz3302LTJJbvGmvFDPRVlhRWt0hRoUMMlxbgcEzvmVaqMTUQOe5io1Z +SHsMdpa8xV0R7L53NqnsNX/y/TmTH04RTLjNo1knCsfw5/9D2UGUGeph/Sq3f12f +Y1I9O1CgT2PioM9Rt8E63CFWDwvUDMnHN6MTMBEwDwYDVR0TAQH/BAUwAwEB/zAK +BggqhQMHAQEDAwOBgQBBVwPYkvGl8/aMQ1MYmn7iB7gLVjHvnUlSmk1rVCws+hWq +LqzxH0cP3n2VSFaQPDX9j5Ve8wDZXHdTSnJKDu5wL4b6YKCBCRoj3XleHjxonuUS +o8gu4NzCZDx47qj8rNNUklWEhrIPHJ7Bl8kGmYUCYMk7y82cXDMX4ZNE4XOuNg== + """, + "3A13FB7AECDB5560EEF6137CFC5DD64691732EBFB3690A1FC0C7E8A4EEEA08307D648D4DC0986C46A87B3FBE4C7AF42EA34359C795954CA39FF3ABBED9051F4D2F86FA60A081091A23DD795E1E3C689EE512A3C82EE0DCC2643C78EEA8FCACD35492558486B20F1C9EC197C90699850260C93BCBCD9C5C3317E19344E173AE36", + """ +MIHTMEECAQEwCgYIKoUDBwEBAwMwEjEQMA4GA1UEAxMHRXhhbXBsZRcNMTQwMTAx +MDAwMDAwWhcNMTQwMTAyMDAwMDAwWjAKBggqhQMHAQEDAwOBgQA6E/t67NtVYO72 +E3z8XdZGkXMuv7NpCh/Ax+ik7uoIMH1kjU3AmGxGqHs/vkx69C6jQ1nHlZVMo5/z +q77ZBR9NL4b6YKCBCRoj3XleHjxonuUSo8gu4NzCZDx47qj8rNNUklWEhrIPHJ7B +l8kGmYUCYMk7y82cXDMX4ZNE4XOuNg== + """, + ) diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/utils.py b/xmlrpcserver/deps/pygost-5.12/pygost/utils.py new file mode 100644 index 0000000..21c31b0 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/utils.py @@ -0,0 +1,101 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from codecs import getdecoder +from codecs import getencoder +from sys import version_info + + +xrange = range if version_info[0] == 3 else xrange + + +def strxor(a, b): + """XOR of two strings + + This function will process only shortest length of both strings, + ignoring remaining one. + """ + mlen = min(len(a), len(b)) + a, b, xor = bytearray(a), bytearray(b), bytearray(mlen) + for i in xrange(mlen): + xor[i] = a[i] ^ b[i] + return bytes(xor) + + +_hexdecoder = getdecoder("hex") +_hexencoder = getencoder("hex") + + +def hexdec(data): + """Decode hexadecimal + """ + return _hexdecoder(data)[0] + + +def hexenc(data): + """Encode hexadecimal + """ + return _hexencoder(data)[0].decode("ascii") + + +def bytes2long(raw): + """Deserialize big-endian bytes into long number + + :param bytes raw: binary string + :returns: deserialized long number + :rtype: int + """ + return int(hexenc(raw), 16) + + +def long2bytes(n, size=32): + """Serialize long number into big-endian bytestring + + :param long n: long number + :returns: serialized bytestring + :rtype: bytes + """ + res = hex(int(n))[2:].rstrip("L") + if len(res) % 2 != 0: + res = "0" + res + s = hexdec(res) + if len(s) != size: + s = (size - len(s)) * b"\x00" + s + return s + + +def modinvert(a, n): + """Modular multiplicative inverse + + :returns: inverse number. -1 if it does not exist + + Realization is taken from: + https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm + """ + if a < 0: + # k^-1 = p - (-k)^-1 mod p + return n - modinvert(-a, n) + t, newt = 0, 1 + r, newr = n, a + while newr != 0: + quotinent = r // newr + t, newt = newt, t - quotinent * newt + r, newr = newr, r - quotinent * newr + if r > 1: + return -1 + if t < 0: + t = t + n + return t diff --git a/xmlrpcserver/deps/pygost-5.12/pygost/wrap.py b/xmlrpcserver/deps/pygost-5.12/pygost/wrap.py new file mode 100644 index 0000000..3fa49e7 --- /dev/null +++ b/xmlrpcserver/deps/pygost-5.12/pygost/wrap.py @@ -0,0 +1,152 @@ +# coding: utf-8 +# PyGOST -- Pure Python GOST cryptographic functions library +# Copyright (C) 2015-2023 Sergey Matveev +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +"""Key wrap. + +:rfc:`4357` key wrapping (28147-89 and CryptoPro). +""" + +from hmac import compare_digest +from struct import pack +from struct import unpack + +from pygost.gost28147 import cfb_encrypt +from pygost.gost28147 import DEFAULT_SBOX +from pygost.gost28147 import ecb_decrypt +from pygost.gost28147 import ecb_encrypt +from pygost.gost28147_mac import MAC +from pygost.gost3413 import ctr +from pygost.gost3413 import mac + + +def wrap_gost(ukm, kek, cek, sbox=DEFAULT_SBOX): + """28147-89 key wrapping + + :param ukm: UKM + :type ukm: bytes, 8 bytes + :param kek: key encryption key + :type kek: bytes, 32 bytes + :param cek: content encryption key + :type cek: bytes, 32 bytes + :returns: wrapped key + :rtype: bytes, 44 bytes + """ + cek_mac = MAC(kek, data=cek, iv=ukm, sbox=sbox).digest()[:4] + cek_enc = ecb_encrypt(kek, cek, sbox=sbox) + return ukm + cek_enc + cek_mac + + +def unwrap_gost(kek, data, sbox=DEFAULT_SBOX): + """28147-89 key unwrapping + + :param kek: key encryption key + :type kek: bytes, 32 bytes + :param data: wrapped key + :type data: bytes, 44 bytes + :returns: unwrapped CEK + :rtype: 32 bytes + """ + if len(data) != 44: + raise ValueError("Invalid data length") + ukm, cek_enc, cek_mac = data[:8], data[8:8 + 32], data[-4:] + cek = ecb_decrypt(kek, cek_enc, sbox=sbox) + if MAC(kek, data=cek, iv=ukm, sbox=sbox).digest()[:4] != cek_mac: + raise ValueError("Invalid MAC") + return cek + + +def wrap_cryptopro(ukm, kek, cek, sbox=DEFAULT_SBOX): + """CryptoPro key wrapping + + :param ukm: UKM + :type ukm: bytes, 8 bytes + :param kek: key encryption key + :type kek: bytes, 32 bytes + :param cek: content encryption key + :type cek: bytes, 32 bytes + :returns: wrapped key + :rtype: bytes, 44 bytes + """ + return wrap_gost( + ukm, + diversify(kek, bytearray(ukm), sbox=sbox), + cek, + sbox=sbox, + ) + + +def unwrap_cryptopro(kek, data, sbox=DEFAULT_SBOX): + """CryptoPro key unwrapping + + :param kek: key encryption key + :type kek: bytes, 32 bytes + :param data: wrapped key + :type data: bytes, 44 bytes + :returns: unwrapped CEK + :rtype: 32 bytes + """ + if len(data) < 8: + raise ValueError("Invalid data length") + return unwrap_gost( + diversify(kek, bytearray(data[:8]), sbox=sbox), + data, + sbox=sbox, + ) + + +def diversify(kek, ukm, sbox=DEFAULT_SBOX): + out = kek + for i in range(8): + s1, s2 = 0, 0 + for j in range(8): + k, = unpack("> j) & 1: + s1 += k + else: + s2 += k + iv = pack("
", "query_type": 24, "to": "tcp://bnd127", "user_id": "3302", "ts_added": 1679825511.7273829}}' diff --git a/xmlrpcserver/getObjects.data b/xmlrpcserver/getObjects.data new file mode 100644 index 0000000..43ab9f2 --- /dev/null +++ b/xmlrpcserver/getObjects.data @@ -0,0 +1 @@ +b'{"files": [], "callback": "http://userv:8008/xmlrpc", "state": 0, "params": {"from": "tcp://kptsp_vb", "query_data": "
", "query_type": 1, "to": "tcp://bnd127", "user_id": "3302", "ts_added": 1679825320.653038}}' diff --git a/xmlrpcserver/infra.py b/xmlrpcserver/infra.py new file mode 100644 index 0000000..11d1e52 --- /dev/null +++ b/xmlrpcserver/infra.py @@ -0,0 +1,9 @@ +from libcommon import * +from libdatabase import * +from libgeodata import * +from libgeodriver import * +from libgeodesy import * +from libgeom import * +from libipdutilities import * +from liboodriver import * + diff --git a/xmlrpcserver/init.py b/xmlrpcserver/init.py new file mode 100644 index 0000000..221869c --- /dev/null +++ b/xmlrpcserver/init.py @@ -0,0 +1,31 @@ +from db import Base, User, connect_db +from sqlalchemy.orm import Session + + +def init(): + sync_engine = connect_db() + Base.metadata.drop_all(sync_engine) + Base.metadata.create_all(sync_engine) + with Session(sync_engine) as session: + bnd127 = User( + username="bnd127", + passwd="gost_2012$a742ec53198ec2a5027086fba8814a89982a57112d1a72d02260161108f39b50", + bndname="bnd127", + newbnd=True, + active=True, + upstream=False + ) + bnd128 = User( + username="bnd128", + passwd="gost_2012$a742ec53198ec2a5027086fba8814a89982a57112d1a72d02260161108f39b50", + bndname="bnd128", + newbnd=True, + active=True, + upstream=False + ) + session.add_all([bnd127, bnd128]) + session.commit() + + +if __name__ == '__main__': + init() diff --git a/xmlrpcserver/reqs/__init__.py b/xmlrpcserver/reqs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/xmlrpcserver/reqs/classifier.py b/xmlrpcserver/reqs/classifier.py new file mode 100644 index 0000000..371e1a0 --- /dev/null +++ b/xmlrpcserver/reqs/classifier.py @@ -0,0 +1,7 @@ +import graphql + +CLASSIFIER_VERSION = '8.23' + +class Classifier: + def get_classifier(self): + diff --git a/xmlrpcserver/reqs/correcting_replication_service.py b/xmlrpcserver/reqs/correcting_replication_service.py new file mode 100644 index 0000000..40cd5fb --- /dev/null +++ b/xmlrpcserver/reqs/correcting_replication_service.py @@ -0,0 +1,71 @@ +from datetime import datetime, timedelta +from enumerations import ReplicationPackageStatusEnum +from models import CorrectingReplicationOutPackage, ReplicantInfo +from typing import List +import xml.etree.ElementTree as ET + + +class CorrectingReplicationService: + EVENT_TYPE: str = 'correcting_replication' + object_list_size: int = 0 + deleted_objects_count: int = 0 + PACKAGE_TAG_NAME: str = 'package' + PACKAGE_ID_ATTRIBUTE_NAME: str = 'pkg_id' + SERVER_VERSION_ATTRIBUTE_NAME: str = 'server_version' + SERVER_ID_ATTRIBUTE_NAME: str = 'server_id' + OBJECTS_TAG_NAME: str = 'objects' + OBJECT_TAG_NAME: str = 'object' + OBJECT_ID_ATTRIBUTE_NAME: str = 'id' + IS_RSC_OBJECT: str = 'is_rsc' + OBJECT_SOURCE_ATTRIBUTE_NAME: str = 'source' + OBJECT_VERSION_ATTRIBUTE_NAME: str = 'version' + METADATA_VERSION_ATTRIBUTE_NAME: str = 'md_version' + ACTUAL_VERSION_DATE_ATTRIBUTE_NAME: str = 'version_date' + OBJECT_MISSING_ATTRIBUTE_NAME: str = 'missing' + CLASSIFIER_VERSION_ATTRIBUTE_NAME: str = 'metadata_clientVersion' + RESULT_TAG_NAME: str = 'result' + RESULT_MESSAGE_ATTRIBUTE_NAME: str = 'result_message' + VERSION_ID_ATTRIBUTE_NAME: str = 'version_id' + VERSION_SOURCE_ATTRIBUTE_NAME: str = 'version_source' + + def start_correcting_replication(self, replicant_id: str, replication_period: int, replication_timeout: int, + manual_run: bool): + replicant = ReplicantInfo() + self.start_correcting_replication(replicant, replication_period, replication_timeout, manual_run) + + def start_correcting_replication(self, except_replicant_id: List[str], replication_period: int, + replication_timeout: int, manual_run: bool): + pass + + def start_correcting_replication(self, replicant: ReplicantInfo, replication_period: int, replication_timeout: int, + manual_run: bool): + pass + + def create_replication_package(self, replicant: ReplicantInfo, replication_period: int, replication_timeout: int) -> CorrectingReplicationOutPackage: + pkg = CorrectingReplicationOutPackage() + pkg.filter_string = replicant.filter_string + pkg.replicant_id = replicant.replicant_id + pkg.server_address = replicant.server_address + pkg.replication_period = replication_period + pkg.replication_timeout = replication_timeout + pkg.status = ReplicationPackageStatusEnum.SENT_REQUEST_TO_CHILD + date = datetime.now() + pkg.replication_date = date + if replication_period: + delta = timedelta(days=-replication_period) + pkg.from_date = date + delta + if replication_timeout: + delta = timedelta(seconds=replication_timeout) + pkg.replication_timeout_date = date + delta + return pkg + + def get_package_xml(self, pkg: CorrectingReplicationOutPackage, request_uuid: str) -> str: + request_xml: ET.Element = xml_service.get_common_request_xml(request_uuid) + element = ET.SubElement(request_xml, self.PACKAGE_TAG_NAME, { + self.PACKAGE_ID_ATTRIBUTE_NAME: pkg.package_id, + self.SERVER_VERSION_ATTRIBUTE_NAME: '1.0.0', + self.SERVER_ID_ATTRIBUTE_NAME: 'ipd-server', + self.CLASSIFIER_VERSION_ATTRIBUTE_NAME: classifier., + }) + xml_service.set_request_uuid(request_xml, request_uuid) + return ET.tostring(request_xml, encoding='unicode', xml_declaration=True) diff --git a/xmlrpcserver/reqs/enumerations.py b/xmlrpcserver/reqs/enumerations.py new file mode 100644 index 0000000..b55aa0d --- /dev/null +++ b/xmlrpcserver/reqs/enumerations.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class ReplicationPackageStatusEnum(Enum): + CANCELLED = -4 + TIMEDOUT = -3 + ERROR = -2 + SENT_REQUEST_TO_CHILD = 1 + SENT_PACKAGE_TO_CHILD = 2 + COMPLETED = 3 diff --git a/xmlrpcserver/reqs/messages.py b/xmlrpcserver/reqs/messages.py new file mode 100644 index 0000000..75d2ad4 --- /dev/null +++ b/xmlrpcserver/reqs/messages.py @@ -0,0 +1,233 @@ +from enum import Enum + + +class Messages(Enum): + REQUEST_EXECUTED_PARTITIALY = 1 + REQUEST_FAILED = 2 + OBJECT_FORBIDDEN = 3 + INVALID_REQUEST_USER = 4 + ACTION_FORBIDDEN = 5 + OBJECTS_FORBIDDEN = 6 + INVALID_REPLICATION_PARAMETERS = 7 + OBJECT_LIST = 11 + OBJECT_LIST_ITEM = 12 + MISSING_TAG = 13 + NO_OBJECTS_AVAILABLE = 14 + OBJECT_BASE_CELL_NOT_FOUND = 15 + WRONG_VERSION_INTERVAL = 16 + REQUEST_PROCESS_STARTED = 17 + REQUEST_PROCESS_FINISHED = 18 + USER_IS_NOT_VALID = 19 + RESPONSE_DELIVERY_ERROR = 20 + RESPONSE_DELIVERY_SUCCESS = 21 + RESPONSE_SEND = 22 + RESPONSE_SEND_ERROR = 23 + DUPLICATE_CHART_NAME = 24 + EXTENDED_METADATA_FORBIDDEN = 25 + MAX_RESULT_COUNT_EXCEEDED = 26 + MAX_RESULT_SIZE_EXCEEDED = 27 + CLIENT_DISCONNECTED = 28 + NO_REQUEST_DATA_PROVIDED = 29 + NO_USER_ID_PROVIDER = 30 + INVALID_REQUEST_DATA = 31 + UNKNOWN_FILTER_ATTRIBUTE_CODE = 32 + UNKNOWN_FILTER_OPERATION = 33 + ARCHIVE_ACCESS_FORBIDDEN = 34 + BROKEN_S57_FILE = 35 + UNKNOWN_OBJECT_ID = 36 + NO_FILTER_IN_REPORT = 37 + UPLOAD_OBJECT_LIST = 100 + UPLOAD_OBJECT_LIST_ITEM = 101 + UPLOAD_WRONG_STRUCTURE = 102 + FOLDER_NOT_FOUND = 103 + UPLOAD_WRONG_SUBVERSION = 104 + UPLOAD_MISSING_CHARTS_FILE = 105 + UPLOAD_NO_CHARTS_IN_FILE = 106 + UPLOAD_WRONG_CHART_TYPE = 107 + UPLOAD_OBJECT_EXISTS = 108 + UPLOAD_BASE_CELL_NOT_FOUND = 109 + UPLOAD_WRONG_VERSION_SEQUENCE = 110 + WRONG_DELETE_VERSION_NUMBER = 111 + CANT_CHANGE_STAMP = 112 + OBJECT_ALREADY_UPDATED = 113 + OBJECT_LOCKED = 114 + UPLOAD_MAIN_FILE_NOT_FOUND = 115 + UPLOAD_VERSION_NUMBER_NOT_THE_SAME = 116 + FROM_ADDRESS = 117 + TO_ADDRESS = 118 + UPLOAD_OBJECT_EXISTS_BY_SIZE_AND_CHECKSUM = 119 + CORRECTING_REPLICATION_TIMED_OUT = 120 + CORRECTING_REPLICATION_AUTO_STARTED = 121 + CORRECTING_REPLICATION_MANUAL_STARTED = 122 + CORRECTING_REPLICATION_ALREADY_STARTED = 123 + CORRECTING_REPLICATION_CANCELLED = 124 + REPLICATION_SENT = 125 + REPLICATION_RECEIVED = 126 + WRONG_OBJECT_FILE_CHECKSUM = 127 + WRONG_UPLOADING_FILE_CHECKSUM = 128 + WRONG_UPLOADING_FILE_SIZE = 129 + CORRECTING_REPLICATION_INFO = 130 + CORRECTING_REPLICATION_CLASSIFIER = 131 + CORRECTING_REPLICATION_LIST_OBJECT = 132 + GET_CORRECTING_REPLICATION_PACKAGE = 133 + CORRECTING_REPLICATION_SIZE_LIMIT = 134 + PACKAGE_INFO = 135 + CORRECTING_REPLICATION_SIZE_ARCHIVE = 136 + SET_CORRECTING_REPLICATION_PACKAGE = 137 + CHECK_DUPLICATE = 138 + CHECK_TAG = 139 + DELETED_DUPLICATE = 140 + STREAMING_REPLICATION_STARTED = 141 + ERROR_PACKAGE_NUM = 142 + STREAMING_REPLICATION_FINISHED = 143 + DELETE_VERSION_STARTED = 144 + DELETE_VERSION_FINISHED = 145 + UPLOAD_OBJECTS_EXISTS_DIFF_CHECKSUM = 146 + UPLOAD_OBJECTS_WITH_LESS_VERSION = 147 + CORRECTING_REPLICATION_OBJECT_COUNTS = 148 + PACKAGE_INFO_FAILED_OBJECTS = 149 + PACKAGE_INFO_INCOMING_OBJECTS = 150 + OBJECT_INFO_DIDNT_ADD = 151 + TAG_NOT_FOUND = 200 + MISSING_ATTRIBUTE = 201 + DUPLICATE_TAG_ID = 202 + CANT_HIDE_TAG = 203 + CANT_MOVE_TAG = 204 + CANT_HIDE_REGION = 205 + CANT_HIDE_REGIONS = 206 + CANT_HIDE_CHILD_REGION = 207 + CANT_HIDE_CHILD_REGIONS = 208 + WRONG_MID = 300 + MAUNFACTURER_KEY_NOT_FOUND = 301 + OBJECT_NOT_FOUND = 302 + OBJECT_REQUESTED_FROM_PARENT_SERVER = 303 + OBJECT_HAS_NO_FILES = 304 + WRONG_EXPIRATION_PERIOD = 400 + OBJECT_LIST_HAS_DUBLICATES = 401 + ACTIVE_SUBSCRIPTION_ALREADY_EXISTS = 402 + ACTIVE_SUBSCRIPTION_NOT_EXISTS = 403 + WRONG_TYPE_ALL_CHARTS = 500 + NO_CLASSIFIER_FILE_ON_SERVER = 600 + NO_CLASSIFIER_VERSION_ON_SERVER = 601 + CLASSIFIERS_VERSIONS_DIFFER = 602 + WRONG_OBJECT_PARAMETER_CODE = 603 + ILLEGAL_PARAMETER_VALUE = 604 + ILLEGAL_PARAMETER_TYPE = 605 + ILLEGAL_PARAMETER_RANGE = 606 + NOT_ALL_REQUIRED_TYPES = 607 + ILLEGAL_ATTRIBUTE_VALUE = 608 + NOT_ALLOWED_ITEM_FOR_TYPE = 609 + NO_CHART_CLASS_WITH_CODE = 610 + CHART_CLASS_CONTAINS_NONEXISTED_ELEMENT = 611 + CLASS_GROUP_CONTAINS_NONEXISTED_CLASS = 612 + SAME_CLASSIFIER_VERSION = 614 + NO_CLASSIFIER_VERSION = 615 + UNKNOWN_ATTR_VAL_DATA_TYPE = 616 + NOT_ALL_USING_ITEMS_IN_CLASSIFIER = 617 + NO_REQIRED_CLASS_CODE_IN_CLASSIFIER = 618 + REQUIRED_ADDED_TO_CHART_CLASS = 619 + SET_CLASSIFIER_STARTED_AUDIT = 620 + DATA_VALIDATION_STARTED_AUDIT = 621 + DATA_VALIDATION_FAILED_AUDIT = 622 + DATA_VALIDATION_ENDED_AUDIT = 623 + SAVING_CLASSIFIER_STARTED_AUDIT = 624 + SAVING_CLASSIFIER_FINISHED_AUDIT = 625 + SEND_SET_CLASSIFIER_REQUEST_AUDIT = 626 + GET_SET_CLASSIFIER_REQUEST_AUDIT = 627 + GET_GET_CLASSIFIER_REQUEST_AUDIT = 628 + IKP_USER_DECISION_TYPE = 700 + IKP_FILE_STRUCTURE_CHECKER_TYPE = 701 + IKP_FILE_STRUCTURE_DB_LINKS_CHECKER_TYPE = 702 + IKP_DB_LINKS_FILE_STRUCTURE_CHECKER_TYPE = 703 + IKP_CHECK_SUM_CHECKER_TYPE = 704 + IKP_BACKUP_TO_DB_TYPE = 705 + IKP_RECOVER_FROM_DB_TYPE = 706 + IKP_RECOVER_FROM_BACKUP_SERVER_TYPE = 707 + IKP_RECOVER_FROM_CHILD_SERVER_TYPE = 708 + IKP_DB_STRUCTURE_CHECKER_TYPE = 709 + IKP_DB_STRUCTURE_MISSING_COLUMN = 710 + IKP_DB_STRUCTURE_WRONG_COLUMN_TYPE = 711 + IKP_DB_STRUCTURE_WRONT_MAX_LENGTH = 712 + IKP_DB_STRUCTURE_MISSING_TABLE = 713 + IKP_NOTHING_TO_RECOVER = 714 + IKP_ERROR_NOT_FIXED = 715 + IKP_FULL_BACKUP_TO_DB_TYPE = 716 + EXPORT_TO_FOLDER_START = 717 + EXPORT_TO_FOLDER_FINISHED = 718 + EXPORT_TO_FOLDER_ERROR = 719 + EXPORT_TO_FOLDER_DELETE_FILE = 720 + IMPORT_FROM_FOLDER_START = 721 + IMPORT_FROM_FOLDER_FINISHED = 722 + IMPORT_FROM_FOLDER_ERROR = 723 + IMPORT_FOLDER_NOT_FOUND = 724 + FILE_NOT_FOUND = 725 + IMPORT_FROM_FOLDER_MERGE_ERROR = 726 + FILE_NOT_FOUND_COUNTER = 727 + LAST_CORRECTION_DATE_NEWER_THAN_NEW_CORRECTION = 728 + CREATION_DATE_MISSING = 729 + IMPORT_FROM_FOLDER_DIDNT_START = 730 + EXPORT_TO_FOLDER_DIDNT_START = 731 + IKP_STEP_START = 800 + IKP_STEP_SUCCESS = 801 + IKP_STEP_ERROR = 802 + IKP_NO_CHECK_ERROR_FOUND = 803 + IKP_SEND_USER_DECISION = 804 + IKP_GET_USER_DECISION = 805 + IKP_FILE_STRUCTURE_ERROR = 806 + IKP_FILE_STRUCTURE_DB_LINKS_ERROR = 807 + IKP_CHECK_SUM_ERROR = 808 + IKP_DB_LINKS_FILE_STRUCTURE_ERROR = 809 + IKP_DB_STRUCTURE_TABLE_COLUMN_ERROR = 810 + IKP_DB_STRUCTURE_TABLE_ERROR = 811 + IKP_STEP_STOPPED = 812 + IKP_WRONG_FILE_ERROR = 813 + IKP_TASK_RUN_COLLISION = 814 + IKP_FIX_SXF_METADATA_CHECKSUM_INFO = 815 + IKP_FIX_SXF_METADATA_CHECKSUM_PASSPORT_ERROR = 816 + IKP_FIX_SXF_METADATA_CHECKSUM_FILE_ERROR = 817 + IKP_MD_RECOVERING_STARTED = 818 + IKP_MD_RECOVERING_NO_VERSION = 819 + IKP_MD_RECOVERING_CREATED = 820 + IKP_MD_RECOVERING_UPDATED = 821 + IKP_MD_RECOVERING_SUCCEED = 822 + IKP_MD_RECOVERING_FAILED = 823 + IKP_CHECK_AVAILABLE_DISK_SPACE_TYPE = 825 + IKP_SCRIPT_RUN = 827 + IKP_SCRIPT_END_WORK_SUCCEED = 828 + IKP_SCRIPT_END_WORK_FAILED = 829 + IKP_SCRIPT_ALREADY_STARTED = 831 + IKP_MERGE_SAME_OBJECTS_INFO = 832 + IKP_MERGE_SAME_OBJECTS_SUCCESSES = 833 + IKP_MERGE_SAME_OBJECTS_WARNING = 834 + IKP_MERGE_SAME_OBJECTS_ERROR = 835 + IKP_MERGE_SAME_OBJECTS_MERGE_TYPE_VERSIONS = 836 + IKP_MERGE_SAME_OBJECTS_MERGE_TYPE_DATES = 837 + RSC_CLASSIFIER_UPLOAD_STARTED = 838 + RSC_CLASSIFIER_UPLOAD_ERROR = 839 + RSC_CLASSIFIER_UPLOAD_FINISHED = 843 + IKP_CLEAR_OUT_FOLDER_INFO = 840 + IKP_CLEAR_OUT_FOLDER_SUCCESS_DELETE = 841 + IKP_CLEAR_OUT_FOLDER_ERROR_DELETE = 842 + SET_CHART_METADATA = 844 + ERROR_WHILE_COPING_FILE = 845 + ERROR_ADD_OBJECT = 848 + MISSING_REGIONS_CHARTS = 849 + NO_MISSING_REGIONS = 850 + IKP_CLEAR_DOWNLOAD_CATALOG_WARNING = 855 + IKP_CLEAR_DOWNLOAD_CATALOG_ERROR = 856 + IKP_CLEAR_DOWNLOAD_CATALOG_INFO = 857 + REPLICATION_PACKAGE_NOT_FOUND = 858 + REPLICATION_PACKAGE_WRONG_STATUS = 859 + NOT_UNIQUE_METADATA = 860 + IKP_SCALE_RECOVERING_STARTED = 861 + IKP_SCALE_RECOVERING_FAILED = 862 + IKP_SCALE_RECOVERING_FINISHED = 863 + OBJECTS_REGIONS_CHECKING_STARTED = 865 + OBJECTS_REGIONS_CHECKING_FINISHED = 866 + OBJECTS_REGIONS_CHECKING_FAILED = 867 + BLACK_HOLE_TRANSMITTER_IS_OFF = 868 + LACK_VERSIONS_IN_TIME_PERIOD = 869 + ERROR_STOPPING_IKP = 870 + IKP_STOPPED = 871 + REPLICATION_ERROR_TEST = 872 + BLACK_HOLE_NOT_PRESENT = 873 diff --git a/xmlrpcserver/reqs/models.py b/xmlrpcserver/reqs/models.py new file mode 100644 index 0000000..e7f21c9 --- /dev/null +++ b/xmlrpcserver/reqs/models.py @@ -0,0 +1,23 @@ +from datetime import datetime + + +class ReplicantInfo: + server_address: str + filter_string: str + replicant_id: str + replicant_user_id: str + replicate_classifiers: bool + + +class CorrectingReplicationOutPackage: + package_id: int + status: int + from_date: datetime + replication_date: datetime + replication_timeout_date: datetime + end_date: datetime + replicant_id: str + server_address: str + filter_string: str + replication_period: int + replication_timeout: int diff --git a/xmlrpcserver/reqs/request_processor.py b/xmlrpcserver/reqs/request_processor.py new file mode 100644 index 0000000..073bec8 --- /dev/null +++ b/xmlrpcserver/reqs/request_processor.py @@ -0,0 +1,4 @@ + +class RequestProcessor: + def __init__(self): + pass diff --git a/xmlrpcserver/reqs/request_xml_service.py b/xmlrpcserver/reqs/request_xml_service.py new file mode 100644 index 0000000..f8baef0 --- /dev/null +++ b/xmlrpcserver/reqs/request_xml_service.py @@ -0,0 +1,109 @@ +import xml.etree.ElementTree as ET +from xmlrpcserver.reqs.messages import Messages + + +class RequestXmlService: + REQUEST_NODE_NAME: str = 'request' + HEADER_NODE_NAME: str = 'header' + RESULT_NODE_NAME: str = 'result' + REQUEST_ID_ATTRIBUTE_NAME: str = 'parcel_id' + RESPONSE_ID_ATTRIBUTE_NAME: str = 'reply_parcel_id' + SOURCE_REQUEST_ID_ATTRIBUTE_NAME: str = 'source_parcel_id' + RESULT_CODE_ATTRIBUTE_NAME: str = 'result_code' + RESULT_MESSAGE_ATTRIBUTE_NAME: str = 'result_message' + HEADER_XPATH: str = HEADER_NODE_NAME + + def get_request_uuid(self, document: ET.Element) -> str: + return self.get_header_attribute(document, self.REQUEST_ID_ATTRIBUTE_NAME) + + def get_response_uuid(self, document: ET.Element) -> str: + return self.get_header_attribute(document, self.RESPONSE_ID_ATTRIBUTE_NAME) + + def get_source_request_uuid(self, document: ET.Element) -> str: + return self.get_header_attribute(document, self.SOURCE_REQUEST_ID_ATTRIBUTE_NAME) + + def get_header_node(self, document: ET.Element) -> ET.Element: + return document.find(self.HEADER_XPATH) + + def get_header_attribute(self, document: ET.Element, attribute_name: str) -> str: + header = self.get_header_node(document) + if header is None: + raise Exception(Messages.MISSING_TAG.value) + result = header.get(attribute_name) + return result.strip() if result else '' + + def get_request_document(self, request_uuid: str, response_uuid) -> ET.Element: + document = ET.Element(self.REQUEST_NODE_NAME) + header = ET.SubElement(document, self.HEADER_NODE_NAME) + header.set(self.REQUEST_ID_ATTRIBUTE_NAME, request_uuid.strip()) + if response_uuid: + header.set(self.RESPONSE_ID_ATTRIBUTE_NAME, response_uuid.strip()) + return document + + def get_common_response_xml(self, request_uuid: str, response_uuid: str, result_code: int, result_message: str) -> ET.Element: + document = self.get_request_document(response_uuid, request_uuid) + + result = ET.SubElement(document, self.RESULT_NODE_NAME) + result.set(self.RESULT_CODE_ATTRIBUTE_NAME, str(result_code)) + result.set(self.RESULT_MESSAGE_ATTRIBUTE_NAME, result_message) + + return document + + def set_result(self, document: ET.Element, result_code: int, result_message: str): + result = document.find(self.RESULT_NODE_NAME) + if result is None: + result = ET.SubElement(document, self.RESULT_NODE_NAME) + result.set(self.RESULT_CODE_ATTRIBUTE_NAME, str(result_code)) + result.set(self.RESULT_MESSAGE_ATTRIBUTE_NAME, result_message) + + def set_request_uuid(self, document: ET.Element, request_uuid: str): + header = self.get_header_node(document) + header.set(self.REQUEST_ID_ATTRIBUTE_NAME, request_uuid.strip()) + + def set_source_request_uuid(self, document: ET.Element, source_request_uuid: str): + header = self.get_header_node(document) + header.set(self.SOURCE_REQUEST_ID_ATTRIBUTE_NAME, source_request_uuid.strip()) + + def get_common_request_xml(self, request_uuid: str) -> ET.Element: + return self.get_request_document(request_uuid, None) + + def get_response_xml(self, document: ET.Element, request_uuid, response_uuid: str, result_code: int, result_message: str) -> ET.Element: + header = document.find(self.HEADER_NODE_NAME) + header.set(self.REQUEST_ID_ATTRIBUTE_NAME, response_uuid.strip()) + header.set(self.RESPONSE_ID_ATTRIBUTE_NAME, request_uuid.strip() if request_uuid else None) + result = document.find(self.RESULT_NODE_NAME) + result.set(self.RESULT_CODE_ATTRIBUTE_NAME, str(result_code)) + result.set(self.RESULT_MESSAGE_ATTRIBUTE_NAME, result_message) + + def get_element(self, document: ET.Element, node: ET.Element, name: str) -> ET.Element: + for child in node: + if child.tag.casefold() == name.casefold(): + return child + return ET.SubElement(document, name) + + def validate_common_request_xml(self, xml: str): + if not xml: + raise Exception(Messages.NO_REQUEST_DATA_PROVIDED.name) + try: + document = ET.parse(xml) + except: + raise Exception(Messages.INVALID_REQUEST_DATA) + self.validate_common_request_xml(document) + + def validate_common_request_xml(self, document): + if not document: + raise Exception(Messages.NO_REQUEST_DATA_PROVIDED.name) + if document.tag != self.REQUEST_NODE_NAME: + raise Exception(Messages.MISSING_TAG.name, self.REQUEST_NODE_NAME) + try: + request_uuid = self.get_header_attribute(document, self.REQUEST_ID_ATTRIBUTE_NAME) + except: + raise Exception(Messages.INVALID_REQUEST_DATA) + if not request_uuid: + raise Exception(Messages.MISSING_ATTRIBUTE, self.REQUEST_ID_ATTRIBUTE_NAME, self.HEADER_NODE_NAME) + + def get_result_code(self, document: ET.Element): + result = self.get_element(document, document, self.RESULT_NODE_NAME) + if not result: + return None + return result.get(self.RESULT_CODE_ATTRIBUTE_NAME) diff --git a/xmlrpcserver/reqs_graphql.py b/xmlrpcserver/reqs_graphql.py new file mode 100644 index 0000000..65d8ee3 --- /dev/null +++ b/xmlrpcserver/reqs_graphql.py @@ -0,0 +1,46 @@ +from gql import gql, Client +from gql.transport.aiohttp import AIOHTTPTransport +from .config import Config + +transport = AIOHTTPTransport(url=Config.gql_url) +service = Config.gql_schema + + +def get_classifier(): + client = Client(transport=transport, fetch_schema_from_transport=True, execute_timeout=None) + query = gql( + """ + query getClassifier($name: String!) { + getClassifier(name: $name) + } + """ + ) + result = client.execute(query, variable_values={"name": service}, ) + return result['getClassifier'] + + +def get_catalog(): + client = Client(transport=transport, fetch_schema_from_transport=True, execute_timeout=None) + query = gql( + """ + query getCatalog($name: String!) { + getCatalog(name: $name) + } + """ + ) + result = client.execute(query, variable_values={"name": service}) + return result['getCatalog'] + + +def get_object(oid: str): + client = Client(transport=transport, fetch_schema_from_transport=True, execute_timeout=None) + query = gql( + """ + query getObjects($oid: String!, $name: String!) { + getObject(name: $name, oid: $oid) + } + """ + ) + params = {'oid': oid, 'name': service} + result = client.execute(query, variable_values=params) + return result['getObject'] diff --git a/xmlrpcserver/test.py b/xmlrpcserver/test.py new file mode 100644 index 0000000..1e2b861 --- /dev/null +++ b/xmlrpcserver/test.py @@ -0,0 +1,33 @@ +import db +from sqlalchemy.orm import Session + + +def get_branch(bndname: str, scheme: str): + conn = db.connect_db() + with Session(conn) as session: + item = session.query(db.IncomeBranch).filter_by(scheme=scheme).join( + db.User).filter_by(bndname=bndname).one_or_none() + if item: + return item.branch + return None + + +def is_replication_scheme(bndname: str, scheme: str): + conn = db.connect_db() + with Session(conn) as session: + item = session.query(db.User).filter_by(bndname=bndname).one_or_none() + if not item: + return False + profiles = {x.scheme: x.to_dict() for x in item.profiles} + if len(profiles) == 0 or scheme in profiles: + return True + return False + + +def main(): + # print(get_branch('bnd128', 'ood')) + print(is_replication_scheme('bnd128', 'documents_src')) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/xmlrpcserver/tmp.data b/xmlrpcserver/tmp.data new file mode 100644 index 0000000..4ac7715 --- /dev/null +++ b/xmlrpcserver/tmp.data @@ -0,0 +1 @@ +{'from': 'tcp://kptsp_vb', 'query_data': '
', 'query_type': 4, 'to': 'tcp://bnd127', 'user_id': '1', 'ts_added': 1679213998.282467} [] http://127.0.0.1:7000/xmlrpc \ No newline at end of file diff --git a/xmlrpcserver/zip.py b/xmlrpcserver/zip.py new file mode 100644 index 0000000..694a4ff --- /dev/null +++ b/xmlrpcserver/zip.py @@ -0,0 +1,23 @@ +import os +from tempfile import TemporaryDirectory, mktemp +from zipfile import ZipFile + + +class Zip: + + def __init__(self): + self.dir = TemporaryDirectory() + + @property + def dirname(self): + return self.dir.name + + def pack(self): + tmp_zip = mktemp(suffix='.zip') + with ZipFile(tmp_zip, 'w') as zip_object: + for folder_name, sub_folders, file_names in os.walk(self.dir.name): + for filename in file_names: + file_path = os.path.join(folder_name, filename) + rel_file_path = os.path.relpath(file_path, self.dir.name) + zip_object.write(file_path, rel_file_path) + return tmp_zip