pax_global_header00006660000000000000000000000064143222460600014511gustar00rootroot0000000000000052 comment=01b71291cda2c645b300ab3f9d1c23962d0b24d1 py-rnp-main/000077500000000000000000000000001432224606000132245ustar00rootroot00000000000000py-rnp-main/.github/000077500000000000000000000000001432224606000145645ustar00rootroot00000000000000py-rnp-main/.github/workflows/000077500000000000000000000000001432224606000166215ustar00rootroot00000000000000py-rnp-main/.github/workflows/ci.yml000066400000000000000000000060651432224606000177460ustar00rootroot00000000000000name: Tests on: pull_request: push: branches: - master jobs: test: env: MAKE_PARALLEL: 2 strategy: matrix: os: [ubuntu-latest, macos-latest] python: [3.9] botan: [2.18.1] rnp: [master, v0.15.2] runs-on: ${{ matrix.os }} continue-on-error: true steps: - uses: actions/checkout@v2 - name: Set environment run: | . ci/setup-env.inc.sh - name: Install build tools if: matrix.os == 'macos-latest' run: | brew install autoconf automake libtool - name: Cache id: cache uses: actions/cache@v2 with: path: ${{ env.CACHE_DIR }} key: ${{ matrix.os }}-botan-${{ matrix.botan }}-rnp-${{ matrix.rnp }}-${{ hashFiles('ci/**') }}-${{ hashFiles('.github/workflows/**') }} - name: Build cache if: steps.cache.outputs.cache-hit != 'true' run: | # botan git clone --depth 1 --branch "${{ matrix.botan }}" https://github.com/randombit/botan "${{ runner.temp }}/botan" cd "${{ runner.temp }}/botan" ./configure.py --prefix="${BOTAN_INSTALL}" --with-debug-info --cxxflags="-fno-omit-frame-pointer" make -j${MAKE_PARALLEL} install # json-c mkdir -p "${{ runner.temp }}/json-c" cd "${{ runner.temp }}/json-c" wget https://s3.amazonaws.com/json-c_releases/releases/json-c-0.12.1.tar.gz -O json-c.tar.gz tar xzf json-c.tar.gz --strip 1 autoreconf -ivf env CFLAGS="-fno-omit-frame-pointer -Wno-implicit-fallthrough -g" ./configure --prefix="$JSONC_INSTALL" make -j${MAKE_PARALLEL} install # rnp git clone https://github.com/rnpgp/rnp "${{ runner.temp }}/rnp" cd "${{ runner.temp }}/rnp" git checkout "${{ matrix.rnp }}" cmake \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DBUILD_SHARED_LIBS=yes \ -DBUILD_TESTING=no \ -DCMAKE_PREFIX_PATH="$BOTAN_INSTALL;$JSONC_INSTALL" \ -DCMAKE_INSTALL_PREFIX="${RNP_INSTALL}" \ . make -j${MAKE_PARALLEL} install - name: Set up Python uses: actions/setup-python@v2 with: python-version: ${{ matrix.python }} - name: Install poetry uses: snok/install-poetry@v1 with: version: 1.1.8 virtualenvs-create: true virtualenvs-in-project: true - name: Load cache venv id: cached-poetry-dependencies uses: actions/cache@v2 with: path: .venv key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} - name: Install dependencies if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' run: poetry install - name: Workaround macOS SIP if: matrix.os == 'macos-latest' run: | sudo cp -a "$JSONC_INSTALL/lib"/* /usr/local/lib sudo cp -a "$BOTAN_INSTALL/lib"/* /usr/local/lib sudo cp -a "$RNP_INSTALL/lib"/* /usr/local/lib - name: Test run: | export LD_LIBRARY_PATH="$JSONC_INSTALL/lib:$BOTAN_INSTALL/lib:$RNP_INSTALL/lib" poetry run tox py-rnp-main/.github/workflows/release.yml000066400000000000000000000027721432224606000207740ustar00rootroot00000000000000name: release on: workflow_dispatch: inputs: next_version: description: | Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc required: true default: 'skip' push: tags: [ v* ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 with: python-version: '3.9' - uses: snok/install-poetry@v1 with: version: 1.1.8 virtualenvs-create: true virtualenvs-in-project: true - id: cached-poetry-dependencies uses: actions/cache@v2 with: path: .venv key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} - if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' run: poetry install - if: github.event_name == 'workflow_dispatch' && github.event.inputs.next_version != 'skip' run: | git config user.name github-actions git config user.email github-actions@github.com poetry version ${{ github.event.inputs.next_version }} - run: poetry build - run: poetry publish env: POETRY_PYPI_TOKEN_PYPI: ${{ secrets.RNP_PYPI_API_TOKEN }} - if: github.event_name == 'workflow_dispatch' && github.event.inputs.next_version != 'skip' run: | git add pyproject.toml git commit -m "Bump version to ${{ github.event.inputs.next_version }}" git tag v${{ github.event.inputs.next_version }} git push py-rnp-main/LICENSE.md000066400000000000000000000027571432224606000146430ustar00rootroot00000000000000This license file adheres to the formatting guidelines of [readable-licenses](https://github.com/nevir/readable-licenses). Ribose's BSD 2-Clause License ----------------------------- Copyright (c) 2017-2022, [Ribose Inc](https://www.ribose.com). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. py-rnp-main/README.md000066400000000000000000000001571432224606000145060ustar00rootroot00000000000000# py-rnp Python bindings for [librnp](https://github.com/rnpgp/rnp). Tested against librnp 0.15.2 and later. py-rnp-main/ci/000077500000000000000000000000001432224606000136175ustar00rootroot00000000000000py-rnp-main/ci/setup-env.inc.sh000066400000000000000000000005751432224606000166600ustar00rootroot00000000000000set -euxo pipefail mkdir -p installs LOCAL_INSTALLS=/tmp/rnp-local-installs ln -s "$GITHUB_WORKSPACE/installs" /tmp/rnp-local-installs echo "CACHE_DIR=installs" >> $GITHUB_ENV echo "BOTAN_INSTALL=$GITHUB_WORKSPACE/installs/botan" >> $GITHUB_ENV echo "JSONC_INSTALL=$GITHUB_WORKSPACE/installs/jsonc" >> $GITHUB_ENV echo "RNP_INSTALL=$GITHUB_WORKSPACE/installs/rnp" >> $GITHUB_ENV py-rnp-main/poetry.lock000066400000000000000000001670461432224606000154360ustar00rootroot00000000000000[[package]] name = "astroid" version = "2.7.3" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = "~=3.6" [package.dependencies] lazy-object-proxy = ">=1.4.0" wrapt = ">=1.11,<1.13" [[package]] name = "atomicwrites" version = "1.4.0" description = "Atomic file writes." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" version = "21.2.0" description = "Classes Without Boilerplate" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] [[package]] name = "backports.entry-points-selectable" version = "1.1.0" description = "Compatibility shim providing selectable entry points for older implementations" category = "dev" optional = false python-versions = ">=2.7" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"] [[package]] name = "black" version = "21.8b0" description = "The uncompromising code formatter." category = "dev" optional = false python-versions = ">=3.6.2" [package.dependencies] click = ">=7.1.2" mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0,<1" platformdirs = ">=2" regex = ">=2020.1.8" tomli = ">=0.2.6,<2.0.0" typing-extensions = [ {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, ] [package.extras] colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] python2 = ["typed-ast (>=1.4.2)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "cachecontrol" version = "0.12.6" description = "httplib2 caching for requests" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] lockfile = {version = ">=0.9", optional = true, markers = "extra == \"filecache\""} msgpack = ">=0.5.2" requests = "*" [package.extras] filecache = ["lockfile (>=0.9)"] redis = ["redis (>=2.10.5)"] [[package]] name = "cachy" version = "0.3.0" description = "Cachy provides a simple yet effective caching library." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] redis = ["redis (>=3.3.6,<4.0.0)"] memcached = ["python-memcached (>=1.59,<2.0)"] msgpack = ["msgpack-python (>=0.5,<0.6)"] [[package]] name = "certifi" version = "2021.5.30" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false python-versions = "*" [[package]] name = "cffi" version = "1.14.6" description = "Foreign Function Interface for Python calling C code." category = "dev" optional = false python-versions = "*" [package.dependencies] pycparser = "*" [[package]] name = "charset-normalizer" version = "2.0.4" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "dev" optional = false python-versions = ">=3.5.0" [package.extras] unicode_backport = ["unicodedata2"] [[package]] name = "cleo" version = "0.7.6" description = "Cleo allows you to create beautiful and testable command-line interfaces." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] clikit = ">=0.4.0,<0.5.0" [[package]] name = "click" version = "8.0.1" description = "Composable command line interface toolkit" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "clikit" version = "0.4.3" description = "CliKit is a group of utilities to build beautiful and testable command line interfaces." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] pastel = ">=0.2.0,<0.3.0" pylev = ">=1.3,<2.0" [[package]] name = "colorama" version = "0.4.4" description = "Cross-platform colored terminal text." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "cryptography" version = "3.4.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] cffi = ">=1.12" [package.extras] docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] sdist = ["setuptools-rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] [[package]] name = "distlib" version = "0.3.2" description = "Distribution utilities" category = "dev" optional = false python-versions = "*" [[package]] name = "filelock" version = "3.0.12" description = "A platform independent file lock." category = "dev" optional = false python-versions = "*" [[package]] name = "flake8" version = "3.9.2" description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.7.0,<2.8.0" pyflakes = ">=2.3.0,<2.4.0" [[package]] name = "html5lib" version = "1.1" description = "HTML parser based on the WHATWG HTML specification" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.dependencies] six = ">=1.9" webencodings = "*" [package.extras] all = ["genshi", "chardet (>=2.2)", "lxml"] chardet = ["chardet (>=2.2)"] genshi = ["genshi"] lxml = ["lxml"] [[package]] name = "idna" version = "3.2" description = "Internationalized Domain Names in Applications (IDNA)" category = "dev" optional = false python-versions = ">=3.5" [[package]] name = "isort" version = "5.9.3" description = "A Python utility / library to sort Python imports." category = "dev" optional = false python-versions = ">=3.6.1,<4.0" [package.extras] pipfile_deprecated_finder = ["pipreqs", "requirementslib"] requirements_deprecated_finder = ["pipreqs", "pip-api"] colors = ["colorama (>=0.4.3,<0.5.0)"] plugins = ["setuptools"] [[package]] name = "jeepney" version = "0.7.1" description = "Low-level, pure Python DBus protocol wrapper." category = "dev" optional = false python-versions = ">=3.6" [package.extras] test = ["pytest", "pytest-trio", "pytest-asyncio", "testpath", "trio", "async-timeout"] trio = ["trio", "async-generator"] [[package]] name = "jsonschema" version = "3.2.0" description = "An implementation of JSON Schema validation for Python" category = "dev" optional = false python-versions = "*" [package.dependencies] attrs = ">=17.4.0" pyrsistent = ">=0.14.0" six = ">=1.11.0" [package.extras] format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] [[package]] name = "keyring" version = "20.0.1" description = "Store and access your passwords safely." category = "dev" optional = false python-versions = ">=3.5" [package.dependencies] pywin32-ctypes = {version = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1", markers = "sys_platform == \"win32\""} secretstorage = {version = "*", markers = "sys_platform == \"linux\""} [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-black-multipy", "pytest-cov"] [[package]] name = "lazy-object-proxy" version = "1.6.0" description = "A fast and thorough lazy object proxy." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [[package]] name = "lockfile" version = "0.12.2" description = "Platform-independent file locking module" category = "dev" optional = false python-versions = "*" [[package]] name = "mccabe" version = "0.6.1" description = "McCabe checker, plugin for flake8" category = "dev" optional = false python-versions = "*" [[package]] name = "more-itertools" version = "8.9.0" description = "More routines for operating on iterables, beyond itertools" category = "dev" optional = false python-versions = ">=3.5" [[package]] name = "msgpack" version = "1.0.2" description = "MessagePack (de)serializer." category = "dev" optional = false python-versions = "*" [[package]] name = "mypy-extensions" version = "0.4.3" description = "Experimental type system extensions for programs checked with the mypy typechecker." category = "dev" optional = false python-versions = "*" [[package]] name = "packaging" version = "21.0" description = "Core utilities for Python packages" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] pyparsing = ">=2.0.2" [[package]] name = "pastel" version = "0.2.1" description = "Bring colors to your terminal." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pathspec" version = "0.9.0" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." category = "dev" optional = false python-versions = "*" [package.dependencies] ptyprocess = ">=0.5" [[package]] name = "pkginfo" version = "1.7.1" description = "Query metadatdata from sdists / bdists / installed packages." category = "dev" optional = false python-versions = "*" [package.extras] testing = ["nose", "coverage"] [[package]] name = "platformdirs" version = "2.3.0" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.6" [package.extras] docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] [[package]] name = "pluggy" version = "0.13.1" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] dev = ["pre-commit", "tox"] [[package]] name = "poetry" version = "1.0.10" description = "Python dependency management and packaging made easy." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] cachecontrol = {version = ">=0.12.4,<0.13.0", extras = ["filecache"]} cachy = ">=0.3.0,<0.4.0" cleo = ">=0.7.6,<0.8.0" clikit = ">=0.4.2,<0.5.0" html5lib = ">=1.0,<2.0" jsonschema = ">=3.1,<4.0" keyring = {version = ">=20.0.1,<21.0.0", markers = "python_version >= \"3.5\" and python_version < \"4.0\""} pexpect = ">=4.7.0,<5.0.0" pkginfo = ">=1.4,<2.0" pyparsing = ">=2.2,<3.0" pyrsistent = ">=0.14.2,<0.15.0" requests = ">=2.18,<3.0" requests-toolbelt = ">=0.8.0,<0.9.0" shellingham = ">=1.1,<2.0" tomlkit = ">=0.5.11,<0.6.0" [[package]] name = "poetry-core" version = "1.0.4" description = "Poetry PEP 517 Build Backend" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" category = "dev" optional = false python-versions = "*" [[package]] name = "py" version = "1.10.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pycodestyle" version = "2.7.0" description = "Python style guide checker" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pycparser" version = "2.20" description = "C parser in Python" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pyflakes" version = "2.3.1" description = "passive checker of Python programs" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pylev" version = "1.4.0" description = "A pure Python Levenshtein implementation that's not freaking GPL'd." category = "dev" optional = false python-versions = "*" [[package]] name = "pylint" version = "2.10.2" description = "python code static checker" category = "dev" optional = false python-versions = "~=3.6" [package.dependencies] astroid = ">=2.7.2,<2.8" colorama = {version = "*", markers = "sys_platform == \"win32\""} isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.7" platformdirs = ">=2.2.0" toml = ">=0.7.1" [[package]] name = "pyparsing" version = "2.4.7" description = "Python parsing module" category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pyrsistent" version = "0.14.11" description = "Persistent/Functional/Immutable data structures" category = "dev" optional = false python-versions = "*" [package.dependencies] six = "*" [[package]] name = "pytest" version = "5.4.3" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.5" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=17.4.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} more-itertools = ">=4.0.0" packaging = "*" pluggy = ">=0.12,<1.0" py = ">=1.5.0" wcwidth = "*" [package.extras] checkqa-mypy = ["mypy (==v0.761)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] name = "pywin32-ctypes" version = "0.2.0" description = "" category = "dev" optional = false python-versions = "*" [[package]] name = "regex" version = "2021.8.28" description = "Alternative regular expression module, to replace re." category = "dev" optional = false python-versions = "*" [[package]] name = "requests" version = "2.26.0" description = "Python HTTP for Humans." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = {version = ">=2.0.0,<2.1.0", markers = "python_version >= \"3\""} idna = {version = ">=2.5,<4", markers = "python_version >= \"3\""} urllib3 = ">=1.21.1,<1.27" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] [[package]] name = "requests-toolbelt" version = "0.8.0" description = "A utility belt for advanced users of python-requests" category = "dev" optional = false python-versions = "*" [package.dependencies] requests = ">=2.0.1,<3.0.0" [[package]] name = "secretstorage" version = "3.3.1" description = "Python bindings to FreeDesktop.org Secret Service API" category = "dev" optional = false python-versions = ">=3.6" [package.dependencies] cryptography = ">=2.0" jeepney = ">=0.6" [[package]] name = "shellingham" version = "1.4.0" description = "Tool to Detect Surrounding Shell" category = "dev" optional = false python-versions = "!=3.0,!=3.1,!=3.2,!=3.3,>=2.6" [[package]] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" version = "1.2.1" description = "A lil' TOML parser" category = "dev" optional = false python-versions = ">=3.6" [[package]] name = "tomlkit" version = "0.5.11" description = "Style preserving TOML library" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "tox" version = "3.24.3" description = "tox is a generic virtualenv management and test command line tool" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""} filelock = ">=3.0.0" packaging = ">=14" pluggy = ">=0.12.0" py = ">=1.4.17" six = ">=1.14.0" toml = ">=0.9.4" virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" [package.extras] docs = ["pygments-github-lexers (>=0.0.5)", "sphinx (>=2.0.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "towncrier (>=18.5.0)"] testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "psutil (>=5.6.1)", "pytest (>=4.0.0)", "pytest-cov (>=2.5.1)", "pytest-mock (>=1.10.0)", "pytest-randomly (>=1.0.0)", "pytest-xdist (>=1.22.2)", "pathlib2 (>=2.3.3)"] [[package]] name = "tox-poetry-installer" version = "0.8.1" description = "A plugin for Tox that lets you install test environment dependencies from the Poetry lockfile" category = "dev" optional = false python-versions = ">=3.6.1,<4.0.0" [package.dependencies] poetry = {version = ">=1.0.0,<2.0.0", optional = true, markers = "extra == \"poetry\""} poetry-core = ">=1.0.0,<2.0.0" tox = ">=3.8.0,<4.0.0" [package.extras] poetry = ["poetry (>=1.0.0,<2.0.0)"] [[package]] name = "typing-extensions" version = "3.10.0.2" description = "Backported and Experimental Type Hints for Python 3.5+" category = "dev" optional = false python-versions = "*" [[package]] name = "urllib3" version = "1.26.6" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] brotli = ["brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" version = "20.7.2" description = "Virtual Python Environment builder" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] "backports.entry-points-selectable" = ">=1.0.4" distlib = ">=0.3.1,<1" filelock = ">=3.0.0,<4" platformdirs = ">=2,<3" six = ">=1.9.0,<2" [package.extras] docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] [[package]] name = "wcwidth" version = "0.2.5" description = "Measures the displayed width of unicode strings in a terminal" category = "dev" optional = false python-versions = "*" [[package]] name = "webencodings" version = "0.5.1" description = "Character encoding aliases for legacy web content" category = "dev" optional = false python-versions = "*" [[package]] name = "wrapt" version = "1.12.1" description = "Module for decorators, wrappers and monkey patching." category = "dev" optional = false python-versions = "*" [metadata] lock-version = "1.1" python-versions = "^3.9" content-hash = "6edd732b1e1709c5001e67b78f595e6f833ff3e05d2b64fc0736cf327db95aad" [metadata.files] astroid = [ {file = "astroid-2.7.3-py3-none-any.whl", hash = "sha256:dc1e8b28427d6bbef6b8842b18765ab58f558c42bb80540bd7648c98412af25e"}, {file = "astroid-2.7.3.tar.gz", hash = "sha256:3b680ce0419b8a771aba6190139a3998d14b413852506d99aff8dc2bf65ee67c"}, ] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, ] "backports.entry-points-selectable" = [ {file = "backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl", hash = "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc"}, {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"}, ] black = [ {file = "black-21.8b0-py3-none-any.whl", hash = "sha256:2a0f9a8c2b2a60dbcf1ccb058842fb22bdbbcb2f32c6cc02d9578f90b92ce8b7"}, {file = "black-21.8b0.tar.gz", hash = "sha256:570608d28aa3af1792b98c4a337dbac6367877b47b12b88ab42095cfc1a627c2"}, ] cachecontrol = [ {file = "CacheControl-0.12.6-py2.py3-none-any.whl", hash = "sha256:10d056fa27f8563a271b345207402a6dcce8efab7e5b377e270329c62471b10d"}, {file = "CacheControl-0.12.6.tar.gz", hash = "sha256:be9aa45477a134aee56c8fac518627e1154df063e85f67d4f83ce0ccc23688e8"}, ] cachy = [ {file = "cachy-0.3.0-py2.py3-none-any.whl", hash = "sha256:338ca09c8860e76b275aff52374330efedc4d5a5e45dc1c5b539c1ead0786fe7"}, {file = "cachy-0.3.0.tar.gz", hash = "sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1"}, ] certifi = [ {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"}, {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"}, ] cffi = [ {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, {file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"}, {file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"}, {file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"}, {file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"}, {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"}, {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"}, {file = "cffi-1.14.6-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534"}, {file = "cffi-1.14.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a"}, {file = "cffi-1.14.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5"}, {file = "cffi-1.14.6-cp35-cp35m-win32.whl", hash = "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca"}, {file = "cffi-1.14.6-cp35-cp35m-win_amd64.whl", hash = "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218"}, {file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"}, {file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"}, {file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"}, {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"}, {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"}, {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"}, {file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"}, {file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"}, {file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"}, {file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"}, {file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"}, {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"}, {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"}, {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"}, {file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"}, {file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"}, {file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"}, {file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"}, {file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"}, {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"}, {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"}, {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"}, {file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"}, {file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"}, {file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"}, {file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"}, {file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"}, {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"}, {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"}, {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"}, {file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"}, {file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"}, {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"}, ] charset-normalizer = [ {file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"}, {file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"}, ] cleo = [ {file = "cleo-0.7.6-py2.py3-none-any.whl", hash = "sha256:9443d67e5b2da79b32d820ae41758dd6a25618345cb10b9a022a695e26b291b9"}, {file = "cleo-0.7.6.tar.gz", hash = "sha256:99cf342406f3499cec43270fcfaf93c126c5164092eca201dfef0f623360b409"}, ] click = [ {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, ] clikit = [ {file = "clikit-0.4.3-py2.py3-none-any.whl", hash = "sha256:71e321b7795a2a6c4888629f43365d52db071737e668ab16861121d7dd3ada09"}, {file = "clikit-0.4.3.tar.gz", hash = "sha256:6e2d7e115e7c7b35bceb0209109935ab2f9ab50910e9ff2293f7fa0b7abf973e"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] cryptography = [ {file = "cryptography-3.4.8-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14"}, {file = "cryptography-3.4.8-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:f44d141b8c4ea5eb4dbc9b3ad992d45580c1d22bf5e24363f2fbf50c2d7ae8a7"}, {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a7dcbcd3f1913f664aca35d47c1331fce738d44ec34b7be8b9d332151b0b01e"}, {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34dae04a0dce5730d8eb7894eab617d8a70d0c97da76b905de9efb7128ad7085"}, {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b"}, {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:9965c46c674ba8cc572bc09a03f4c649292ee73e1b683adb1ce81e82e9a6a0fb"}, {file = "cryptography-3.4.8-cp36-abi3-win32.whl", hash = "sha256:21ca464b3a4b8d8e86ba0ee5045e103a1fcfac3b39319727bc0fc58c09c6aff7"}, {file = "cryptography-3.4.8-cp36-abi3-win_amd64.whl", hash = "sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc"}, {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d2a6e5ef66503da51d2110edf6c403dc6b494cc0082f85db12f54e9c5d4c3ec5"}, {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a305600e7a6b7b855cd798e00278161b681ad6e9b7eca94c721d5f588ab212af"}, {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:3fa3a7ccf96e826affdf1a0a9432be74dc73423125c8f96a909e3835a5ef194a"}, {file = "cryptography-3.4.8-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:d9ec0e67a14f9d1d48dd87a2531009a9b251c02ea42851c060b25c782516ff06"}, {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5b0fbfae7ff7febdb74b574055c7466da334a5371f253732d7e2e7525d570498"}, {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94fff993ee9bc1b2440d3b7243d488c6a3d9724cc2b09cdb297f6a886d040ef7"}, {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:8695456444f277af73a4877db9fc979849cd3ee74c198d04fc0776ebc3db52b9"}, {file = "cryptography-3.4.8-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:cd65b60cfe004790c795cc35f272e41a3df4631e2fb6b35aa7ac6ef2859d554e"}, {file = "cryptography-3.4.8.tar.gz", hash = "sha256:94cc5ed4ceaefcbe5bf38c8fba6a21fc1d365bb8fb826ea1688e3370b2e24a1c"}, ] distlib = [ {file = "distlib-0.3.2-py2.py3-none-any.whl", hash = "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"}, {file = "distlib-0.3.2.zip", hash = "sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736"}, ] filelock = [ {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, ] flake8 = [ {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, ] html5lib = [ {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, ] idna = [ {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"}, {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"}, ] isort = [ {file = "isort-5.9.3-py3-none-any.whl", hash = "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"}, {file = "isort-5.9.3.tar.gz", hash = "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899"}, ] jeepney = [ {file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"}, {file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"}, ] jsonschema = [ {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, ] keyring = [ {file = "keyring-20.0.1-py2.py3-none-any.whl", hash = "sha256:c674f032424b4bffc62abeac5523ec49cc84aed07a480c3233e0baf618efc15c"}, {file = "keyring-20.0.1.tar.gz", hash = "sha256:963bfa7f090269d30bdc5e25589e5fd9dad2cf2a7c6f176a7f2386910e5d0d8d"}, ] lazy-object-proxy = [ {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, {file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"}, {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"}, {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"}, {file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"}, {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"}, {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"}, {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"}, {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"}, {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"}, {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"}, {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"}, {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"}, {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"}, {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"}, {file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"}, {file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"}, {file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"}, {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"}, {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"}, {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"}, {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"}, ] lockfile = [ {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"}, {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, ] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] more-itertools = [ {file = "more-itertools-8.9.0.tar.gz", hash = "sha256:8c746e0d09871661520da4f1241ba6b908dc903839733c8203b552cffaf173bd"}, {file = "more_itertools-8.9.0-py3-none-any.whl", hash = "sha256:70401259e46e216056367a0a6034ee3d3f95e0bf59d3aa6a4eb77837171ed996"}, ] msgpack = [ {file = "msgpack-1.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b6d9e2dae081aa35c44af9c4298de4ee72991305503442a5c74656d82b581fe9"}, {file = "msgpack-1.0.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a99b144475230982aee16b3d249170f1cccebf27fb0a08e9f603b69637a62192"}, {file = "msgpack-1.0.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1026dcc10537d27dd2d26c327e552f05ce148977e9d7b9f1718748281b38c841"}, {file = "msgpack-1.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:fe07bc6735d08e492a327f496b7850e98cb4d112c56df69b0c844dbebcbb47f6"}, {file = "msgpack-1.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9ea52fff0473f9f3000987f313310208c879493491ef3ccf66268eff8d5a0326"}, {file = "msgpack-1.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:26a1759f1a88df5f1d0b393eb582ec022326994e311ba9c5818adc5374736439"}, {file = "msgpack-1.0.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:497d2c12426adcd27ab83144057a705efb6acc7e85957a51d43cdcf7f258900f"}, {file = "msgpack-1.0.2-cp36-cp36m-win32.whl", hash = "sha256:e89ec55871ed5473a041c0495b7b4e6099f6263438e0bd04ccd8418f92d5d7f2"}, {file = "msgpack-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a4355d2193106c7aa77c98fc955252a737d8550320ecdb2e9ac701e15e2943bc"}, {file = "msgpack-1.0.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:d6c64601af8f3893d17ec233237030e3110f11b8a962cb66720bf70c0141aa54"}, {file = "msgpack-1.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f484cd2dca68502de3704f056fa9b318c94b1539ed17a4c784266df5d6978c87"}, {file = "msgpack-1.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f3e6aaf217ac1c7ce1563cf52a2f4f5d5b1f64e8729d794165db71da57257f0c"}, {file = "msgpack-1.0.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:8521e5be9e3b93d4d5e07cb80b7e32353264d143c1f072309e1863174c6aadb1"}, {file = "msgpack-1.0.2-cp37-cp37m-win32.whl", hash = "sha256:31c17bbf2ae5e29e48d794c693b7ca7a0c73bd4280976d408c53df421e838d2a"}, {file = "msgpack-1.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8ffb24a3b7518e843cd83538cf859e026d24ec41ac5721c18ed0c55101f9775b"}, {file = "msgpack-1.0.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:b28c0876cce1466d7c2195d7658cf50e4730667196e2f1355c4209444717ee06"}, {file = "msgpack-1.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:87869ba567fe371c4555d2e11e4948778ab6b59d6cc9d8460d543e4cfbbddd1c"}, {file = "msgpack-1.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b55f7db883530b74c857e50e149126b91bb75d35c08b28db12dcb0346f15e46e"}, {file = "msgpack-1.0.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:ac25f3e0513f6673e8b405c3a80500eb7be1cf8f57584be524c4fa78fe8e0c83"}, {file = "msgpack-1.0.2-cp38-cp38-win32.whl", hash = "sha256:0cb94ee48675a45d3b86e61d13c1e6f1696f0183f0715544976356ff86f741d9"}, {file = "msgpack-1.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:e36a812ef4705a291cdb4a2fd352f013134f26c6ff63477f20235138d1d21009"}, {file = "msgpack-1.0.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2a5866bdc88d77f6e1370f82f2371c9bc6fc92fe898fa2dec0c5d4f5435a2694"}, {file = "msgpack-1.0.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:92be4b12de4806d3c36810b0fe2aeedd8d493db39e2eb90742b9c09299eb5759"}, {file = "msgpack-1.0.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:de6bd7990a2c2dabe926b7e62a92886ccbf809425c347ae7de277067f97c2887"}, {file = "msgpack-1.0.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5a9ee2540c78659a1dd0b110f73773533ee3108d4e1219b5a15a8d635b7aca0e"}, {file = "msgpack-1.0.2-cp39-cp39-win32.whl", hash = "sha256:c747c0cc08bd6d72a586310bda6ea72eeb28e7505990f342552315b229a19b33"}, {file = "msgpack-1.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:d8167b84af26654c1124857d71650404336f4eb5cc06900667a493fc619ddd9f"}, {file = "msgpack-1.0.2.tar.gz", hash = "sha256:fae04496f5bc150eefad4e9571d1a76c55d021325dcd484ce45065ebbdd00984"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] packaging = [ {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"}, {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, ] pastel = [ {file = "pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364"}, {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, ] pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] pexpect = [ {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, ] pkginfo = [ {file = "pkginfo-1.7.1-py2.py3-none-any.whl", hash = "sha256:37ecd857b47e5f55949c41ed061eb51a0bee97a87c969219d144c0e023982779"}, {file = "pkginfo-1.7.1.tar.gz", hash = "sha256:e7432f81d08adec7297633191bbf0bd47faf13cd8724c3a13250e51d542635bd"}, ] platformdirs = [ {file = "platformdirs-2.3.0-py3-none-any.whl", hash = "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"}, {file = "platformdirs-2.3.0.tar.gz", hash = "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f"}, ] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] poetry = [ {file = "poetry-1.0.10-py2.py3-none-any.whl", hash = "sha256:bf5f809a5f08bb4262c636b4bfee8e177fc8524ab817a7708e0901633da808de"}, {file = "poetry-1.0.10.tar.gz", hash = "sha256:4b1b895d272d9bae22e1796dfe38d6122a75963709d7a909068e68aa6937a6f2"}, ] poetry-core = [ {file = "poetry-core-1.0.4.tar.gz", hash = "sha256:4b3847ad3e7b5deb88a35b23fa19762b9cef26828770cef3a5b47ffb508119c1"}, {file = "poetry_core-1.0.4-py2.py3-none-any.whl", hash = "sha256:a99fa921cf84f0521644714bb4b531d9d8f839c64de20aa71fa137f7461a1516"}, ] ptyprocess = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] py = [ {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, ] pycodestyle = [ {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, ] pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] pyflakes = [ {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] pylev = [ {file = "pylev-1.4.0-py2.py3-none-any.whl", hash = "sha256:7b2e2aa7b00e05bb3f7650eb506fc89f474f70493271a35c242d9a92188ad3dd"}, {file = "pylev-1.4.0.tar.gz", hash = "sha256:9e77e941042ad3a4cc305dcdf2b2dec1aec2fbe3dd9015d2698ad02b173006d1"}, ] pylint = [ {file = "pylint-2.10.2-py3-none-any.whl", hash = "sha256:e178e96b6ba171f8ef51fbce9ca30931e6acbea4a155074d80cc081596c9e852"}, {file = "pylint-2.10.2.tar.gz", hash = "sha256:6758cce3ddbab60c52b57dcc07f0c5d779e5daf0cf50f6faacbef1d3ea62d2a1"}, ] pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pyrsistent = [ {file = "pyrsistent-0.14.11.tar.gz", hash = "sha256:3ca82748918eb65e2d89f222b702277099aca77e34843c5eb9d52451173970e2"}, ] pytest = [ {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, ] pywin32-ctypes = [ {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, ] regex = [ {file = "regex-2021.8.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2"}, {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a"}, {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0"}, {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb"}, {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a"}, {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308"}, {file = "regex-2021.8.28-cp310-cp310-win32.whl", hash = "sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed"}, {file = "regex-2021.8.28-cp310-cp310-win_amd64.whl", hash = "sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8"}, {file = "regex-2021.8.28-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c"}, {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c"}, {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13"}, {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0"}, {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1"}, {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f"}, {file = "regex-2021.8.28-cp36-cp36m-win32.whl", hash = "sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354"}, {file = "regex-2021.8.28-cp36-cp36m-win_amd64.whl", hash = "sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645"}, {file = "regex-2021.8.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a"}, {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e"}, {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892"}, {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791"}, {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"}, {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906"}, {file = "regex-2021.8.28-cp37-cp37m-win32.whl", hash = "sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a"}, {file = "regex-2021.8.28-cp37-cp37m-win_amd64.whl", hash = "sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc"}, {file = "regex-2021.8.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd"}, {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797"}, {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f"}, {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256"}, {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b"}, {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e"}, {file = "regex-2021.8.28-cp38-cp38-win32.whl", hash = "sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d"}, {file = "regex-2021.8.28-cp38-cp38-win_amd64.whl", hash = "sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2"}, {file = "regex-2021.8.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468"}, {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb"}, {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d"}, {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983"}, {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8"}, {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed"}, {file = "regex-2021.8.28-cp39-cp39-win32.whl", hash = "sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374"}, {file = "regex-2021.8.28-cp39-cp39-win_amd64.whl", hash = "sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73"}, {file = "regex-2021.8.28.tar.gz", hash = "sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1"}, ] requests = [ {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, ] requests-toolbelt = [ {file = "requests-toolbelt-0.8.0.tar.gz", hash = "sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5"}, {file = "requests_toolbelt-0.8.0-py2.py3-none-any.whl", hash = "sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237"}, ] secretstorage = [ {file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"}, {file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"}, ] shellingham = [ {file = "shellingham-1.4.0-py2.py3-none-any.whl", hash = "sha256:536b67a0697f2e4af32ab176c00a50ac2899c5a05e0d8e2dadac8e58888283f9"}, {file = "shellingham-1.4.0.tar.gz", hash = "sha256:4855c2458d6904829bd34c299f11fdeed7cfefbf8a2c522e4caea6cd76b3171e"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomli = [ {file = "tomli-1.2.1-py3-none-any.whl", hash = "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f"}, {file = "tomli-1.2.1.tar.gz", hash = "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442"}, ] tomlkit = [ {file = "tomlkit-0.5.11-py2.py3-none-any.whl", hash = "sha256:4e1bd6c9197d984528f9ff0cc9db667c317d8881288db50db20eeeb0f6b0380b"}, {file = "tomlkit-0.5.11.tar.gz", hash = "sha256:f044eda25647882e5ef22b43a1688fb6ab12af2fc50e8456cdfc751c873101cf"}, ] tox = [ {file = "tox-3.24.3-py2.py3-none-any.whl", hash = "sha256:9fbf8e2ab758b2a5e7cb2c72945e4728089934853076f67ef18d7575c8ab6b88"}, {file = "tox-3.24.3.tar.gz", hash = "sha256:c6c4e77705ada004283610fd6d9ba4f77bc85d235447f875df9f0ba1bc23b634"}, ] tox-poetry-installer = [ {file = "tox-poetry-installer-0.8.1.tar.gz", hash = "sha256:e3ee6578baa7f0ff9129182cc68af9eb0bbde520f9b0460a3f6e451579832c21"}, {file = "tox_poetry_installer-0.8.1-py3-none-any.whl", hash = "sha256:7acb70fa996d36168fd4de6f86d8e045e972844b8ad955d6768b77518af82e7f"}, ] typing-extensions = [ {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, ] urllib3 = [ {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, ] virtualenv = [ {file = "virtualenv-20.7.2-py2.py3-none-any.whl", hash = "sha256:e4670891b3a03eb071748c569a87cceaefbf643c5bac46d996c5a45c34aa0f06"}, {file = "virtualenv-20.7.2.tar.gz", hash = "sha256:9ef4e8ee4710826e98ff3075c9a4739e2cb1040de6a2a8d35db0055840dc96a0"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, ] webencodings = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] wrapt = [ {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, ] py-rnp-main/pyproject.toml000066400000000000000000000007151432224606000161430ustar00rootroot00000000000000[tool.poetry] name = "rnp" version = "0.1.0" description = "python bindings for librnp" authors = ["Daniel Wyatt "] [tool.poetry.dependencies] python = "^3.9" [tool.poetry.dev-dependencies] pytest = "^5.2" tox = "^3.24.3" black = "^21.8b0" flake8 = "^3.9.2" pylint = "^2.10.2" tox-poetry-installer = {extras = ["poetry"], version = "^0.8.1"} [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" py-rnp-main/rnp/000077500000000000000000000000001432224606000140235ustar00rootroot00000000000000py-rnp-main/rnp/__init__.py000066400000000000000000000024001432224606000161300ustar00rootroot00000000000000__version__ = "0.1.0" __all__ = [ "Rnp", "RnpException", "Input", "Output", "Key", "UID", "Signature", "Generate", "Sign", "Verify", "Encrypt", "version_string", "version_string_full", "version", "version_major", "version_minor", "version_patch", "version_for", "commit_time", "enable_debug", "disable_debug", "default_homedir", "homedir_info", "key_format", "calculate_iterations", "supports", "features", "enarmor", "dearmor", "parse", "guess_contents", "check", ] from .rnp import Rnp from .lib import RnpException from .input import Input from .output import Output from .key import Key from .uid import UID from .signature import Signature from .op.generate import Generate from .op.sign import Sign from .op.verify import Verify from .op.encrypt import Encrypt from .misc import ( version_string, version_string_full, version, version_major, version_minor, version_patch, version_for, commit_time, enable_debug, disable_debug, default_homedir, homedir_info, key_format, calculate_iterations, supports, features, enarmor, dearmor, parse, guess_contents, check, ) py-rnp-main/rnp/input.py000066400000000000000000000033661432224606000155440ustar00rootroot00000000000000from ctypes import ( c_bool, c_uint8, c_void_p, c_size_t, byref, py_object, cast, POINTER, CFUNCTYPE, ) from .lib import _lib class Input: def __init__(self, obj, io=None): self._obj = obj self._io = io def __del__(self): _lib.rnp_input_destroy(self._obj) def obj(self): return self._obj @staticmethod def from_path(path): obj = c_void_p() _lib.rnp_input_from_path(byref(obj), path.encode("utf-8")) return Input(obj) @staticmethod def from_bytes(data): obj = c_void_p() buf = (c_uint8 * len(data)).from_buffer_copy(data) _lib.rnp_input_from_memory(byref(obj), buf, len(data), True) return Input(obj) @staticmethod def from_io(io): obj = c_void_p() io = py_object(io) _lib.rnp_input_from_callback(byref(obj), Input.READER, Input.CLOSER, byref(io)) return Input(obj, io) @staticmethod @CFUNCTYPE(c_bool, c_void_p, c_void_p, c_size_t, POINTER(c_size_t)) def READER(app_ctx, buf, buf_len, read): try: io = cast(app_ctx, POINTER(py_object)).contents.value data = io.read(buf_len) if isinstance(data, str): data = data.encode("utf-8") buf = (c_uint8 * buf_len).from_address(buf) buf[: len(data)] = data[: len(data)] read.contents.value = len(data) return True except Exception as e: print(e) return False @staticmethod @CFUNCTYPE(None, c_void_p) def CLOSER(app_ctx): try: io = cast(app_ctx, POINTER(py_object)).contents.value io.close() except Exception as e: print(e) py-rnp-main/rnp/key.py000066400000000000000000000267621432224606000152020ustar00rootroot00000000000000import json from ctypes import ( c_char_p, c_size_t, c_uint8, c_uint32, c_uint64, c_bool, c_void_p, byref, pointer, addressof, ) from .lib import ( _lib, _encode, _flags, RNP_KEY_EXPORT_ARMORED, RNP_KEY_EXPORT_PUBLIC, RNP_KEY_EXPORT_SECRET, RNP_KEY_EXPORT_SUBKEYS, RNP_JSON_PUBLIC_MPIS, RNP_JSON_SECRET_MPIS, RNP_JSON_SIGNATURES, RNP_JSON_SIGNATURE_MPIS, RNP_KEY_REMOVE_PUBLIC, RNP_KEY_REMOVE_SECRET, RNP_KEY_REMOVE_SUBKEYS, RNP_JSON_DUMP_MPI, RNP_JSON_DUMP_RAW, RNP_JSON_DUMP_GRIP, RNP_KEY_SUBKEYS_ONLY, RNP_ERROR_KEY_NOT_FOUND, RNP_ERROR_NO_SUITABLE_KEY, RnpException, ) from .output import Output class Key: def __init__(self, obj, free=True): self._obj = obj self._free = free def __del__(self): if self._free: _lib.rnp_key_handle_destroy(self._obj) def obj(self): return self._obj def alg(self): return self._string_property(_lib.rnp_key_get_alg) def fingerprint(self): return self._string_property(_lib.rnp_key_get_fprint) def keyid(self): return self._string_property(_lib.rnp_key_get_keyid) def grip(self): return self._string_property(_lib.rnp_key_get_grip) def primary_grip(self): return self._string_property(_lib.rnp_key_get_primary_grip) def primary_fingerprint(self): return self._string_property(_lib.rnp_key_get_primary_fprint) def primary_userid(self): return self._string_property(_lib.rnp_key_get_primary_uid) def userids(self): from .uid import UID return map( lambda uid: uid.data().decode("utf-8"), filter(lambda uid: uid.type() == UID.RNP_USER_ID, self.uids()), ) def uids(self): from .uid import UID count = c_size_t() _lib.rnp_key_get_uid_count(self._obj, byref(count)) for i in range(count.value): userid = c_void_p() _lib.rnp_key_get_uid_handle_at(self._obj, i, byref(userid)) yield UID(userid.value) def add_userid( self, userid, hashalg=None, expiration_time=0, key_flags=0, primary=False ): _lib.rnp_key_add_uid( self._obj, userid.encode("utf-8"), _encode(hashalg), expiration_time, key_flags, primary, ) def signatures(self): from .signature import Signature count = c_size_t() _lib.rnp_key_get_signature_count(self._obj, byref(count)) for i in range(count.value): psig = c_void_p() _lib.rnp_key_get_signature_at(self._obj, i, byref(psig)) yield Signature(psig.value) def bits(self): bits = c_uint32() _lib.rnp_key_get_bits(self._obj, byref(bits)) return bits.value def qbits(self): qbits = c_uint32() _lib.rnp_key_get_dsa_qbits(self._obj, byref(qbits)) return qbits.value def curve(self): return self._string_property(_lib.rnp_key_get_curve) def is_locked(self): pbool = c_bool() _lib.rnp_key_is_locked(self.obj(), byref(pbool)) return pbool.value def lock(self): _lib.rnp_key_lock(self.obj()) def unlock(self, password=None): _lib.rnp_key_unlock(self._obj, _encode(password)) def is_protected(self): pbool = c_bool() _lib.rnp_key_is_protected(self.obj(), byref(pbool)) return pbool.value def protect( self, password, cipher=None, cipher_mode=None, s2k_hashalg=None, s2k_iterations=0, ): _lib.rnp_key_protect( self._obj, _encode(password), _encode(cipher), _encode(cipher_mode), _encode(s2k_hashalg), s2k_iterations, ) def unprotect(self, password=None): _lib.rnp_key_unprotect(self._obj, _encode(password)) def is_primary(self): return self._bool_property(_lib.rnp_key_is_primary) def is_sub(self): return self._bool_property(_lib.rnp_key_is_sub) def has_public_key(self): return self._bool_property(_lib.rnp_key_have_public) def has_secret_key(self): return self._bool_property(_lib.rnp_key_have_secret) def is_valid(self): return self._bool_property(_lib.rnp_key_is_valid) def protection_cipher(self): return self._string_property(_lib.rnp_key_get_protection_cipher) def protection_hashalg(self): return self._string_property(_lib.rnp_key_get_protection_hash) def protection_mode(self): return self._string_property(_lib.rnp_key_get_protection_mode) def protection_type(self): return self._string_property(_lib.rnp_key_get_protection_type) def protection_iterations(self): return self._size_t_property(_lib.rnp_key_get_protection_iterations) def export_public(self, armored=True, include_subkeys=False, outp=None): with Output.default(outp) as outp: self._export(armored, True, False, include_subkeys, outp) return outp.default_output() def export_secret(self, armored=True, include_subkeys=False, outp=None): with Output.default(outp) as outp: self._export(armored, False, True, include_subkeys, outp) return outp.default_output() def export_revocation(self, hashalg=None, code=None, reason=None, outp=None): with Output.default(outp) as outp: _lib.rnp_key_export_revocation( self.obj(), outp.obj(), 0, _encode(hashalg), _encode(code), _encode(reason), ) return outp.default_output() def public_key_data(self): return self._buf_property(_lib.rnp_get_public_key_data) def secret_key_data(self): return self._buf_property(_lib.rnp_get_secret_key_data) def to(self, usage, subkeys_only=False): pkey = c_void_p() flags = _flags([(subkeys_only, RNP_KEY_SUBKEYS_ONLY)]) rc = _lib.rnp_key_get_default_key( self._obj, usage.encode("ascii"), flags, byref(pkey) ) if rc not in [0, RNP_ERROR_KEY_NOT_FOUND, RNP_ERROR_NO_SUITABLE_KEY]: raise RnpException("rnp_key_get_default_key failed", rc) if pkey.value: return Key(pkey.value) return None def json( self, public_mpis=False, secret_mpis=False, signatures=True, signature_mpis=False, ): flags = _flags( [ (public_mpis, RNP_JSON_PUBLIC_MPIS), (secret_mpis, RNP_JSON_SECRET_MPIS), (signatures, RNP_JSON_SIGNATURES), (signature_mpis, RNP_JSON_SIGNATURE_MPIS), ] ) jsn = c_char_p() try: _lib.rnp_key_to_json(self._obj, flags, byref(jsn)) # pylint: disable=E1101 return json.loads(jsn.value.decode("utf-8")) finally: _lib.rnp_buffer_destroy(jsn) def packets_json(self, secret=False, mpi=False, raw=False, grip=False): flags = _flags( [ (mpi, RNP_JSON_DUMP_MPI), (raw, RNP_JSON_DUMP_RAW), (grip, RNP_JSON_DUMP_GRIP), ] ) jsn = c_char_p() try: _lib.rnp_key_packets_to_json(self._obj, secret, flags, byref(jsn)) # pylint: disable=E1101 return json.loads(jsn.value.decode("utf-8")) finally: _lib.rnp_buffer_destroy(jsn) def remove(self, remove_public=True, remove_secret=True, remove_subkeys=False): flags = _flags( [ (remove_public, RNP_KEY_REMOVE_PUBLIC), (remove_secret, RNP_KEY_REMOVE_SECRET), (remove_subkeys, RNP_KEY_REMOVE_SUBKEYS), ] ) _lib.rnp_key_remove(self._obj, flags) def revoke(self, hashalg=None, code=None, reason=None): _lib.rnp_key_revoke( self._obj, 0, _encode(hashalg), _encode(code), _encode(reason) ) def revocation_signature(self): from .signature import Signature psig = c_void_p() _lib.rnp_key_get_revocation_signature(self._obj, byref(psig)) if psig.value: return Signature(psig.value) return None def subkeys(self): count = c_size_t() _lib.rnp_key_get_subkey_count(self._obj, byref(count)) for i in range(count.value): pkey = c_void_p() _lib.rnp_key_get_subkey_at(self._obj, i, byref(pkey)) yield Key(pkey.value) def can_sign(self): result = c_bool() _lib.rnp_key_allows_usage(self._obj, "sign".encode("ascii"), byref(result)) return result.value def can_certify(self): result = c_bool() _lib.rnp_key_allows_usage(self._obj, "certify".encode("ascii"), byref(result)) return result.value def can_encrypt(self): result = c_bool() _lib.rnp_key_allows_usage(self._obj, "encrypt".encode("ascii"), byref(result)) return result.value def can_authenticate(self): result = c_bool() _lib.rnp_key_allows_usage( self._obj, "authenticate".encode("ascii"), byref(result) ) return result.value def is_revoked(self): return self._bool_property(_lib.rnp_key_is_revoked) def is_compromised(self): return self._bool_property(_lib.rnp_key_is_compromised) def is_retired(self): return self._bool_property(_lib.rnp_key_is_retired) def is_superseded(self): return self._bool_property(_lib.rnp_key_is_superseded) def revocation_reason(self): return self._string_property(_lib.rnp_key_get_revocation_reason) def creation_time(self): time = c_uint32() _lib.rnp_key_get_creation(self._obj, byref(time)) return time.value def lifetime(self): secs = c_uint32() _lib.rnp_key_get_expiration(self._obj, byref(secs)) return secs.value def set_lifetime(self, secs): _lib.rnp_key_set_expiration(self._obj, secs) def valid_until(self): result = c_uint64() _lib.rnp_key_valid_till64(self._obj, byref(result)) return result.value def _export(self, armored, public_key, secret_key, include_subkeys, outp): flags = _flags( [ (armored, RNP_KEY_EXPORT_ARMORED), (public_key, RNP_KEY_EXPORT_PUBLIC), (secret_key, RNP_KEY_EXPORT_SECRET), (include_subkeys, RNP_KEY_EXPORT_SUBKEYS), ] ) _lib.rnp_key_export(self._obj, outp.obj(), flags) def _buf_property(self, fn): buf = pointer(c_uint8()) buf_len = c_size_t() try: fn(self._obj, byref(buf), byref(buf_len)) return bytes( (c_uint8 * buf_len.value).from_address(addressof(buf.contents)) ) finally: _lib.rnp_buffer_destroy(buf) def _string_property(self, fn): prop = c_char_p() try: fn(self._obj, byref(prop)) # pylint: disable=E1101 return prop.value.decode("utf-8") finally: _lib.rnp_buffer_destroy(prop) def _bool_property(self, fn): prop = c_bool() fn(self._obj, byref(prop)) return prop.value def _size_t_property(self, fn): prop = c_size_t() fn(self._obj, byref(prop)) return prop.value py-rnp-main/rnp/lib.py000066400000000000000000000452051432224606000151510ustar00rootroot00000000000000#!/usr/bin/env python import io from ctypes import ( CDLL, CFUNCTYPE, POINTER, c_uint8, c_uint32, c_uint64, c_char_p, c_void_p, c_bool, c_size_t, c_int, c_char, ) from sys import platform class RnpException(Exception): def __init__(self, message, rc=0): self.rc = rc if rc == 0: super(RnpException, self).__init__(message) else: desc = _lib.rnp_result_to_string(rc).decode("ascii") super(RnpException, self).__init__("%s: 0x%x (%s)" % (message, rc, desc)) def error_code(self): return self.rc PASS_PROVIDER = CFUNCTYPE( c_bool, c_void_p, c_void_p, c_void_p, c_char_p, POINTER(c_char), c_size_t ) KEY_PROVIDER = CFUNCTYPE(None, c_void_p, c_void_p, c_char_p, c_char_p, c_bool) INPUT_READER = CFUNCTYPE(c_bool, c_void_p, c_void_p, c_size_t, POINTER(c_size_t)) INPUT_CLOSER = CFUNCTYPE(None, c_void_p) OUTPUT_WRITER = CFUNCTYPE(c_bool, c_void_p, c_void_p, c_size_t) OUTPUT_CLOSER = CFUNCTYPE(None, c_void_p, c_bool) RNP_LOAD_SAVE_PUBLIC_KEYS = 1 << 0 RNP_LOAD_SAVE_SECRET_KEYS = 1 << 1 RNP_LOAD_SAVE_PERMISSIVE = 1 << 8 RNP_LOAD_SAVE_SINGLE = 1 << 9 RNP_KEY_EXPORT_ARMORED = 1 << 0 RNP_KEY_EXPORT_PUBLIC = 1 << 1 RNP_KEY_EXPORT_SECRET = 1 << 2 RNP_KEY_EXPORT_SUBKEYS = 1 << 3 RNP_JSON_PUBLIC_MPIS = 1 << 0 RNP_JSON_SECRET_MPIS = 1 << 1 RNP_JSON_SIGNATURES = 1 << 2 RNP_JSON_SIGNATURE_MPIS = 1 << 3 RNP_KEY_REMOVE_PUBLIC = 1 << 0 RNP_KEY_REMOVE_SECRET = 1 << 1 RNP_KEY_REMOVE_SUBKEYS = 1 << 2 RNP_JSON_DUMP_MPI = 1 << 0 RNP_JSON_DUMP_RAW = 1 << 1 RNP_JSON_DUMP_GRIP = 1 << 2 RNP_KEY_SUBKEYS_ONLY = 1 << 0 RNP_ERROR_KEY_NOT_FOUND = 0x12000005 RNP_ERROR_NO_SUITABLE_KEY = 0x12000006 def _load_lib(): libnames = [] if platform in ["win32", "cygin", "msys"]: libnames.extend(["rnp.dll", "librnp.dll"]) elif platform in ["darwin", "macos"]: libnames.extend(["rnp.dylib", "librnp.dylib"]) else: libnames.extend(["rnp.so", "librnp.so"]) for libname in libnames: try: return CDLL(libname) except OSError: pass raise RnpException("Unable to load rnp native library") def _errcheck(rc, fn, _args): if rc == 0: return rc raise RnpException("%s failed" % (fn.__name__), rc) def _setup(lib): def define(func, args): func.argtypes = args func.restype = c_uint32 func.errcheck = _errcheck lib.rnp_result_to_string.argtypes = [c_uint32] lib.rnp_result_to_string.restype = c_char_p lib.rnp_version_string.argtypes = [] lib.rnp_version_string.restype = c_char_p lib.rnp_version_string_full.argtypes = [] lib.rnp_version_string_full.restype = c_char_p lib.rnp_version.argtypes = [] lib.rnp_version.restype = c_uint32 lib.rnp_version_for.argtypes = [c_uint32, c_uint32, c_uint32] lib.rnp_version_for.restype = c_uint32 lib.rnp_version_major.argtypes = [] lib.rnp_version_major.restype = c_uint32 lib.rnp_version_minor.argtypes = [] lib.rnp_version_minor.restype = c_uint32 lib.rnp_version_patch.argtypes = [] lib.rnp_version_patch.restype = c_uint32 lib.rnp_version_commit_timestamp.argtypes = [] lib.rnp_version_commit_timestamp.restype = c_uint64 # features/quirks lib.features = { "have-rnp-signature-get-expiration": lib.rnp_version() > lib.rnp_version_for(0, 15, 2) or lib.rnp_version_commit_timestamp() > 1629965914, } lib.rnp_buffer_destroy.argtypes = [c_void_p] lib.rnp_buffer_destroy.restype = None define(lib.rnp_enable_debug, [c_char_p]) define(lib.rnp_disable_debug, []) define(lib.rnp_ffi_create, [c_void_p, c_char_p, c_char_p]) define(lib.rnp_ffi_destroy, [c_void_p]) define(lib.rnp_ffi_set_log_fd, [c_void_p, c_int]) define(lib.rnp_ffi_set_key_provider, [c_void_p, KEY_PROVIDER, c_void_p]) define(lib.rnp_ffi_set_pass_provider, [c_void_p, PASS_PROVIDER, c_void_p]) define(lib.rnp_get_default_homedir, [POINTER(c_char_p)]) define( lib.rnp_detect_homedir_info, [ c_char_p, POINTER(c_char_p), POINTER(c_char_p), POINTER(c_char_p), POINTER(c_char_p), ], ) define(lib.rnp_detect_key_format, [POINTER(c_uint8), c_size_t, POINTER(c_char_p)]) define(lib.rnp_calculate_iterations, [c_char_p, c_size_t, POINTER(c_size_t)]) define(lib.rnp_supports_feature, [c_char_p, c_char_p, POINTER(c_bool)]) define(lib.rnp_supported_features, [c_char_p, POINTER(c_char_p)]) define(lib.rnp_guess_contents, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_enarmor, [c_void_p, c_void_p, c_char_p]) define(lib.rnp_dearmor, [c_void_p, c_void_p]) define(lib.rnp_dump_packets_to_json, [c_void_p, c_uint32, POINTER(c_char_p)]) define(lib.rnp_load_keys, [c_void_p, c_char_p, c_void_p, c_uint32]) define(lib.rnp_unload_keys, [c_void_p, c_uint32]) define(lib.rnp_save_keys, [c_void_p, c_char_p, c_void_p, c_uint32]) define(lib.rnp_import_keys, [c_void_p, c_void_p, c_uint32, POINTER(c_char_p)]) define(lib.rnp_import_signatures, [c_void_p, c_void_p, c_uint32, POINTER(c_char_p)]) define(lib.rnp_get_public_key_count, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_get_secret_key_count, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_input_from_path, [POINTER(c_void_p), c_char_p]) define( lib.rnp_input_from_memory, [POINTER(c_void_p), POINTER(c_uint8), c_size_t, c_bool], ) define( lib.rnp_input_from_callback, [POINTER(c_void_p), INPUT_READER, INPUT_CLOSER, c_void_p], ) define(lib.rnp_input_destroy, [c_void_p]) define(lib.rnp_output_to_path, [POINTER(c_void_p), c_char_p]) define(lib.rnp_output_to_memory, [POINTER(c_void_p), c_size_t]) define( lib.rnp_output_memory_get_buf, [c_void_p, POINTER(POINTER(c_uint8)), POINTER(c_size_t), c_bool], ) define(lib.rnp_output_to_null, [POINTER(c_void_p)]) define( lib.rnp_output_to_callback, [c_void_p, OUTPUT_WRITER, OUTPUT_CLOSER, c_void_p] ) define(lib.rnp_output_destroy, [c_void_p]) define(lib.rnp_locate_key, [c_void_p, c_char_p, c_char_p, POINTER(c_void_p)]) define(lib.rnp_generate_key_json, [c_void_p, c_char_p, POINTER(c_char_p)]) define( lib.rnp_generate_key_rsa, [c_void_p, c_uint32, c_uint32, c_char_p, c_char_p, POINTER(c_void_p)], ) define( lib.rnp_generate_key_dsa_eg, [c_void_p, c_uint32, c_uint32, c_char_p, c_char_p, POINTER(c_void_p)], ) define( lib.rnp_generate_key_ec, [c_void_p, c_char_p, c_char_p, c_char_p, POINTER(c_void_p)], ) define( lib.rnp_generate_key_25519, [c_void_p, c_char_p, c_char_p, POINTER(c_void_p)] ) define(lib.rnp_generate_key_sm2, [c_void_p, c_char_p, c_char_p, POINTER(c_void_p)]) define( lib.rnp_generate_key_ex, [ c_void_p, c_char_p, c_char_p, c_uint32, c_uint32, c_char_p, c_char_p, c_char_p, c_char_p, POINTER(c_void_p), ], ) define(lib.rnp_ffi_set_pass_provider, [c_void_p, PASS_PROVIDER, c_void_p]) define(lib.rnp_decrypt, [c_void_p, c_void_p, c_void_p]) define(lib.rnp_key_handle_destroy, [c_void_p]) define(lib.rnp_key_get_keyid, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_fprint, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_grip, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_primary_grip, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_primary_fprint, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_uid_count, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_key_get_uid_at, [c_void_p, c_size_t, POINTER(c_char_p)]) define(lib.rnp_key_get_uid_handle_at, [c_void_p, c_size_t, POINTER(c_void_p)]) define(lib.rnp_key_get_primary_uid, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_alg, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_bits, [c_void_p, POINTER(c_uint32)]) define(lib.rnp_key_get_dsa_qbits, [c_void_p, POINTER(c_uint32)]) define(lib.rnp_key_get_curve, [c_void_p, POINTER(c_char_p)]) define( lib.rnp_key_add_uid, [c_void_p, c_char_p, c_char_p, c_uint32, c_uint8, c_bool] ) define(lib.rnp_key_export, [c_void_p, c_void_p, c_uint32]) define( lib.rnp_key_export_autocrypt, [c_void_p, c_void_p, c_char_p, c_void_p, c_uint32] ) define( lib.rnp_key_export_revocation, [c_void_p, c_void_p, c_uint32, c_char_p, c_char_p, c_char_p], ) define(lib.rnp_key_remove, [c_void_p, c_uint32]) define(lib.rnp_key_is_primary, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_is_sub, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_have_secret, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_have_public, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_to_json, [c_void_p, c_uint32, POINTER(c_char_p)]) define(lib.rnp_key_is_revoked, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_get_revocation_reason, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_revocation_signature, [c_void_p, POINTER(c_void_p)]) define(lib.rnp_key_is_superseded, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_is_compromised, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_is_retired, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_allows_usage, [c_void_p, c_char_p, POINTER(c_bool)]) define(lib.rnp_key_get_creation, [c_void_p, POINTER(c_uint32)]) define(lib.rnp_key_get_expiration, [c_void_p, POINTER(c_uint32)]) define(lib.rnp_key_set_expiration, [c_void_p, c_uint32]) define(lib.rnp_key_get_signature_count, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_key_get_signature_at, [c_void_p, c_size_t, POINTER(c_void_p)]) define(lib.rnp_key_get_subkey_count, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_key_get_subkey_at, [c_void_p, c_size_t, POINTER(c_void_p)]) define(lib.rnp_key_lock, [c_void_p]) define(lib.rnp_key_unlock, [c_void_p, c_char_p]) define(lib.rnp_key_is_locked, [c_void_p, POINTER(c_bool)]) define( lib.rnp_key_protect, [c_void_p, c_char_p, c_char_p, c_char_p, c_char_p, c_size_t], ) define(lib.rnp_key_unprotect, [c_void_p, c_char_p]) define(lib.rnp_key_is_protected, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_packets_to_json, [c_void_p, c_bool, c_uint32, POINTER(c_char_p)]) define(lib.rnp_key_revoke, [c_void_p, c_uint32, c_char_p, c_char_p, c_char_p]) define( lib.rnp_get_public_key_data, [c_void_p, POINTER(POINTER(c_uint8)), POINTER(c_size_t)], ) define( lib.rnp_get_secret_key_data, [c_void_p, POINTER(POINTER(c_uint8)), POINTER(c_size_t)], ) define(lib.rnp_key_is_valid, [c_void_p, POINTER(c_bool)]) define(lib.rnp_key_get_protection_cipher, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_protection_hash, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_protection_mode, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_protection_type, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_key_get_protection_iterations, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_key_valid_till64, [c_void_p, POINTER(c_uint64)]) lib.rnp_key_get_default_key.argtypes = [ c_void_p, c_char_p, c_uint32, POINTER(c_void_p), ] lib.rnp_key_get_default_key.restype = c_uint32 define(lib.rnp_uid_get_type, [c_void_p, POINTER(c_uint32)]) define(lib.rnp_uid_get_data, [c_void_p, POINTER(c_void_p), POINTER(c_size_t)]) define(lib.rnp_uid_is_primary, [c_void_p, POINTER(c_bool)]) define(lib.rnp_uid_is_valid, [c_void_p, POINTER(c_bool)]) define(lib.rnp_uid_is_revoked, [c_void_p, POINTER(c_bool)]) define(lib.rnp_uid_get_revocation_signature, [c_void_p, POINTER(c_void_p)]) define(lib.rnp_uid_get_signature_count, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_uid_get_signature_at, [c_void_p, c_size_t, POINTER(c_void_p)]) define(lib.rnp_uid_remove, [c_void_p, c_void_p]) define(lib.rnp_uid_handle_destroy, [c_void_p]) define(lib.rnp_identifier_iterator_create, [c_void_p, POINTER(c_void_p), c_char_p]) define(lib.rnp_identifier_iterator_next, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_identifier_iterator_destroy, [c_void_p]) define(lib.rnp_signature_handle_destroy, [c_void_p]) define(lib.rnp_signature_get_type, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_signature_get_alg, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_signature_get_hash_alg, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_signature_get_keyid, [c_void_p, POINTER(c_char_p)]) define(lib.rnp_signature_get_creation, [c_void_p, POINTER(c_uint32)]) if lib.features["have-rnp-signature-get-expiration"]: define(lib.rnp_signature_get_expiration, [c_void_p, POINTER(c_uint32)]) define(lib.rnp_signature_get_signer, [c_void_p, POINTER(c_void_p)]) define(lib.rnp_signature_packet_to_json, [c_void_p, c_uint32, POINTER(c_char_p)]) lib.rnp_signature_is_valid.argtypes = [c_void_p, c_uint32] lib.rnp_signature_is_valid.restype = c_uint32 define(lib.rnp_op_sign_create, [POINTER(c_void_p), c_void_p, c_void_p, c_void_p]) define( lib.rnp_op_sign_cleartext_create, [POINTER(c_void_p), c_void_p, c_void_p, c_void_p], ) define( lib.rnp_op_sign_detached_create, [POINTER(c_void_p), c_void_p, c_void_p, c_void_p], ) define(lib.rnp_op_sign_destroy, [c_void_p]) define(lib.rnp_op_sign_set_armor, [c_void_p, c_bool]) define(lib.rnp_op_sign_set_hash, [c_void_p, c_char_p]) define(lib.rnp_op_sign_set_compression, [c_void_p, c_char_p]) define(lib.rnp_op_sign_set_creation_time, [c_void_p, c_uint32]) define(lib.rnp_op_sign_set_expiration_time, [c_void_p, c_uint32]) define(lib.rnp_op_sign_add_signature, [c_void_p, c_void_p, POINTER(c_void_p)]) define(lib.rnp_op_sign_signature_set_hash, [c_void_p, c_char_p]) define(lib.rnp_op_sign_signature_set_creation_time, [c_void_p, c_uint32]) define(lib.rnp_op_sign_signature_set_expiration_time, [c_void_p, c_uint32]) define(lib.rnp_op_sign_execute, [c_void_p]) define(lib.rnp_op_sign_set_file_mtime, [c_void_p, c_uint32]) define(lib.rnp_op_sign_set_file_name, [c_void_p, c_char_p]) define(lib.rnp_op_verify_create, [POINTER(c_void_p), c_void_p, c_void_p, c_void_p]) define( lib.rnp_op_verify_detached_create, [POINTER(c_void_p), c_void_p, c_void_p, c_void_p], ) define(lib.rnp_op_verify_destroy, [c_void_p]) define(lib.rnp_op_verify_execute, [c_void_p]) define(lib.rnp_op_verify_get_signature_count, [c_void_p, POINTER(c_size_t)]) define(lib.rnp_op_verify_get_signature_at, [c_void_p, c_size_t, POINTER(c_void_p)]) define(lib.rnp_op_verify_signature_get_handle, [c_void_p, POINTER(c_void_p)]) define( lib.rnp_op_verify_get_file_info, [c_void_p, POINTER(c_char_p), POINTER(c_uint32)], ) define( lib.rnp_op_verify_get_protection_info, [c_void_p, POINTER(c_char_p), POINTER(c_char_p), POINTER(c_bool)], ) lib.rnp_op_verify_signature_get_status.argtypes = [c_void_p] lib.rnp_op_verify_signature_get_status.restype = c_uint32 define(lib.rnp_op_generate_create, [POINTER(c_void_p), c_void_p, c_char_p]) define(lib.rnp_op_generate_execute, [c_void_p]) define(lib.rnp_op_generate_destroy, [c_void_p]) define( lib.rnp_op_generate_subkey_create, [POINTER(c_void_p), c_void_p, c_void_p, c_char_p], ) define(lib.rnp_op_generate_set_bits, [c_void_p, c_uint32]) define(lib.rnp_op_generate_set_hash, [c_void_p, c_char_p]) define(lib.rnp_op_generate_set_dsa_qbits, [c_void_p, c_uint32]) define(lib.rnp_op_generate_set_curve, [c_void_p, c_char_p]) define(lib.rnp_op_generate_set_protection_password, [c_void_p, c_char_p]) define(lib.rnp_op_generate_set_protection_cipher, [c_void_p, c_char_p]) define(lib.rnp_op_generate_set_protection_hash, [c_void_p, c_char_p]) define(lib.rnp_op_generate_set_protection_mode, [c_void_p, c_char_p]) define(lib.rnp_op_generate_set_protection_iterations, [c_void_p, c_uint32]) define(lib.rnp_op_generate_add_usage, [c_void_p, c_char_p]) define(lib.rnp_op_generate_clear_usage, [c_void_p]) define(lib.rnp_op_generate_set_userid, [c_void_p, c_char_p]) define(lib.rnp_op_generate_set_expiration, [c_void_p, c_uint32]) define(lib.rnp_op_generate_add_pref_hash, [c_void_p, c_char_p]) define(lib.rnp_op_generate_clear_pref_hashes, [c_void_p]) define(lib.rnp_op_generate_add_pref_compression, [c_void_p, c_char_p]) define(lib.rnp_op_generate_clear_pref_compression, [c_void_p]) define(lib.rnp_op_generate_add_pref_cipher, [c_void_p, c_char_p]) define(lib.rnp_op_generate_clear_pref_ciphers, [c_void_p]) define(lib.rnp_op_generate_set_pref_keyserver, [c_void_p, c_char_p]) define(lib.rnp_op_generate_get_key, [c_void_p, POINTER(c_void_p)]) define(lib.rnp_op_encrypt_create, [POINTER(c_void_p), c_void_p, c_void_p, c_void_p]) define(lib.rnp_op_encrypt_destroy, [c_void_p]) define(lib.rnp_op_encrypt_execute, [c_void_p]) define( lib.rnp_op_encrypt_add_password, [c_void_p, c_char_p, c_char_p, c_size_t, c_char_p], ) define(lib.rnp_op_encrypt_add_recipient, [c_void_p, c_void_p]) define(lib.rnp_op_encrypt_add_signature, [c_void_p, c_void_p, POINTER(c_void_p)]) define(lib.rnp_op_encrypt_set_aead, [c_void_p, c_char_p]) define(lib.rnp_op_encrypt_set_aead_bits, [c_void_p, c_int]) define(lib.rnp_op_encrypt_set_armor, [c_void_p, c_bool]) define(lib.rnp_op_encrypt_set_cipher, [c_void_p, c_char_p]) define(lib.rnp_op_encrypt_set_hash, [c_void_p, c_char_p]) define(lib.rnp_op_encrypt_set_compression, [c_void_p, c_char_p, c_int]) define(lib.rnp_op_encrypt_set_creation_time, [c_void_p, c_uint32]) define(lib.rnp_op_encrypt_set_expiration_time, [c_void_p, c_uint32]) define(lib.rnp_op_encrypt_set_file_mtime, [c_void_p, c_uint32]) define(lib.rnp_op_encrypt_set_file_name, [c_void_p, c_char_p]) def _encode(value): if isinstance(value, str): return value.encode("utf-8") return value def _obj(value): if value is not None: return value.obj() def _flags(flags): from functools import reduce import operator return reduce( operator.or_, map(operator.itemgetter(1), filter(operator.itemgetter(0), flags)), 0, ) def _inp(inp): from rnp import Input if isinstance(inp, (bytes, bytearray)): inp = Input.from_bytes(inp) elif isinstance(inp, str): inp = Input.from_bytes(str.encode("utf-8")) elif isinstance(inp, io.IOBase): inp = Input.from_io(inp) return inp _lib = _load_lib() _setup(_lib) py-rnp-main/rnp/misc.py000066400000000000000000000111621432224606000153310ustar00rootroot00000000000000from ctypes import pointer, c_uint8, c_char_p, c_bool, c_size_t, byref import json from .lib import ( _lib, _encode, _flags, _inp, RNP_JSON_DUMP_MPI, RNP_JSON_DUMP_RAW, RNP_JSON_DUMP_GRIP, ) from .output import Output def version_string(): return _lib.rnp_version_string().decode("ascii") def version_string_full(): return _lib.rnp_version_string_full().decode("ascii") def version(ver=None): if ver is None: return _lib.rnp_version() components = list(map(int, ver.split("."))) assert len(components) == 3 return _lib.rnp_version_for(components[0], components[1], components[2]) def version_for(major, minor, patch): return _lib.rnp_version_for(major, minor, patch) def version_major(): return _lib.rnp_version_major() def version_minor(): return _lib.rnp_version_minor() def version_patch(): return _lib.rnp_version_patch() def commit_time(): return _lib.rnp_version_commit_timestamp() def enable_debug(files=None): _lib.rnp_enable_debug(_encode(files)) def disable_debug(): _lib.rnp_disable_debug() def default_homedir(): try: homedir = None phomedir = pointer(c_char_p()) _lib.rnp_get_default_homedir(phomedir) homedir = phomedir.contents return homedir.value.decode("utf-8") finally: _lib.rnp_buffer_destroy(homedir) def homedir_info(homedir): try: pub_format = pub_path = sec_format = sec_path = None ppub_format = pointer(c_char_p()) ppub_path = pointer(c_char_p()) psec_format = pointer(c_char_p()) psec_path = pointer(c_char_p()) _lib.rnp_detect_homedir_info( homedir.encode("utf-8"), ppub_format, ppub_path, psec_format, psec_path ) pub_format = ppub_format.contents pub_path = ppub_path.contents sec_format = psec_format.contents sec_path = psec_path.contents return { "public": { "format": pub_format.value.decode("utf-8"), "path": pub_path.value.decode("utf-8"), }, "secret": { "format": sec_format.value.decode("utf-8"), "path": sec_path.value.decode("utf-8"), }, } finally: _lib.rnp_buffer_destroy(pub_format) _lib.rnp_buffer_destroy(pub_path) _lib.rnp_buffer_destroy(sec_format) _lib.rnp_buffer_destroy(sec_path) def key_format(keybytes): try: fmt = None pfmt = pointer(c_char_p()) buf = (c_uint8 * len(keybytes)).from_buffer_copy(keybytes) _lib.rnp_detect_key_format(buf, len(keybytes), pfmt) fmt = pfmt.contents if not fmt.value: return None return fmt.value.decode("utf-8") finally: _lib.rnp_buffer_destroy(fmt) def calculate_iterations(hashalg, msec): iters = c_size_t() _lib.rnp_calculate_iterations(hashalg.encode("ascii"), msec, byref(iters)) return iters.value def supports(ftype, fname): supported = c_bool() _lib.rnp_supports_feature( ftype.encode("ascii"), fname.encode("ascii"), byref(supported) ) return supported.value def features(ftype): try: jsn = None pjsn = pointer(c_char_p()) _lib.rnp_supported_features(ftype.encode("ascii"), pjsn) jsn = pjsn.contents return json.loads(jsn.value.decode("ascii")) finally: _lib.rnp_buffer_destroy(jsn) def enarmor(inp, outp=None, typ=None): inp = _inp(inp) with Output.default(outp) as outp: _lib.rnp_enarmor(inp.obj(), outp.obj(), _encode(typ)) return outp.default_output() def dearmor(inp, outp=None): inp = _inp(inp) with Output.default(outp) as outp: _lib.rnp_dearmor(inp.obj(), outp.obj()) return outp.default_output() def parse(inp, mpi=False, raw=False, grip=False): inp = _inp(inp) flags = _flags( [ (mpi, RNP_JSON_DUMP_MPI), (raw, RNP_JSON_DUMP_RAW), (grip, RNP_JSON_DUMP_GRIP), ] ) jsn = c_char_p() try: _lib.rnp_dump_packets_to_json(inp.obj(), flags, byref(jsn)) if jsn.value is not None: # pylint: disable=E1101 return json.loads(jsn.value.decode("utf-8")) return None finally: _lib.rnp_buffer_destroy(jsn) def guess_contents(inp): inp = _inp(inp) result = c_char_p() try: _lib.rnp_guess_contents(inp.obj(), byref(result)) # pylint: disable=E1101 return result.value.decode("utf-8") finally: _lib.rnp_buffer_destroy(result) def check(quirk): return _lib.features.get(quirk) py-rnp-main/rnp/op/000077500000000000000000000000001432224606000144415ustar00rootroot00000000000000py-rnp-main/rnp/op/__init__.py000066400000000000000000000000001432224606000165400ustar00rootroot00000000000000py-rnp-main/rnp/op/encrypt.py000066400000000000000000000100511432224606000164740ustar00rootroot00000000000000from ctypes import c_void_p, byref from ..lib import _lib, _encode, _inp from ..key import Key class Encrypt: def __init__(self, obj, io): self._obj = obj self._armored = None self._compression = None self._cipher = None self._aead = None self._aead_bits = None self._hashalg = None self._creation_time = None self._lifetime = None self._file_mtime = None self._filename = None self._io = io def __del__(self): _lib.rnp_op_encrypt_destroy(self._obj) def obj(self): return self._obj @staticmethod def start(rnp, inp, outp): inp = _inp(inp) pop = c_void_p() _lib.rnp_op_encrypt_create(byref(pop), rnp.obj(), inp.obj(), outp.obj()) if pop.value: return Encrypt(pop, (inp, outp)) @property def armored(self): return self._armored @armored.setter def armored(self, armored): _lib.rnp_op_encrypt_set_armor(self._obj, armored) self._armored = armored @property def cipher(self): return self._cipher @cipher.setter def cipher(self, cipher): _lib.rnp_op_encrypt_set_cipher(self._obj, cipher.encode("ascii")) self._cipher = cipher @property def aead(self): return self._aead @aead.setter def aead(self, aead): _lib.rnp_op_encrypt_set_aead(self._obj, aead.encode("ascii")) self._aead = aead @property def aead_bits(self): return self._aead_bits @aead_bits.setter def aead_bits(self, aead_bits): _lib.rnp_op_encrypt_set_aead_bits(self._obj, aead_bits) self._aead_bits = aead_bits @property def compression(self): return self._compression @compression.setter def compression(self, compression): if compression is None: compression = ("Uncompressed", 0) _lib.rnp_op_encrypt_set_compression( self._obj, compression[0].encode("ascii"), compression[1] ) self._compression = compression @property def hashalg(self): return self._hashalg @hashalg.setter def hashalg(self, hashalg): _lib.rnp_op_encrypt_set_hash(self._obj, hashalg.encode("ascii")) self._hashalg = hashalg @property def creation_time(self): return self._creation_time @creation_time.setter def creation_time(self, creation_time): _lib.rnp_op_encrypt_set_creation_time(self._obj, creation_time) self._creation_time = creation_time @property def lifetime(self): return self._lifetime @lifetime.setter def lifetime(self, lifetime): _lib.rnp_op_encrypt_set_expiration_time(self._obj, lifetime) self._lifetime = lifetime @property def file_mtime(self): return self._file_mtime @file_mtime.setter def file_mtime(self, mtime): self._file_mtime = mtime _lib.rnp_op_encrypt_set_file_mtime(self._obj, mtime) @property def filename(self): return self._filename @filename.setter def filename(self, name): self._filename = name _lib.rnp_op_encrypt_set_file_name(self._obj, _encode(name)) def add_recipient(self, recipient): assert isinstance(recipient, Key) _lib.rnp_op_encrypt_add_recipient(self._obj, recipient.obj()) def add_password( self, password, s2k_hashalg=None, iterations=None, s2k_cipher=None ): _lib.rnp_op_encrypt_add_password( self._obj, password.encode("utf-8"), _encode(s2k_hashalg), iterations or 0, _encode(s2k_cipher), ) def add_signature(self, signer, hashalg=None, creation_time=None, lifetime=None): from .sign import Sign assert isinstance(signer, Key) psig = c_void_p() _lib.rnp_op_encrypt_add_signature(self._obj, signer.obj(), byref(psig)) Sign._set_signature_opts(psig, hashalg, creation_time, lifetime) def finish(self): _lib.rnp_op_encrypt_execute(self._obj) py-rnp-main/rnp/op/generate.py000066400000000000000000000120061432224606000166040ustar00rootroot00000000000000from ctypes import c_void_p, byref from ..lib import _lib from ..key import Key class Generate: def __init__(self, obj): self._obj = obj self._bits = None self._hashalg = None self._qbits = None self._curve = None self._password = None self._cipher = None self._s2k_hashalg = None self._protection_mode = None self._s2k_iterations = None self._usage = None self._uid = None self._lifetime = None self._preferences = None def __del__(self): _lib.rnp_op_generate_destroy(self._obj) def obj(self): return self._obj @staticmethod def start(rnp, typ): pop = c_void_p() _lib.rnp_op_generate_create(byref(pop), rnp.obj(), typ.encode("ascii")) if pop.value: return Generate(pop) @staticmethod def start_subkey(rnp, primary, typ): pop = c_void_p() _lib.rnp_op_generate_subkey_create( byref(pop), rnp.obj(), primary.obj(), typ.encode("ascii") ) if pop.value: return Generate(pop) @property def bits(self): return self._bits @bits.setter def bits(self, value): _lib.rnp_op_generate_set_bits(self.obj(), value) self._bits = value @property def hashalg(self): return self._hashalg @hashalg.setter def hashalg(self, value): _lib.rnp_op_generate_set_hash(self.obj(), value.encode("ascii")) self._hashalg = value @property def qbits(self): return self._qbits @qbits.setter def qbits(self, value): _lib.rnp_op_generate_set_dsa_qbits(self.obj(), value) self._qbits = value @property def curve(self): return self._curve @curve.setter def curve(self, value): _lib.rnp_op_generate_set_curve(self.obj(), value.encode("ascii")) self._curve = value @property def password(self): return self._password @password.setter def password(self, value): _lib.rnp_op_generate_set_protection_password(self.obj(), value.encode("utf-8")) self._password = value @property def cipher(self): return self._cipher @cipher.setter def cipher(self, value): _lib.rnp_op_generate_set_protection_cipher(self.obj(), value.encode("ascii")) self._cipher = value @property def s2k_hashalg(self): return self._s2k_hashalg @s2k_hashalg.setter def s2k_hashalg(self, value): _lib.rnp_op_generate_set_protection_hash(self.obj(), value.encode("ascii")) self._s2k_hashalg = value @property def protection_mode(self): return self._protection_mode @protection_mode.setter def protection_mode(self, value): _lib.rnp_op_generate_set_protection_mode(self.obj(), value.encode("ascii")) self._protection_mode = value @property def s2k_iterations(self): return self._s2k_iterations @s2k_iterations.setter def s2k_iterations(self, value): _lib.rnp_op_generate_set_protection_iterations(self.obj(), value) self._s2k_iterations = value @property def usage(self): return self._usage @usage.setter def usage(self, value): _lib.rnp_op_generate_clear_usage(self.obj()) if not isinstance(value, list): value = [value] for usage in value: _lib.rnp_op_generate_add_usage(self.obj(), usage.encode("ascii")) self._usage = value @property def uid(self): return self._uid @uid.setter def uid(self, value): _lib.rnp_op_generate_set_userid(self.obj(), value.encode("utf-8")) self._uid = value @property def lifetime(self): return self._lifetime @lifetime.setter def lifetime(self, value): _lib.rnp_op_generate_set_expiration(self.obj(), value) self._lifetime = value @property def preferences(self): return self._preferences @preferences.setter def preferences(self, value): _lib.rnp_op_generate_clear_pref_hashes(self.obj()) _lib.rnp_op_generate_clear_pref_compression(self.obj()) _lib.rnp_op_generate_clear_pref_ciphers(self.obj()) _lib.rnp_op_generate_set_pref_keyserver(self.obj(), None) for alg in value.get("hashes"): _lib.rnp_op_generate_add_pref_hash(self.obj(), alg.encode("ascii")) for alg in value.get("compression"): _lib.rnp_op_generate_add_pref_compression(self.obj(), alg.encode("ascii")) for alg in value.get("ciphers"): _lib.rnp_op_generate_add_pref_cipher(self.obj(), alg.encode("ascii")) if value.get("key_server"): _lib.rnp_op_generate_set_pref_keyserver( self.obj(), value.get("key_server").encode("utf-8") ) def finish(self): _lib.rnp_op_generate_execute(self.obj()) handle = c_void_p() _lib.rnp_op_generate_get_key(self.obj(), byref(handle)) if handle: return Key(handle) py-rnp-main/rnp/op/sign.py000066400000000000000000000062011432224606000157520ustar00rootroot00000000000000from ctypes import c_void_p, byref from ..lib import _lib, _inp class Sign: def __init__(self, obj, io): self._obj = obj self._armored = None self._compression = None self._hashalg = None self._creation_time = None self._lifetime = None self._io = io def __del__(self): _lib.rnp_op_sign_destroy(self._obj) def obj(self): return self._obj @staticmethod def start(rnp, inp, outp): inp = _inp(inp) pop = c_void_p() _lib.rnp_op_sign_create(byref(pop), rnp.obj(), inp.obj(), outp.obj()) if pop.value: return Sign(pop, (inp, outp)) @staticmethod def start_cleartext(rnp, inp, outp): inp = _inp(inp) pop = c_void_p() _lib.rnp_op_sign_cleartext_create(byref(pop), rnp.obj(), inp.obj(), outp.obj()) if pop.value: return Sign(pop, (inp, outp)) @staticmethod def start_detached(rnp, inp, outp): inp = _inp(inp) pop = c_void_p() _lib.rnp_op_sign_detached_create(byref(pop), rnp.obj(), inp.obj(), outp.obj()) if pop.value: return Sign(pop, (inp, outp)) def add_signer(self, signer, hashalg=None, creation_time=None, lifetime=None): psig = c_void_p() _lib.rnp_op_sign_add_signature(self.obj(), signer.obj(), byref(psig)) Sign._set_signature_opts(psig, hashalg, creation_time, lifetime) @property def armored(self): return self._armored @armored.setter def armored(self, armored): _lib.rnp_op_sign_set_armor(self._obj, armored) self._armored = armored @property def compression(self): return self._compression @compression.setter def compression(self, compression): if compression is None: compression = ("Uncompressed", 0) _lib.rnp_op_sign_set_compression( self._obj, compression[0].encode("ascii"), compression[1] ) self._compression = compression @property def hashalg(self): return self._hashalg @hashalg.setter def hashalg(self, hashalg): _lib.rnp_op_sign_set_hash(self._obj, hashalg.encode("ascii")) self._hashalg = hashalg @property def creation_time(self): return self._creation_time @creation_time.setter def creation_time(self, creation_time): _lib.rnp_op_sign_set_creation_time(self._obj, creation_time) self._creation_time = creation_time @property def lifetime(self): return self._lifetime @lifetime.setter def lifetime(self, lifetime): _lib.rnp_op_sign_set_expiration_time(self._obj, lifetime) self._lifetime = lifetime def finish(self): _lib.rnp_op_sign_execute(self.obj()) @staticmethod def _set_signature_opts(psig, hashalg, creation_time, lifetime): if hashalg: _lib.rnp_op_sign_signature_set_hash(psig, hashalg.encode("ascii")) if creation_time: _lib.rnp_op_sign_signature_set_creation_time(psig, creation_time) if lifetime: _lib.rnp_op_sign_signature_set_expiration_time(psig, lifetime) py-rnp-main/rnp/op/verify.py000066400000000000000000000052521432224606000163230ustar00rootroot00000000000000from ctypes import c_void_p, c_size_t, c_uint32, c_bool, c_char_p, byref from ..lib import _lib, _inp from ..output import Output from ..signature import Signature class Verify: def __init__(self, obj, io): self._obj = obj self._io = io def __del__(self): _lib.rnp_op_verify_destroy(self._obj) def obj(self): return self._obj @staticmethod def start(rnp, inp, outp=None): inp = _inp(inp) pop = c_void_p() if outp is None: outp = Output.to_null() _lib.rnp_op_verify_create(byref(pop), rnp.obj(), inp.obj(), outp.obj()) if pop.value: op = Verify(pop, (inp, outp)) return op @staticmethod def start_detached(rnp, inpdata, inpsig): inpdata = _inp(inpdata) inpsig = _inp(inpsig) pop = c_void_p() _lib.rnp_op_verify_detached_create( byref(pop), rnp.obj(), inpdata.obj(), inpsig.obj() ) if pop.value: return Verify(pop, (inpdata, inpsig)) def finish(self): _lib.rnp_op_verify_execute(self._obj) def file_mtime(self): mtime = c_uint32() _lib.rnp_op_verify_get_file_info(self._obj, None, byref(mtime)) return mtime.value def filename(self): filename = c_char_p() try: _lib.rnp_op_verify_get_file_info(self._obj, byref(filename), None) return filename.decode("utf-8") finally: _lib.rnp_buffer_destroy(filename) def protection_mode(self): mode = c_char_p() try: _lib.rnp_op_verify_get_protection_info(self._obj, byref(mode), None, None) return mode.decode("utf-8") finally: _lib.rnp_buffer_destroy(mode) def protection_cipher(self): cipher = c_char_p() try: _lib.rnp_op_verify_get_protection_info(self._obj, byref(cipher), None, None) return cipher.decode("utf-8") finally: _lib.rnp_buffer_destroy(cipher) def protection_valid(self): valid = c_bool() _lib.rnp_op_verify_get_protection_info(self._obj, None, None, byref(valid)) return valid.value def signatures(self): count = c_size_t() _lib.rnp_op_verify_get_signature_count(self._obj, byref(count)) for i in range(count.value): pvsig = c_void_p() _lib.rnp_op_verify_get_signature_at(self._obj, i, byref(pvsig)) psig = c_void_p() _lib.rnp_op_verify_signature_get_handle(pvsig, byref(psig)) sig = Signature(psig.value) sig.status = lambda: _lib.rnp_op_verify_signature_get_status(pvsig) yield sig py-rnp-main/rnp/output.py000066400000000000000000000046021432224606000157370ustar00rootroot00000000000000from ctypes import ( c_bool, c_uint8, c_void_p, c_size_t, pointer, addressof, byref, py_object, cast, POINTER, CFUNCTYPE, ) from .lib import _lib class DefaultOutput: def __init__(self, outp): self.outp = Output.to_bytes() if outp is None else outp self.default = outp is None def __enter__(self): if self.default: self.outp.default_output = self.outp.bytes return self.outp def __exit__(self, type, value, traceback): pass class Output: def __init__(self, obj, io=None): self._obj = obj self._io = io def __del__(self): _lib.rnp_output_destroy(self._obj) def obj(self): return self._obj @staticmethod def to_path(path): obj = c_void_p() _lib.rnp_output_to_path(byref(obj), path.encode("utf-8")) return Output(obj) @staticmethod def to_bytes(max_alloc=0): obj = c_void_p() _lib.rnp_output_to_memory(byref(obj), max_alloc) return Output(obj) @staticmethod def to_null(): obj = c_void_p() _lib.rnp_output_to_null(byref(obj)) return Output(obj) @staticmethod def to_io(io): obj = c_void_p() io = py_object(io) _lib.rnp_output_to_callback(byref(obj), Output.WRITER, Output.CLOSER, byref(io)) return Output(obj, io) @staticmethod @CFUNCTYPE(c_bool, c_void_p, c_void_p, c_size_t) def WRITER(app_ctx, buf, buf_len): try: io = cast(app_ctx, POINTER(py_object)).contents.value buf = (c_uint8 * buf_len).from_address(buf) return io.write(buf) == buf_len except Exception as e: print(e) return False @staticmethod @CFUNCTYPE(None, c_void_p, c_bool) def CLOSER(app_ctx, discard): try: io = cast(app_ctx, POINTER(py_object)).contents.value io.close() except Exception as e: print(e) # private @staticmethod def default(outp): return DefaultOutput(outp) # private def default_output(self): return None def bytes(self): buf = pointer(c_uint8()) buflen = c_size_t() _lib.rnp_output_memory_get_buf(self.obj(), byref(buf), byref(buflen), False) return bytes((c_uint8 * buflen.value).from_address(addressof(buf.contents))) py-rnp-main/rnp/rnp.py000066400000000000000000000365001432224606000152000ustar00rootroot00000000000000#!/usr/bin/env python from collections.abc import Iterable from ctypes import ( pointer, c_bool, c_char_p, c_void_p, c_size_t, byref, c_char, addressof, py_object, cast, CFUNCTYPE, POINTER, ) import json from .lib import ( _lib, _flags, _obj, _encode, _inp, PASS_PROVIDER, KEY_PROVIDER, RNP_LOAD_SAVE_PUBLIC_KEYS, RNP_LOAD_SAVE_SECRET_KEYS, RNP_LOAD_SAVE_PERMISSIVE, RNP_LOAD_SAVE_SINGLE, ) from .output import Output from .key import Key from .op.sign import Sign from .op.verify import Verify from .op.encrypt import Encrypt class Rnp: def __init__(self, pub_format="GPG", sec_format="GPG"): self._obj = c_void_p() _lib.rnp_ffi_create( byref(self._obj), pub_format.encode("ascii"), sec_format.encode("ascii") ) def __del__(self): _lib.rnp_ffi_destroy(self._obj) def obj(self): return self._obj def load_keys(self, inp, fmt, public_keys=True, secret_keys=True): inp = _inp(inp) flags = Rnp._load_save_flags(public_keys, secret_keys) _lib.rnp_load_keys(self._obj, fmt.encode("ascii"), inp.obj(), flags) def unload_keys(self, public_keys=True, secret_keys=True): flags = Rnp._load_save_flags(public_keys, secret_keys) _lib.rnp_unload_keys(self._obj, flags) def save_keys(self, outp, fmt, public_keys=True, secret_keys=True): flags = Rnp._load_save_flags(public_keys, secret_keys) _lib.rnp_save_keys(self._obj, fmt.encode("ascii"), outp.obj(), flags) def import_keys( self, inp, public_keys=True, secret_keys=True, permissive=True, single=False ): inp = _inp(inp) try: jsn = None pjsn = pointer(c_char_p()) flags = Rnp._import_key_flags(public_keys, secret_keys, permissive, single) _lib.rnp_import_keys(self._obj, inp.obj(), flags, pjsn) jsn = pjsn.contents return json.loads(jsn.value.decode("utf-8")) finally: _lib.rnp_buffer_destroy(jsn) def import_signatures(self, inp): inp = _inp(inp) try: jsn = None pjsn = pointer(c_char_p()) _lib.rnp_import_signatures(self._obj, inp.obj(), 0, pjsn) jsn = pjsn.contents return json.loads(jsn.value.decode("utf-8")) finally: _lib.rnp_buffer_destroy(jsn) def public_key_count(self): count = c_size_t() _lib.rnp_get_public_key_count(self._obj, byref(count)) return count.value def secret_key_count(self): count = c_size_t() _lib.rnp_get_secret_key_count(self._obj, byref(count)) return count.value def _find_key(self, identifier_type, identifier): handle = c_void_p() _lib.rnp_locate_key(self._obj, identifier_type, identifier, byref(handle)) if handle.value: return Key(handle) def find_key_by_id(self, keyid): return self._find_key("keyid".encode("ascii"), keyid.encode("ascii")) def find_key_by_userid(self, userid): return self._find_key("userid".encode("ascii"), userid.encode("utf-8")) def find_key_by_fingerprint(self, fpr): return self._find_key("fingerprint".encode("ascii"), fpr.encode("ascii")) def userids(self): return self._identifiers("userid") def keyids(self): return self._identifiers("keyid") def fingerprints(self): return self._identifiers("fingerprint") def grips(self): return self._identifiers("grip") def _identifiers(self, typ): it = c_void_p() try: _lib.rnp_identifier_iterator_create( self._obj, byref(it), typ.encode("ascii") ) while True: identifier = c_char_p() _lib.rnp_identifier_iterator_next(it, byref(identifier)) if identifier.value: # pylint: disable=E1101 yield identifier.value.decode("utf-8") else: break finally: _lib.rnp_identifier_iterator_destroy(it) def generate_key(self, description): try: presults = c_char_p() jsn = json.dumps(description) _lib.rnp_generate_key_json(self._obj, jsn.encode("utf-8"), byref(presults)) # pylint: disable=E1101 results = json.loads(presults.value.decode("utf-8")) for entry in results: results[entry] = self._find_key( next(iter(results[entry].keys())).encode("ascii"), next(iter(results[entry].values())).encode("ascii"), ) return results finally: _lib.rnp_buffer_destroy(presults) def generate_rsa(self, userid, password, bits, subbits=0): pkey = c_void_p() _lib.rnp_generate_key_rsa( self._obj, bits, subbits, userid.encode("utf-8"), _encode(password), byref(pkey), ) if pkey.value: return Key(pkey) def generate_dsa_elgamal(self, userid, password, bits, subbits=0): pkey = c_void_p() _lib.rnp_generate_key_dsa_eg( self._obj, bits, subbits, userid.encode("utf-8"), _encode(password), byref(pkey), ) if pkey.value: return Key(pkey) def generate_ecdsa_ecdh(self, userid, password, curve): pkey = c_void_p() _lib.rnp_generate_key_ec( self._obj, curve.encode("ascii"), userid.encode("utf-8"), _encode(password), byref(pkey), ) if pkey.value: return Key(pkey) def generate_eddsa_25519(self, userid, password): pkey = c_void_p() _lib.rnp_generate_key_25519( self._obj, userid.encode("utf-8"), _encode(password), byref(pkey) ) if pkey.value: return Key(pkey) def generate_sm2(self, userid, password): pkey = c_void_p() _lib.rnp_generate_key_sm2( self._obj, userid.encode("utf-8"), _encode(password), byref(pkey) ) if pkey.value: return Key(pkey) def generate( self, userid, password, typ, bits, curve, subtyp=None, subbits=0, subcurve=None ): pkey = c_void_p() _lib.rnp_generate_key_ex( self._obj, typ.encode("ascii"), _encode(subtyp), bits, subbits, _encode(curve), _encode(subcurve), userid.encode("utf-8"), _encode(password), byref(pkey), ) if pkey.value: return Key(pkey) def export_autocrypt(self, userid, primary, subkey=None, outp=None): with Output.default(outp) as outp: _lib.rnp_key_export_autocrypt( primary.obj(), _obj(subkey), _encode(userid), outp.obj(), 0 ) return outp.default_output() def sign( self, signers, inp, armored=None, hashalg=None, compression=None, creation_time=None, lifetime=None, outp=None, ): with Output.default(outp) as outp: op = Sign.start(self, inp, outp) self._do_sign( op, signers, armored, hashalg, compression, creation_time, lifetime ) return outp.default_output() def sign_cleartext( self, signers, inp, hashalg=None, compression=None, creation_time=None, lifetime=None, outp=None, ): with Output.default(outp) as outp: op = Sign.start_cleartext(self, inp, outp) self._do_sign( op, signers, None, hashalg, compression, creation_time, lifetime ) return outp.default_output() def sign_detached( self, signers, inp, armored=None, hashalg=None, compression=None, creation_time=None, lifetime=None, outp=None, ): with Output.default(outp) as outp: op = Sign.start_detached(self, inp, outp) self._do_sign( op, signers, armored, hashalg, compression, creation_time, lifetime ) return outp.default_output() def verify(self, inp, outp=None): op = Verify.start(self, inp, outp) op.finish() return op def verify_detached(self, inpdata, inpsig): op = Verify.start_detached(self, inpdata, inpsig) op.finish() return op def encrypt( self, inp, recipients, armored=None, compression=None, cipher=None, aead=None, aead_bits=None, outp=None, ): with Output.default(outp) as outp: op = Encrypt.start(self, inp, outp) self._do_encrypt( op, recipients, armored=armored, compression=compression, cipher=cipher, aead=aead, aead_bits=aead_bits, ) return outp.default_output() def encrypt_and_sign( self, inp, recipients, signers, armored=None, compression=None, cipher=None, aead=None, aead_bits=None, hashalg=None, creation_time=None, lifetime=None, outp=None, ): with Output.default(outp) as outp: op = Encrypt.start(self, inp, outp) if hashalg is not None: op.hashalg = hashalg if creation_time is not None: op.creation_time = creation_time if lifetime is not None: op.lifetime = lifetime signers = [] if signers is None else signers signers = [signers] if isinstance(signers, Key) else signers for signer in signers: op.add_signature(signer) self._do_encrypt( op, recipients=recipients, armored=armored, compression=compression, cipher=cipher, aead=aead, aead_bits=aead_bits, ) return outp.default_output() def symmetric_encrypt( self, inp, passwords, armored=None, compression=None, cipher=None, aead=None, aead_bits=None, s2k_hashalg=None, s2k_iterations=None, s2k_cipher=None, outp=None, ): with Output.default(outp) as outp: op = Encrypt.start(self, inp, outp) passwords = [] if passwords is None else passwords passwords = ( [passwords] if isinstance(passwords, (str, bytes, bytearray)) else passwords ) for password in passwords: op.add_password(password, s2k_hashalg, s2k_iterations, s2k_cipher) self._do_encrypt( op, recipients=None, armored=armored, compression=compression, cipher=cipher, aead=aead, aead_bits=aead_bits, ) return outp.default_output() @staticmethod def _do_encrypt(op, recipients, armored, compression, cipher, aead, aead_bits): if armored is not None: op.armored = armored if compression is not None: op.compression = compression if cipher is not None: op.cipher = cipher if aead is not None: op.aead = aead if aead_bits is not None: op.aead_bits = aead_bits recipients = [] if recipients is None else recipients recipients = [recipients] if isinstance(recipients, Key) else recipients for recipient in recipients: op.add_recipient(recipient) op.finish() @staticmethod def _do_sign(op, signers, armored, hashalg, compression, creation_time, lifetime): signers = (signers,) if not isinstance(signers, Iterable) else signers for signer in signers: op.add_signer(signer) if armored is not None: op.armored = armored if hashalg is not None: op.hashalg = hashalg if compression is not None: op.compression = compression if creation_time is not None: op.creation_time = creation_time if lifetime is not None: op.lifetime = lifetime op.finish() def decrypt(self, inp, outp=None): inp = _inp(inp) with Output.default(outp) as outp: _lib.rnp_decrypt(self._obj, inp.obj(), outp.obj()) return outp.default_output() def set_password_provider(self, provider): if provider is None: _lib.rnp_ffi_set_pass_provider(self._obj, cast(None, PASS_PROVIDER), None) else: self.pass_provider = py_object(provider) _lib.rnp_ffi_set_pass_provider( self._obj, Rnp.PASS_PROVIDER_PROXY, byref(self.pass_provider) ) @staticmethod @CFUNCTYPE( c_bool, c_void_p, c_void_p, c_void_p, c_char_p, POINTER(c_char), c_size_t ) def PASS_PROVIDER_PROXY(_rnp, app_ctx, pkey, reason, buf, buf_len): password = cast(app_ctx, POINTER(py_object)).contents.value if callable(password): key = Key(c_void_p(pkey), False) password = password(key, reason) if password is not None: if isinstance(password, str): password = password.encode("utf-8") if len(password) >= buf_len: return False buf = (c_char * buf_len).from_address(addressof(buf.contents)) buf[: len(password)] = password[: len(password)] return True return False def set_key_provider(self, provider): if provider is None: _lib.rnp_ffi_set_key_provider(self._obj, cast(None, KEY_PROVIDER), None) else: self.key_provider = py_object([provider, self]) _lib.rnp_ffi_set_key_provider( self._obj, Rnp.KEY_PROVIDER_PROXY, byref(self.key_provider) ) @staticmethod @CFUNCTYPE(None, c_void_p, c_void_p, c_char_p, c_char_p, c_bool) def KEY_PROVIDER_PROXY(_rnp, app_ctx, identifier_type, identifier, is_secret): ctx = cast(app_ctx, POINTER(py_object)).contents.value identifier_type = identifier_type.decode("ascii") identifier = identifier.decode("utf-8") return ctx[0](ctx[1], identifier_type, identifier, is_secret) @staticmethod def _load_save_flags(public_keys, secret_keys): return _flags( [ (public_keys, RNP_LOAD_SAVE_PUBLIC_KEYS), (secret_keys, RNP_LOAD_SAVE_SECRET_KEYS), ] ) @staticmethod def _import_key_flags(public_keys, secret_keys, permissive, single): return _flags( [ (public_keys, RNP_LOAD_SAVE_PUBLIC_KEYS), (secret_keys, RNP_LOAD_SAVE_SECRET_KEYS), (permissive, RNP_LOAD_SAVE_PERMISSIVE), (single, RNP_LOAD_SAVE_SINGLE), ] ) py-rnp-main/rnp/signature.py000066400000000000000000000042671432224606000164070ustar00rootroot00000000000000import json from ctypes import c_char_p, c_uint32, c_void_p, byref from .lib import ( _lib, _flags, RNP_JSON_DUMP_MPI, RNP_JSON_DUMP_RAW, RNP_JSON_DUMP_GRIP, RnpException, ) from .key import Key class Signature: def __init__(self, obj): self._obj = obj def __del__(self): _lib.rnp_signature_handle_destroy(self._obj) def obj(self): return self._obj def type(self): return self._string_property(_lib.rnp_signature_get_type) def alg(self): return self._string_property(_lib.rnp_signature_get_alg) def hashalg(self): return self._string_property(_lib.rnp_signature_get_hash_alg) def keyid(self): return self._string_property(_lib.rnp_signature_get_keyid) def creation_time(self): time = c_uint32() _lib.rnp_signature_get_creation(self._obj, byref(time)) return time.value def lifetime(self): if _lib.features.get("have-rnp-signature-get-expiration"): time = c_uint32() _lib.rnp_signature_get_expiration(self._obj, byref(time)) return time.value raise RnpException("Not supported in this version of librnp") def signer(self): signer = c_void_p() _lib.rnp_signature_get_signer(self._obj, byref(signer)) if signer.value: return Key(signer.value) def status(self): return _lib.rnp_signature_is_valid(self._obj, 0) def json(self, mpis=False, raw=False, grip=False): flags = _flags( [ (mpis, RNP_JSON_DUMP_MPI), (raw, RNP_JSON_DUMP_RAW), (grip, RNP_JSON_DUMP_GRIP), ] ) jsn = c_char_p() try: _lib.rnp_signature_packet_to_json(self._obj, flags, byref(jsn)) # pylint: disable=E1101 return json.loads(jsn.value.decode("utf-8")) finally: _lib.rnp_buffer_destroy(jsn) def _string_property(self, fn): prop = c_char_p() try: fn(self._obj, byref(prop)) # pylint: disable=E1101 return prop.value.decode("ascii") finally: _lib.rnp_buffer_destroy(prop) py-rnp-main/rnp/uid.py000066400000000000000000000035601432224606000151620ustar00rootroot00000000000000from ctypes import ( c_size_t, c_uint8, c_uint32, c_bool, c_void_p, POINTER, cast, byref, addressof, ) from .lib import _lib class UID: RNP_USER_ID = 1 RNP_USER_ATTR = 2 def __init__(self, obj): self._obj = obj def __del__(self): _lib.rnp_uid_handle_destroy(self._obj) def obj(self): return self._obj def type(self): uidtype = c_uint32() _lib.rnp_uid_get_type(self._obj, byref(uidtype)) return uidtype.value def data(self): buf = c_void_p() buf_size = c_size_t() try: _lib.rnp_uid_get_data(self._obj, byref(buf), byref(buf_size)) buf = cast(buf, POINTER(c_uint8)) return bytes( (c_uint8 * buf_size.value).from_address(addressof(buf.contents)) ) finally: _lib.rnp_buffer_destroy(buf) def is_primary(self): primary = c_bool() _lib.rnp_uid_is_primary(self._obj, byref(primary)) return primary.value def is_valid(self): valid = c_bool() _lib.rnp_uid_is_valid(self._obj, byref(valid)) return valid.value def is_revoked(self): revoked = c_bool() _lib.rnp_uid_is_revoked(self._obj, byref(revoked)) return revoked.value def revocation_signature(self): from .signature import Signature psig = c_void_p() _lib.rnp_uid_get_revocation_signature(self._obj, byref(psig)) if psig.value: return Signature(psig.value) def signatures(self): from .signature import Signature count = c_size_t() _lib.rnp_uid_get_signature_count(self._obj, byref(count)) for i in range(count.value): psig = c_void_p() _lib.rnp_uid_get_signature_at(self._obj, i, byref(psig)) yield Signature(psig.value) py-rnp-main/tests/000077500000000000000000000000001432224606000143665ustar00rootroot00000000000000py-rnp-main/tests/data/000077500000000000000000000000001432224606000152775ustar00rootroot00000000000000py-rnp-main/tests/data/keyrings/000077500000000000000000000000001432224606000171325ustar00rootroot00000000000000py-rnp-main/tests/data/keyrings/gpg/000077500000000000000000000000001432224606000177075ustar00rootroot00000000000000py-rnp-main/tests/data/keyrings/gpg/info.txt000066400000000000000000000000231432224606000213760ustar00rootroot00000000000000password: password py-rnp-main/tests/data/keyrings/gpg/pubring.gpg000066400000000000000000000067171432224606000220670ustar00rootroot00000000000000˜YpàÜÇÂCØÖS¿åâR£´ÿ·o»ý¶d× žrŠÔ¯/Íeë=BÙ½þ4wÅð#0PÈ‹åüÃ[2Gûx‹Že‹·ø°5½'pö¤‘‹8ÔÚþÙ¡¨¼G"8-›Xá"—dôy´7‹Ë_uì·NÆõ·X kku)&¡`µU‰´ key0-uid0ˆ¹#YpàÜ  € {Æp›Â:J§ºKª›_^¹{„÷ ÞóýnW¡LºÛ.«Ûíþm2'- 0¢Þ¬Yú‹‡úZ—¿7Chk64S†-Zš‰Ó5¼÷œU¸ˆÉ&b˜Ð5iÈa|°ZVœ`›‰t#4;< ýRË=t³Ëø,'¡ØJ»OuÁÂ0‚{¾¬ôŸü°´ key0-uid1ˆ¹#Ypàì  € {Æp›Â:J ÿizKI~LmêŠÑÜ ¿é·}ñ¢`?²ˆ ‰ÁÈ™ÕFã<~à û$.apëõ™üãnù}òÕ })û»)HÊïúÉÊ|l™CQ,ü™œK¶Sª5¤ƒ².SD „' Ô‹*Æû^Ï\7oŽŽ?UÕâ,âí{Y°´ key0-uid2ˆ¹#Ypàö  € {Æp›Â:J^kÁØB:)· ¯ãOé7ɲá÷1fL+ë9„5Ñüñ`Ä5›4? ïwÒ.ëœaREÝ´oÒµ¥áÓt@à ã:«n½‰îtÌÛˆbÚUŠhrI>ö÷-S5¤‡`ÈC%ÔkL'Ù¿3Zˆ/’AçjHxú±o Œçay°¸Ypàܽé>¢= œ³üÃî€V;µ[ýV’Ö,P9CO®Dð4KG%U¿“œ±²¢tnœ¹@ý;äNÆk[»¹$øt®?H@¬-Cb9‹‹N(çª"w ö^žM5³§õæoRÞA$ß´îí@l>x®µš¨Vß@.è®ìn“ 7ÖÜA ˆŸ YpàÜ {Æp›Â:Jdž™D nêzÓûñ#×ûWš ûš²¢bŸ²ÚP ùbD Û]×D°Ëº½ÁA4¸‡Î U.Syam,[!Àèô´ÁOL.ïX/Ù«÷š˜D.¼ø£/Ö•Y‹X(-nŒZÝk/Ÿá¬›}Jßú!cl+ü? ás´O†3æ*ˆ°¹¢Ypàû¬»Î •â-Ôä½ãòQ¢¬ºWŽ„²ÉûLüà[)ê=W‰îQÓµ’’,n+^o¢?šÄQ-'2ïRÍzÁ<>ºŸÂ-9n¤åÅO$_)¥®S5¦ÎÚݳâz|ÏGÍ3_]dðCù<€|Ÿ0¬ÎUþïôT{õ+z?ÙK Ù§o4S!xLaÑþ…&å½Á©ÿLvÅS×;òslOÓû•ý MÐP¦’´G_øÞ¢m.ê@#çÅÀݲ’}oßÔÔÓ﹇lëè áÈ•8@#‚¹–„þÕÅåÞ³¨,‚[ Òµ¸üRUÒÿÃfñ‡rØðXmcÛB‹“Šä¥¿Mµä‰N F¿Ñé¢XŠøl ý‚Ÿ¾Œõ«4yxnÚ®*z—õäíúbæU˜(´=³ö#U¶U µö7zÒÏu®“®dïû¦Y¼¦j”Õt>u·ß£ÇÕÿ.ñS'~tíìEaÂęʖ‚ßd!x³þ¹ [7oœJ-iVd6DeLì  ¾y‘²8V ˆíYpàû ¢(€R {Æp›Â:JG Ypàû ~ŠS“É—¨ï=ŸjB…3{d0"iGÖ:7Gš2ß[Žu«"R9DP6[[rI-a…ûºjþ+ݦäRr|þ7‘µ{p• ™ÛxQu–ò vÊÃäÇÎïcHTŬ„ß íÏÁ²g/ª ,Ç6a ωÈ{AÉoĮϽ$-¯ô²#&d¨Â4{ÆëBÎŽõ«µ .W¨­j7è³) Œ ³W “›v»½P« ¦ˆ#°¸Ypá(é1ÂÝôѱ1Ý9C“Y1Jæ=¢^è7d®•óC¸æ¤wë€ÄkÂaȉx"§ûE0øsS"€é[#ªWîNú)ÏÐÄùù\·¨GÞgÍ^™Qä,Ä›0n{/HŠÊ.½D'Àg¦Nëº}uý& rÍ•aá•0ß’Äõ ÛìÚËá»ÍÆ´³îÄ‘™@~ûY"D‹iÕXµ5»±÷|¯Þ<ó)´\Ó&ÂÖù„d‘}ŠuF¬ ËÇO~ûëQœ 6f§ðH‰h02#ùô‹,øÎ¯ÁN°¹ YpáZÿb’£¶ìP H11µcjËnÇÕ;[áb=lïÉΰŸO÷ ‹)ÒûSfÅBXW/e‰ ö­Ag_ ±ÕN…®ÈïÉÐPËþ÷˜ÕE\AFF(’+„L€5Ò+FÓœ´ÐÍ/ÄæëÁþFÄZű~ÃÑuTêå2ªt޹›’ñçý$É£ÅÌ. ¡'èbÜm†Ž$¾%”á&#‚3êë ßvç}|uEšr"4§Rº¤q8 eÓ/æ•ä y%µ9CFçɺý‰“ç˜yÈÃÕqÐÅ./â£9Ür†Â…Z†îƒ©:°Cj{’FÑd%Þª}ëJ†S¤ˆOYpáZ  {Ç` /Êßÿ¥»à¿³.…]B2Ÿ\š.#¿0©"km✠8ÂXXÑ™ü¥Vk…ÿWq0L°¹ Ypâ5Îwa£èŒ„ªbƾ•ê Ⳝ@áO]BZÙÁ» ,[¬£b9ˆ½b?ãîÐ×¼šÈl}z@W»[£ã}'aÛ#¶ì,˜‚ÜbHëzHØüV€¨¤©¢+Õùßt°}(#ßž™ìîDc\/¤™Dò«EMªì߀»ÿMP4%G¯MÜ~wÚSYý ÿ¤J>ø/ÌÔ}p´fñ¥ôD?ÛÈÒøÞÛ#쑼Z•¸íßÕ ôÐõÒ¸D­(•zõîŒÚx†…¸8Å"ฤK”Vz°PŸÈÇ\zF¡÷øõçÑȾøšØïxhÖ!´ÍX{ÇTÙ;Þɽ=͈I Ypâ5 /Êßÿ¥»æŸs»OˆZ›Yxë>ó;˜«ÑtE2ž$&Lͤí !eƒQ ð[ðÖ²A°py-rnp-main/tests/data/keyrings/gpg/secring.gpg000066400000000000000000000114551432224606000220460ustar00rootroot00000000000000•þYpàÜÇÂCØÖS¿åâR£´ÿ·o»ý¶d× žrŠÔ¯/Íeë=BÙ½þ4wÅð#0PÈ‹åüÃ[2Gûx‹Že‹·ø°5½'pö¤‘‹8ÔÚþÙ¡¨¼G"8-›Xá"—dôy´7‹Ë_uì·NÆõ·X kku)&¡`µU‰þkÀ…àƒ asÓêÍÖ})Z[Å5ê€îæ-H’“‘ÛQ.ë#h·Pסi©‹$aôÐ]ÈíEyõ9ÙïS¿PïHÏÁe,0¹ð4Éêëï aTêÇtú‘fÓ Ä>8—{Ý(»[OX'Q£ÂL*æ3qøò8*¸Ò¾W=sàY™-·ÌËI]ÏîäMò¹Ìédh*Ñä`&6:#cr CÑ»^Í2:°® ½¾Ñ%~J Þ›Ô“›Tãí£ñ‚¶â²¥/l‘*mÊ"bÀ” ‘› Ø[°“c„²é½áÒÓˆ:- ±`ª±öÀäh‰ÊøZÃǦï6´HREš:öÒ¥¨!‚HýaÜt/“ÔP%ÒvRz ‹šýLƒÿçLðeù€I½bšod>%ˆ3÷+²ëÚ*V]5ñáì½Bt°Ÿµ ^ŒÜx7P¥çè°ÀºFIµ˜8è Qj®tíøA'*´ key0-uid0ˆ¹#YpàÜ  € {Æp›Â:J§ºKª›_^¹{„÷ ÞóýnW¡LºÛ.«Ûíþm2'- 0¢Þ¬Yú‹‡úZ—¿7Chk64S†-Zš‰Ó5¼÷œU¸ˆÉ&b˜Ð5iÈa|°ZVœ`›‰t#4;< ýRË=t³Ëø,'¡ØJ»OuÁÂ0‚{¾¬ôŸü°´ key0-uid1ˆ¹#Ypàì  € {Æp›Â:J ÿizKI~LmêŠÑÜ ¿é·}ñ¢`?²ˆ ‰ÁÈ™ÕFã<~à û$.apëõ™üãnù}òÕ })û»)HÊïúÉÊ|l™CQ,ü™œK¶Sª5¤ƒ².SD „' Ô‹*Æû^Ï\7oŽŽ?UÕâ,âí{Y°´ key0-uid2ˆ¹#Ypàö  € {Æp›Â:J^kÁØB:)· ¯ãOé7ɲá÷1fL+ë9„5Ñüñ`Ä5›4? ïwÒ.ëœaREÝ´oÒµ¥áÓt@à ã:«n½‰îtÌÛˆbÚUŠhrI>ö÷-S5¤‡`ÈC%ÔkL'Ù¿3Zˆ/’AçjHxú±o Œçay°þYpàܽé>¢= œ³üÃî€V;µ[ýV’Ö,P9CO®Dð4KG%U¿“œ±²¢tnœ¹@ý;äNÆk[»¹$øt®?H@¬-Cb9‹‹N(çª"w ö^žM5³§õæoRÞA$ß´îí@l>x®µš¨Vß@.è®ìn“ 7ÖÜA þkÀ…àƒ asÓ-U ýëKŸÀ5u~»iD¶°äØËQ5ã¥æ)sÁ%Ôò;²p]b†sm[“M"mSÛÀ D­ôyßÿNø^ÒýÜEÖøÊ±n¬ƒL!\yÎÿaT´Ä›O•À™2íÌd¸ëÝÉÙiÊÏU ˆâ³Aq$¤bìk8üù(óf÷Œ;Ø;o[Vˆ›÷L@ýÖœx$ ­Æ¦³è6õÁ¯GâÊY¸' Ë ûþ“æ‡^ p„¸ –f¥•á‰p£Ì W·T!:´¹ó‡Õ¼öƒÀWúÎU’Ë8‚€ å’2ž,Ç­/î‘g«G3Ü3~©3ÁãaÚÛQ±Ø´€CZhºƒ]5©UìMÃ¥pÀP }U~ïºùœà`íYÈ¢úÔI䔞¼ÒÕHšpNÁ&¯Å«Ô¬š­H¨ß­é²ÑÅ¡òíÈ6OµàqÀ"ˆƒ;Ê6Ø!Žù+`ÞH´œO¡ÐR± 爟 YpàÜ {Æp›Â:Jdž™D nêzÓûñ#×ûWš ûš²¢bŸ²ÚP ùbD Û]×D°Ëº½ÁA4¸‡Î U.Syam,[!Àèô´ÁOL.ïX/Ù«÷š˜D.¼ø£/Ö•Y‹X(-nŒZÝk/Ÿá¬›}Jßú!cl+ü? ás´O†3æ*ˆ°áYpàû¬»Î •â-Ôä½ãòQ¢¬ºWŽ„²ÉûLüà[)ê=W‰îQÓµ’’,n+^o¢?šÄQ-'2ïRÍzÁ<>ºŸÂ-9n¤åÅO$_)¥®S5¦ÎÚݳâz|ÏGÍ3_]dðCù<€|Ÿ0¬ÎUþïôT{õ+z?ÙK Ù§o4S!xLaÑþ…&å½Á©ÿLvÅS×;òslOÓû•ý MÐP¦’´G_øÞ¢m.ê@#çÅÀݲ’}oßÔÔÓ﹇lëè áÈ•8@#‚¹–„þÕÅåÞ³¨,‚[ Òµ¸üRUÒÿÃfñ‡rØðXmcÛB‹“Šä¥¿Mµä‰N F¿Ñé¢XŠøl ý‚Ÿ¾Œõ«4yxnÚ®*z—õäíúbæU˜(´=³ö#U¶U µö7zÒÏu®“®dïû¦Y¼¦j”Õt>u·ß£ÇÕÿ.ñS'~tíìEaÂęʖ‚ßd!x³þ¹ [7oœJ-iVd6DeLì  ¾y‘²8V þϨ{=¥Ñ­ÓV7±ŸÄ\˜WJŒÖñ{ïµÔßgÊ]зì.¸ÿ?àN–‡µ Vl½ hë5ÌJ¢©ˆíYpàû ¢(€R {Æp›Â:JG Ypàû ~ŠS“É—¨ï=›¤ÎêÙ—å$­žL€RBÈæ‰8  ¾…'ŠüS¢Ï·2™ÈÊÆ` nEºjþ+ݦäRr|þ7‘µ{p• ™ÛxQu–ò vÊÃäÇÎïcHTŬ„ß íÏÁ²g/ª ,Ç6a ωÈ{AÉoĮϽ$-¯ô²#&d¨Â4{ÆëBÎŽõ«µ .W¨­j7è³) Œ ³W “›v»½P« ¦ˆ#°þYpá(é1ÂÝôѱ1Ý9C“Y1Jæ=¢^è7d®•óC¸æ¤wë€ÄkÂaȉx"§ûE0øsS"€é[#ªWîNú)ÏÐÄùù\·¨GÞgÍ^™Qä,Ä›0n{/HŠÊ.½D'Àg¦Nëº}uý& rÍ•aá•0ß’Äõ ÛìÚËá»ÍÆ´³îÄ‘™@~ûY"D‹iÕXµ5»±÷|¯Þ<ó)´\Ó&ÂÖù„d‘}ŠuF¬ ËÇO~ûëQœ 6f§ðH‰h02#ùô‹,øÎ¯ÁN°´ key1-uid2ˆi)Ypâ) {Ç`  € /Êßÿ¥»Ñ-ŸH¼«ÁBé A ¿EGH… ˜Cž*JáB b$µÕÞGàDh%°WYpáZÿb’£¶ìP H11µcjËnÇÕ;[áb=lïÉΰŸO÷ ‹)ÒûSfÅBXW/e‰ ö­Ag_ ±ÕN…®ÈïÉÐPËþ÷˜ÕE\AFF(’+„L€5Ò+FÓœ´ÐÍ/ÄæëÁþFÄZű~ÃÑuTêå2ªt޹›’ñçý$É£ÅÌ. ¡'èbÜm†Ž$¾%”á&#‚3êë ßvç}|uEšr"4§Rº¤q8 eÓ/æ•ä y%µ9CFçɺý‰“ç˜yÈÃÕqÐÅ./â£9Ür†Â…Z†îƒ©:°Cj{’FÑd%Þª}ëJ†S¤þÿÍî}#8БӢ±IìW˜Ð mhÒ õ"…Pƒ.cób+”ée˜Ê1ª¿£ôáÒî21{´¡g/eã¦tZæêDå¦ÚˆOYpáZ  {Ç` /Êßÿ¥»àŸAl¤Aû,,Ð:Øl²»dó`Ø©ŸGibØp•Žž¸³?è \Nªñ°XYpâ5Îwa£èŒ„ªbƾ•ê Ⳝ@áO]BZÙÁ» ,[¬£b9ˆ½b?ãîÐ×¼šÈl}z@W»[£ã}'aÛ#¶ì,˜‚ÜbHëzHØüV€¨¤©¢+Õùßt°}(#ßž™ìîDc\/¤™Dò«EMªì߀»ÿMP4%G¯MÜ~wÚSYý ÿ¤J>ø/ÌÔ}p´fñ¥ôD?ÛÈÒøÞÛ#쑼Z•¸íßÕ ôÐõÒ¸D­(•zõîŒÚx†…¸8Å"ฤK”Vz°PŸÈÇ\zF¡÷øõçÑȾøšØïxhÖ!´ÍX{ÇTÙ;Þɽ=ÍþKèå×9HÓûbÝ<ÆÍ¼w/Û +W Ö˜a½b+é7ÃaÞÙ ÜíS–¦á:á´qIã%UiuXðߦD%bÜ•kˆI Ypâ5 /Êßÿ¥»æŸnS.Ü{]jd¹eéý}%á“ÔóTŸbCk_]ѳM¯ØãWFθ¢r5°py-rnp-main/tests/data/keyrings/gpg21/000077500000000000000000000000001432224606000200525ustar00rootroot00000000000000py-rnp-main/tests/data/keyrings/gpg21/info.txt000066400000000000000000000000231432224606000215410ustar00rootroot00000000000000password: password py-rnp-main/tests/data/keyrings/gpg21/private-keys-v1.d/000077500000000000000000000000001432224606000232435ustar00rootroot00000000000000py-rnp-main/tests/data/keyrings/gpg21/private-keys-v1.d/63E59092E4B1AE9F8E675B2F98AA2B8BD9F4EA59.key000066400000000000000000000022061432224606000305510ustar00rootroot00000000000000(21:protected-private-key(3:rsa(1:n257:³ì‰OÚ¦~qåhÌ“W´uêÏÊûöìÆŸ }Œ÷G]^ÓÙ¥±â΂Ýrrh¨]2èÉÅÖ!ÑŽ0á!¢›µø{œì!ÂE/‚¯€†aoÒ–z¹Sƒ /j‘=›P†mß}̰a›Z¤¶Ã}ûe°º+h3!½ö£Ô­=옪ÞÛo$¡LÔÅ6ÑxL¬¨‡¡•wnG½¡𠇳Èü§ÙÍža×:g íYÇð¸í´NŒ€æIø+qk[0÷¾á²­C)OF¼Fø4PågÕwíL¹ïjTuõ9bN¢ìòWOã&Cz:¬8ŸñJå?ÄÅõ‰Ÿ)(1:e3:)(9:protected25:openpgp-s2k3-sha1-aes-cbc((4:sha18:w*œåA ì8:16777216)16:©îÕ:°ÓyçLÄG)720:¿ú©Ìy¬!Í2ÖרíÙJCõl¤=|ü+ôÙ`–i¶.ç}úÓ†t.托d—pf!d’Dÿ&ÕB¦=©‚7ÜüR,Ëno€áWÐ&u{šn®( ³øÍÞŒ×)à$(¿À!IAøÝ\Ça¸ÿœ‹BçJ¬Ú®Cí³.ˆ·™˜Ò‡ŒXúµPÏõa}~¾ÖtuçþË÷••=y•†¥¹ÝýäXfRm¬ÿŒ [6\äQœDSvxf^Úeòë}cOñê¢Å%³å⦂h¨óTLTý¾Ñ*C!d·¡Ïæ©èø¹=Rî»Jíùª Äp¢sÆ"Þ•#@~G™ü}GüºTÒ5UÃ\g2^©úµ'›8Þ@ìY¨/ý–ÓKȲ*xË_îFy|§LSàëì¾<œpüDQÙwÐÔåfŽÙÚœZçý‡ÅH`=¸â_Äíò1Ôª.GÏ ,÷“¢ù|^…€‰c –ðGœMÁG †ßXÒq‹6î,Þ“vç‹Ø—',ÕÏLû ŒŽ&‘ÿÿö÷®»vªø‹månÝÄÂàV™W)üŒƒŽ´–çV#Z•íŠ/kŠŽV–ØÈÍI•_gÀ † ùŸÂÊåyTü`V>y¬ø‡µO#ôJÃîsM§Þ¡ôkÆ)ÕÔ@a²qm|rˆ'Œé/˜£v[“vì@ÂL—øUu°&oü©¿@°Ó§[¨÷g ÏQјž×¨¼Óòñtµ¢u·Óh@ËS½VddÛQ'”l+Q²; …ËÐx$×p8ô//½öo]Äaù\+|†’³î‰T'÷òÞÓ.V®ôW Z[€QáÒáµÝ;Ù*gWª¶˜  ›´™3˜UVý+Xb‘ÛèÄâu,ºmh«ZF8«|nè<” ôSꆠÙd“lôÃǶ÷)(12:protected-at15:20170930T132911)))py-rnp-main/tests/data/keyrings/gpg21/private-keys-v1.d/7EAB41A2F46257C36F2892696F5A2F0432499AD3.key000066400000000000000000000022061432224606000304100ustar00rootroot00000000000000(21:protected-private-key(3:rsa(1:n257:¹ã8rÊ͹ÌD¨Ér-{¯!eiÕ…UD(³-ÔZȾt¶(î¤Õ_§ˆÊW\¨ 2ãg÷¤´ZpÊÃ]a@æ¬ô¼Ò,Y+î€ëA£œ¯“EØäæŸÌºÍzw (^ó¾B›€†IÆ©B¶1Èoµc›F²?²ùa¥`ꡚŒ62Èë0ã»ìaË­û±~—¯gꊹ£²ùöìóÕS”«éP¦nü6tI$¶’÷”`þfZYMNèã|Pø]¶«€@ÁŒoTyîfç-ßÇ宸Pò(¢þhйº%ž‹¥è ^nÎcJDÍžO'ž»)(1:e3:)(9:protected25:openpgp-s2k3-sha1-aes-cbc((4:sha18: =[¹0mx8:16777216)16:Œ†j¥œ¼aˆ6wÿ,)720:ó^ÊóX·a)÷×Rò/´!ãMåW–Úȳ6 û*i´ð幋½‰,’-›ê"É´-¨éþ>%‚ôÿ“þ=~¤×Ô›“®B¤ G!(€í\èÞÍ¢·Á³S•‡uˆ·bw¹1ÒXñ3ivº¿ü6r‹’±x{+Ÿ8Õ˜Tu9½Ô#Úe+)K󬀘P0ȱÅÙ4%Ãå¶JJ=v¬¾Û,ˆ×Q ƒÁ‘|uw0™ÁÔ‡„Àx§ïF¨Óu5À%Œ<6Òõ.6àÏ?<€Åû;>åÔÿÀ Èÿt&í ©ñ¹Æ#|KÔ,1ÿ¸æ þ½9/Ëøv‘sàt3š Ù¨/f³_Qx»é+‹»ÀšÁQ”IÌdW¯ôg;8š¼Íªèû‡¯ô\’–N~<8Žo¬¢?Æ—–XPç)Ã5v;ƒÿ¾XúŽo0 OošýhÔù•{`LãµÃ^Àz²mÆ­'[6Ç›ÊÿBYàâÙàÉp“Og­6F 1…Ö×Äg! ¡^™[º×Ъí‡I¶^ Þ¼4¿S|þ쪫|Ò3zÚ%QvHb¯ ™6RøÍkã"öFhw$ðŽq½*Äá›I²1”¼¶Íy²X¿è.x6Ö5™ÍypªªiOÚM®=?í<‡$úÉ@¹Y-"Rûƒo³Ð›l¶`ðÇaȘjŸM£>ÃÿÍÊÕX%“ö) ö‹ðmÔÁûdìõa]H÷;!yë<´|Oëcõî¶Ì81GE~“7ˆÁ¿¼™YôÓÆ…3¸ñÚ9×~Ã˾›?!ÐÁ+ÇÉ‘?èŃG.Î:³„E¥ñT%ÊäB:áTÿz®ìe`1¬xŠŽÃ„í|c `Öó°ýØèŽÒèÉZ4ŽÚDÑZ×·Èéh>SùP ÈØíî̯ûæ®{ÓhÌÁ¦–j)(12:protected-at15:20170930T132910)))py-rnp-main/tests/data/keyrings/gpg21/pubring.kbx000066400000000000000000000026331432224606000222320ustar00rootroot00000000000000 KBXfYÏ›þYÏ›þ{~éO.b·NjLÓ3¼KáG»"ß` y>6~ègÃ.5*¤›®Án‹È< žYÏœ'™ YÏœ¹ã8rÊ͹ÌD¨Ér-{¯!eiÕ…UD(³-ÔZȾt¶(î¤Õ_§ˆÊW\¨ 2ãg÷¤´ZpÊÃ]a@æ¬ô¼Ò,Y+î€ëA£œ¯“EØäæŸÌºÍzw (^ó¾B›€†IÆ©B¶1Èoµc›F²?²ùa¥`ꡚŒ62Èë0ã»ìaË­û±~—¯gꊹ£²ùöìóÕS”«éP¦nü6tI$¶’÷”`þfZYMNèã|Pø]¶«€@ÁŒoTyîfç-ßÇ宸Pò(¢þhйº%ž‹¥è ^nÎcJDÍžO'ž»° gpg´test1° gpg‰T>!O.b·NjLÓ3¼KáG»"ß`YÏœ Âg  € KáG»"ß`Taþ'VHuܪœ¿~°‹âb•‰ž”T²f]˜<ž¦…`E ÝM­ ޵db)W•M4U-«ŸãêYËïh§ ³@Å@E+±ì.»{¯ùFÔÛð„ŸùüêÀAÍÖ³.°ëEà¸Ï¨‡©ÛȸeÅ^Lsg¿×‘>jä±—ëø»Q—ñÿ ãë½z¿?gŠžˆk¾—0JT5ÃI¨¨’?1-|t•ÙÇÊZ[tßvùPU Qá {£±ó¶b‹Ø.|Ð9èo[¢Ø'Yïi¥ŸŒgKÝî<ßÊ퇌"â¥vE.}¥—ÄÍÆœ9L°AñÀò¿¿þrDÂa— ûÓ3á6ê°gpg¹ YÏœ³ì‰OÚ¦~qåhÌ“W´uêÏÊûöìÆŸ }Œ÷G]^ÓÙ¥±â΂Ýrrh¨]2èÉÅÖ!ÑŽ0á!¢›µø{œì!ÂE/‚¯€†aoÒ–z¹Sƒ /j‘=›P†mß}̰a›Z¤¶Ã}ûe°º+h3!½ö£Ô­=옪ÞÛo$¡LÔÅ6ÑxL¬¨‡¡•wnG½¡𠇳Èü§ÙÍža×:g íYÇð¸í´NŒ€æIø+qk[0÷¾á²­C)OF¼Fø4PågÕwíL¹ïjTuõ9bN¢ìòWOã&Cz:¬8ŸñJå?ÄÅõ‰Ÿ‰<&!O.b·NjLÓ3¼KáG»"ß`YÏœ  Âg KáG»"ß`õü¶îNƒf¤ þ }æ5¥FWðmj•‹CìŸXXÍ¥tê?¦•ÝäúþA<›‰ÅÄ®WÌY·›Ø}šKæ¼ ¨ ÇŽiLCÎFØK±ÁBy „SylOQŠhvK¼¤ya­#¡¤"ú?tI}ˆ|"Öý»]‘…:œˆÞbtÁZ”™Â5a9å^ÓÛ‘æž´£·2ò:Þf³ÀLn¡Ê™\ºóKD,54qq¸í5Æá^Ê¿ñÍ@[Þº:I)©›a™\u¡Ùbó¹lÒKëäÌql€œJ{cd·oŠÿ¬8f$R¤4u3tˆZ‰Â6lM*Çɰgpg¨NË\ÙA}4") assert len(list(key.signatures())) == 0 imported = rpgp.import_signatures( rnp.Input.from_path("tests/data/keys/alice-rev.pgp") ) assert len(imported["sigs"]) == 1 assert imported["sigs"][0]["public"] == "new" assert ( imported["sigs"][0]["signer fingerprint"] == "73edcc9119afc8e2dbbdcde50451409669ffde3c" ) assert len(list(key.signatures())) == 1 sig = next(key.signatures()) assert sig.type() == "key revocation" assert sig.alg() == key.alg() assert sig.keyid() == "0451409669FFDE3C" assert sig.hashalg() == "SHA256" assert sig.creation_time() == 1578663151 if rnp.check('have-rnp-signature-get-expiration'): assert sig.lifetime() == 0 assert sig.signer().keyid() == key.keyid() assert sig.status() == 0 py-rnp-main/tests/test_input_io.py000066400000000000000000000005361432224606000176310ustar00rootroot00000000000000import io import rnp def test_input_io(): rpgp = rnp.Rnp() rpgp.set_password_provider(lambda key, reason: "password") sio = io.StringIO("some secret text") encrypted = rpgp.symmetric_encrypt(rnp.Input.from_io(sio), "password") bio = io.BytesIO(encrypted) assert rpgp.decrypt(rnp.Input.from_io(bio)) == b"some secret text" py-rnp-main/tests/test_key_add_userid.py000066400000000000000000000004031432224606000207470ustar00rootroot00000000000000import rnp def test_key_add_uid(): rpgp = rnp.Rnp() key = rpgp.generate_key( {"primary": {"type": "RSA", "length": 1024, "userid": "test"}} )["primary"] key.add_userid("test2") assert set(key.userids()) == set(["test", "test2"]) py-rnp-main/tests/test_key_count.py000066400000000000000000000005341432224606000200010ustar00rootroot00000000000000import rnp def test_key_count(): rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 0 rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") assert rpgp.secret_key_count() == 7 py-rnp-main/tests/test_key_export.py000066400000000000000000000046611432224606000201770ustar00rootroot00000000000000import pytest import rnp @pytest.fixture def rpgp(): lib = rnp.Rnp() lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") return lib @pytest.fixture def key(rpgp): return rpgp.find_key_by_id("326ef111425d14a5") def test_export_defaults(rpgp, key): assert key.has_public_key() assert key.has_secret_key() secexported = key.export_secret() pubexported = key.export_public() pubdata = key.public_key_data() assert pubexported.startswith(b"-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n") assert pubexported.endswith(b"-----END PGP PUBLIC KEY BLOCK-----\r\n") key.remove() key = None assert rpgp.find_key_by_id("326ef111425d14a5") is None rpgp.load_keys(rnp.Input.from_bytes(pubexported), "GPG") key = rpgp.find_key_by_id("326ef111425d14a5") assert key assert key.public_key_data() == pubdata assert key.has_public_key() assert not key.has_secret_key() rpgp.import_keys(rnp.Input.from_bytes(secexported), "GPG") # must obtain new key handle after importing sec key = rpgp.find_key_by_id("326ef111425d14a5") assert key.has_secret_key() def test_export_autocrypt(rpgp): primary = rpgp.find_key_by_id("2fcadf05ffa501bb") subkey = rpgp.find_key_by_id("54505a936a4a970e") exported = rpgp.export_autocrypt("key1-uid2", primary, subkey) pkts = rnp.parse(rnp.Input.from_bytes(exported)) # primary key, userid, userid cert, subkey, subkey binding assert len(pkts) == 5 assert pkts[0]["keyid"] == "2fcadf05ffa501bb" assert pkts[1]["userid"] == "key1-uid2" assert pkts[3]["keyid"] == "54505a936a4a970e" def test_export_autocrypt_default_sub(rpgp): primary = rpgp.find_key_by_id("2fcadf05ffa501bb") exported = rpgp.export_autocrypt("key1-uid2", primary) pkts = rnp.parse(rnp.Input.from_bytes(exported)) # primary key, userid, userid cert, subkey, subkey binding assert len(pkts) == 5 assert pkts[0]["keyid"] == "2fcadf05ffa501bb" assert pkts[1]["userid"] == "key1-uid2" assert pkts[3]["keyid"] == "326ef111425d14a5" def test_export_revocation(rpgp): key = rpgp.find_key_by_id("2fcadf05ffa501bb") key.unlock("password") revocation = key.export_revocation() pkts = rnp.parse(rnp.Input.from_bytes(revocation)) assert len(pkts) == 1 assert pkts[0]["type.str"] == "Key revocation signature" py-rnp-main/tests/test_key_lifetime.py000066400000000000000000000013531432224606000204470ustar00rootroot00000000000000import rnp def test_key_lifetime(): rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") key = rpgp.find_key_by_id("7bc6709b15c23a4a") key.unlock("password") assert key.lifetime() == 0 key.set_lifetime(1234) assert key.lifetime() == 1234 pkts = rnp.parse(rnp.Input.from_bytes(key.public_key_data())) certs = [ pkt for pkt in pkts if pkt.get("type.str") == "Positive User ID certification" ] assert len(certs) == 3 for cert in certs: exp = [ sub for sub in cert["subpackets"] if sub["type.str"] == "key expiration time" ] assert len(exp) == 1 exp[0]["key expiration"] == 1234 py-rnp-main/tests/test_key_properties.py000066400000000000000000000061441432224606000210500ustar00rootroot00000000000000import rnp import pytest @pytest.fixture def rpgp(): lib = rnp.Rnp() lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") return lib @pytest.fixture def key0(rpgp): return rpgp.find_key_by_id("7bc6709b15c23a4a") def test_key0_alg(key0): assert key0.alg() == "RSA" def test_key0_valid(key0): assert key0.is_valid() def test_key0_identifiers(key0): assert key0.keyid() == "7bc6709b15c23a4a".upper() assert key0.fingerprint() == "e95a3cbf583aa80a2ccc53aa7bc6709b15c23a4a".upper() assert key0.grip() == "66D6A0800A3FACDE0C0EB60B16B3669ED380FDFA" assert set(key0.userids()) == set(["key0-uid0", "key0-uid1", "key0-uid2"]) assert key0.primary_userid() == "key0-uid0" def test_key0_times(key0): assert key0.creation_time() == 1500569820 assert key0.lifetime() == 0 def test_key0_revoked(key0): assert not key0.is_revoked() def test_key0_usage(key0): assert key0.can_sign() assert key0.can_certify() assert not key0.can_encrypt() assert not key0.can_authenticate() def test_key0_sigs(key0): assert list(key0.signatures()) == [] def test_key0_bits(key0): assert key0.bits() == 1024 def test_key0_primary_sub(key0): assert key0.is_primary() assert not key0.is_sub() def test_key0_pub_sec(key0): assert key0.has_public_key() assert key0.has_secret_key() def test_key0_protection(key0): assert key0.is_locked() assert key0.is_protected() def test_key0_keydata(key0): assert isinstance(key0.public_key_data(), bytes) assert isinstance(key0.secret_key_data(), bytes) def test_key0_json(key0): jsn = key0.json() assert jsn["fingerprint"] == "E95A3CBF583AA80A2CCC53AA7BC6709B15C23A4A" @pytest.fixture def key0s2(rpgp): return rpgp.find_key_by_id("1d7e8a5393c997a8") def test_key0s2_valid(key0s2): assert not key0s2.is_valid() def test_key0s2_valid_until(key0s2): assert key0s2.valid_until() == key0s2.creation_time() + (60 * 60 * 24 * 123) def test_key0s2_protection(key0s2): assert key0s2.protection_cipher() == "CAST5" assert key0s2.protection_hashalg() == "SHA1" assert key0s2.protection_mode() == "CFB" assert key0s2.protection_type() == "Encrypted-Hashed" assert key0s2.protection_iterations() == 9961472 def test_key0s2_alg(key0s2): assert key0s2.alg() == "DSA" def test_key0s2_lifetime(key0s2): assert key0s2.lifetime() == 10627200 def test_key0s2_primary_sub(key0s2): assert not key0s2.is_primary() assert key0s2.is_sub() def test_key0s2_primary_ids(key0, key0s2): assert key0s2.primary_grip() == key0.grip() assert key0s2.primary_fingerprint() == key0.fingerprint() def test_key0s2_qbits(key0s2): assert key0s2.qbits() == 160 @pytest.fixture def ecclib(): lib = rnp.Rnp() lib.load_keys(rnp.Input.from_path("tests/data/keys/ecc-p384-pub.asc"), "GPG") return lib @pytest.fixture def ecckey(ecclib): return ecclib.find_key_by_id("242A3AA5EA85F44A") def test_ecc_curve(ecckey): assert ecckey.curve() == "NIST P-384" py-rnp-main/tests/test_key_protect_lock.py000066400000000000000000000015661432224606000213470ustar00rootroot00000000000000import rnp def test_protect_lock(): rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") key = rpgp.find_key_by_id("326ef111425d14a5") assert key.is_protected() assert key.is_locked() pkts = rnp.parse(rnp.Input.from_bytes(key.secret_key_data())) assert "symmetric algorithm" in pkts[0]["material"].keys() key.unlock("password") assert not key.is_locked() key.unprotect() assert not key.is_protected() pkts = rnp.parse(rnp.Input.from_bytes(key.secret_key_data())) assert "symmetric algorithm" not in pkts[0]["material"].keys() key.protect("password") assert key.is_protected() assert key.is_locked() pkts = rnp.parse(rnp.Input.from_bytes(key.secret_key_data())) assert "symmetric algorithm" in pkts[0]["material"].keys() key.lock() assert key.is_locked() py-rnp-main/tests/test_key_revocation.py000066400000000000000000000024631432224606000210250ustar00rootroot00000000000000import random import pytest import rnp @pytest.fixture def rpgp(): return rnp.Rnp() @pytest.fixture def key(rpgp): return rpgp.generate_key( {"primary": {"type": "RSA", "length": 1024, "userid": "testing"}} )["primary"] def test_key_revocation(key): assert not key.is_revoked() key.revoke() assert key.is_revoked() def test_key_revocation_sig(key): assert key.revocation_signature() is None key.revoke() assert isinstance(key.revocation_signature(), rnp.Signature) assert ( key.revocation_signature().json()[0]["type.str"] == "Key revocation signature" ) def test_key_revocation_reason(key): assert not key.is_revoked() key.revoke(None, None, "for testing") assert key.is_revoked() assert key.revocation_reason() == "for testing" def test_key_revocation_code(key): assert not key.is_revoked() key.revoke(None, "compromised") assert key.is_compromised() assert not key.is_retired() assert not key.is_superseded() def test_key_revocation_hash(rpgp, key): hashalg = random.choice(rnp.features("hash algorithm")) key.revoke(hashalg) pkts = key.packets_json() pkt = next( filter(lambda pkt: pkt.get("type.str") == "Key revocation signature", pkts) ) assert pkt["hash algorithm.str"] == hashalg py-rnp-main/tests/test_key_sigs.py000066400000000000000000000020641432224606000176160ustar00rootroot00000000000000import pytest import rnp @pytest.fixture def rpgp(): lib = rnp.Rnp() lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") return lib @pytest.fixture def key(rpgp): return rpgp.find_key_by_id("54505a936a4a970e") def test_key_signatures(key): assert len(list(key.signatures())) == 1 sig = next(key.signatures()) assert sig.type() == "subkey binding" assert sig.alg() == "DSA" assert sig.hashalg() == "SHA1" assert sig.keyid() == "2FCADF05FFA501BB" assert sig.creation_time() == 1500569946 assert sig.signer().keyid() == "2FCADF05FFA501BB" assert sig.status() == 0 def test_key_signatures_json(key): # mpi, raw, grip sig = next(key.signatures()) assert len(sig.json()) == 1 assert sig.json()[0]["type.str"] == "Subkey Binding Signature" # mpi assert "r.raw" not in sig.json()[0]["material"].keys() assert "r.raw" in sig.json(True)[0]["material"].keys() # raw assert "raw" not in sig.json()[0].keys() assert "raw" in sig.json(False, True)[0].keys() py-rnp-main/tests/test_key_subkeys.py000066400000000000000000000007221432224606000203350ustar00rootroot00000000000000import rnp def test_subkeys(): rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") key = rpgp.find_key_by_id("2fcadf05ffa501bb") assert set(map(lambda key: key.keyid(), key.subkeys())) == set( ["54505A936A4A970E", "326EF111425D14A5"] ) rpgp.find_key_by_id("326EF111425D14A5").remove(True, False) assert set(map(lambda key: key.keyid(), key.subkeys())) == set(["54505A936A4A970E"]) py-rnp-main/tests/test_key_userid.py000066400000000000000000000045241432224606000201470ustar00rootroot00000000000000import rnp def test_key_user_attr_photo(): rpgp = rnp.Rnp() rpgp.load_keys( rnp.Input.from_path("tests/data/keys/ecc-25519-photo-pub.asc"), "GPG" ) key = rpgp.find_key_by_id("CC786278981B0728") assert list(key.userids()) == ["ecc-25519"] uids = list(key.uids()) assert len(uids) == 2 assert uids[0].type() == rnp.UID.RNP_USER_ID assert not uids[0].is_primary() assert uids[0].is_valid() assert not uids[0].is_revoked() assert uids[0].data() == b"ecc-25519" assert uids[1].type() == rnp.UID.RNP_USER_ATTR assert not uids[1].is_primary() assert uids[1].is_valid() assert not uids[1].is_revoked() def test_key_uid_revsig(): rpgp = rnp.Rnp() rpgp.load_keys( rnp.Input.from_path("tests/data/keys/ecc-p256-revoked-uid.asc"), "GPG" ) key = rpgp.find_key_by_id("23674f21b2441527") uids = list(key.uids()) assert len(uids) == 2 assert uids[0].revocation_signature() is None sigs = list(uids[0].signatures()) assert len(sigs) == 1 sig = sigs[0] assert sig.type() == "certification (positive)" assert sig.alg() == "ECDSA" assert sig.hashalg() == "SHA256" assert sig.keyid() == "23674F21B2441527" assert sig.creation_time() == 1549119463 if rnp.check('have-rnp-signature-get-expiration'): assert sig.lifetime() == 0 assert sig.signer().keyid() == "23674F21B2441527" assert sig.status() == 0 sigs = list(uids[1].signatures()) assert len(sigs) == 2 sig = sigs[0] assert sig.type() == "certification revocation" assert sig.alg() == "ECDSA" assert sig.hashalg() == "SHA256" assert sig.keyid() == "23674F21B2441527" assert sig.creation_time() == 1556630215 if rnp.check('have-rnp-signature-get-expiration'): assert sig.lifetime() == 0 assert sig.signer().keyid() == "23674F21B2441527" assert sig.status() == 0 sig = sigs[1] assert sig.type() == "certification (positive)" assert sig.alg() == "ECDSA" assert sig.hashalg() == "SHA256" assert sig.keyid() == "23674F21B2441527" assert sig.creation_time() == 1556630177 if rnp.check('have-rnp-signature-get-expiration'): assert sig.lifetime() == 0 assert sig.signer().keyid() == "23674F21B2441527" assert sig.status() == 0 assert uids[1].revocation_signature().creation_time() == 1556630215 py-rnp-main/tests/test_load_save.py000066400000000000000000000060431432224606000177370ustar00rootroot00000000000000import rnp def test_load_keys(): rpgp = rnp.Rnp() assert rpgp.public_key_count() == 0 assert rpgp.secret_key_count() == 0 rpgp.load_keys( rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG", False, True ) assert rpgp.public_key_count() == 0 assert rpgp.secret_key_count() == 0 rpgp.load_keys( rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG", True, False ) assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 0 rpgp.load_keys( rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG", True, False ) assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 0 rpgp.load_keys( rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG", False, True ) assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 7 def test_load_keys_public_from_secret(): rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 7 def test_save_keys(): rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") # public outp = rnp.Output.to_bytes() rpgp.save_keys(outp, "GPG", True, False) assert { pkt["header"]["tag.str"] for pkt in rnp.parse(rnp.Input.from_bytes(outp.bytes())) } == {"Public Key", "Public Subkey", "User ID", "Signature"} # secret outp = rnp.Output.to_bytes() rpgp.save_keys(outp, "GPG", False, True) assert { pkt["header"]["tag.str"] for pkt in rnp.parse(rnp.Input.from_bytes(outp.bytes())) } == {"Secret Key", "Secret Subkey", "User ID", "Signature"} def test_unload_keys(): # public rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 7 rpgp.unload_keys(True, False) assert rpgp.public_key_count() == 0 assert rpgp.secret_key_count() == 7 # secret rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 7 rpgp.unload_keys(False, True) assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 0 # both rpgp = rnp.Rnp() rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") rpgp.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") assert rpgp.public_key_count() == 7 assert rpgp.secret_key_count() == 7 rpgp.unload_keys() assert rpgp.public_key_count() == 0 assert rpgp.secret_key_count() == 0 py-rnp-main/tests/test_misc.py000066400000000000000000000054511432224606000167370ustar00rootroot00000000000000import rnp def test_debug(): # ensure callable rnp.enable_debug() rnp.disable_debug() def test_default_homedir(): assert isinstance(rnp.default_homedir(), str) def test_homedir_info_gpg(): info = rnp.homedir_info("tests/data/keyrings/gpg") assert info["public"]["format"] == "GPG" assert info["public"]["path"] == "tests/data/keyrings/gpg/pubring.gpg" assert info["secret"]["format"] == "GPG" assert info["secret"]["path"] == "tests/data/keyrings/gpg/secring.gpg" def test_homedir_info_gpg21(): info = rnp.homedir_info("tests/data/keyrings/gpg21") assert info["public"]["format"] == "KBX" assert info["public"]["path"] == "tests/data/keyrings/gpg21/pubring.kbx" assert info["secret"]["format"] == "G10" assert info["secret"]["path"] == "tests/data/keyrings/gpg21/private-keys-v1.d" def test_key_format(): assert ( rnp.key_format(open("tests/data/keyrings/gpg/pubring.gpg", mode="rb").read(20)) == "GPG" ) assert ( rnp.key_format( open("tests/data/keyrings/gpg21/pubring.kbx", mode="rb").read(20) ) == "KBX" ) assert ( rnp.key_format( open( "tests/data/keyrings/gpg21/private-keys-v1.d/63E59092E4B1AE9F8E675B2F98AA2B8BD9F4EA59.key", mode="rb", ).read(20) ) == "G10" ) assert rnp.key_format(b"ABC") is None def test_calc_iters(): hashalg = rnp.features("hash algorithm")[0] assert isinstance(rnp.calculate_iterations(hashalg, 1), int) def test_supports(): assert isinstance(rnp.supports("hash algorithm", "SHA1"), bool) def test_features(): assert isinstance(rnp.features("hash algorithm"), list) def test_armor_msg_default_output(): msg = rnp.enarmor(rnp.Input.from_bytes(b"Test message"), None, "message") assert msg.startswith(b"-----BEGIN PGP MESSAGE-----") assert rnp.dearmor(rnp.Input.from_bytes(msg)) == b"Test message" def test_dearmor_key(tmp_path): path = str(tmp_path / "alice-pub.gpg") rnp.dearmor( rnp.Input.from_path("tests/data/keys/alice-pub.asc"), rnp.Output.to_path(path) ) rnp.guess_contents(rnp.Input.from_path(path)) == "public key" def test_armor_public_key(): outp = rnp.Output.to_bytes() rnp.enarmor(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), outp) result = outp.bytes() assert result.startswith(b"-----BEGIN PGP PUBLIC KEY BLOCK-----") assert ( rnp.dearmor(rnp.Input.from_bytes(result)) == open("tests/data/keyrings/gpg/pubring.gpg", mode="rb").read() ) def test_guess_contents(): assert rnp.guess_contents(rnp.Input.from_bytes(b"BEEF")) == "unknown" assert ( rnp.guess_contents(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg")) == "public key" ) py-rnp-main/tests/test_output_io.py000066400000000000000000000006201432224606000200240ustar00rootroot00000000000000import io import rnp def test_output_io(): rpgp = rnp.Rnp() rpgp.set_password_provider(lambda key, reason: "password") plaintext = b"some secret" bio = io.BytesIO() outp = rnp.Output.to_io(bio) assert ( rpgp.symmetric_encrypt(rnp.Input.from_bytes(plaintext), "password", outp=outp) is None ) assert rpgp.decrypt(bytes(bio.getbuffer())) == plaintext py-rnp-main/tests/test_simple_encrypt.py000066400000000000000000000046641432224606000210460ustar00rootroot00000000000000import pytest import rnp @pytest.fixture def rpgp(): lib = rnp.Rnp() lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") return lib def simple_password_provider(key, reason): return "password" def test_simple_encrypt(rpgp): key = rpgp.find_key_by_id("54505a936a4a970e") plaintext = "this is a test".encode("utf-8") encrypted = rpgp.encrypt(rnp.Input.from_bytes(plaintext), key) assert isinstance(encrypted, bytes) rpgp.set_password_provider(simple_password_provider) decrypted = rpgp.decrypt(rnp.Input.from_bytes(encrypted)) assert decrypted == plaintext def test_simple_encrypt_sign(rpgp): key1 = rpgp.find_key_by_userid("key0-uid2") key2 = rpgp.find_key_by_userid("key1-uid0") plaintext = b"this is a test" rpgp.set_password_provider(lambda key, reason: "password") encrypted = rpgp.encrypt_and_sign( rnp.Input.from_bytes(plaintext), [key1, key2], [key1] ) assert isinstance(encrypted, bytes) decrypted = rpgp.decrypt(rnp.Input.from_bytes(encrypted)) assert decrypted == plaintext verify = rpgp.verify(rnp.Input.from_bytes(encrypted)) signatures = list(verify.signatures()) assert len(signatures) == 1 assert signatures[0].keyid() == key1.keyid() def test_simple_symmetric_encrypt_single(): rpgp = rnp.Rnp() plaintext = b"secret data" encrypted = rpgp.symmetric_encrypt(rnp.Input.from_bytes(plaintext), "pass") rpgp.set_password_provider(lambda key, reason: "pass") assert rpgp.decrypt(rnp.Input.from_bytes(encrypted)) == plaintext def test_simple_symmetric_encrypt_multiple(): rpgp = rnp.Rnp() plaintext = b"secret data" encrypted = rpgp.symmetric_encrypt( rnp.Input.from_bytes(plaintext), ["pass1", "pass2"] ) # bad password with pytest.raises(rnp.RnpException): rpgp.set_password_provider(lambda key, reason: "pass") rpgp.decrypt(rnp.Input.from_bytes(encrypted)) # no password with pytest.raises(rnp.RnpException): rpgp.set_password_provider(None) rpgp.decrypt(rnp.Input.from_bytes(encrypted)) rpgp.set_password_provider(lambda key, reason: "pass1") assert rpgp.decrypt(rnp.Input.from_bytes(encrypted)) == plaintext rpgp.set_password_provider(lambda key, reason: "pass2") assert rpgp.decrypt(rnp.Input.from_bytes(encrypted)) == plaintext py-rnp-main/tests/test_simple_sign.py000066400000000000000000000056601432224606000203170ustar00rootroot00000000000000import time import random import pytest import rnp @pytest.fixture def rpgp(): lib = rnp.Rnp() lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/pubring.gpg"), "GPG") lib.load_keys(rnp.Input.from_path("tests/data/keyrings/gpg/secring.gpg"), "GPG") return lib @pytest.fixture def key(rpgp): key = rpgp.find_key_by_id("7bc6709b15c23a4a") key.unlock("password") return key def test_simple_sign(rpgp, key): signature = rpgp.sign(key, rnp.Input.from_bytes(b"test data")) assert isinstance(signature, bytes) assert len(signature) >= 1 rpgp.verify(rnp.Input.from_bytes(signature)) outp = rnp.Output.to_bytes() rpgp.verify(rnp.Input.from_bytes(signature), outp) assert outp.bytes() == b"test data" def test_simple_sign_with_options(rpgp, key): halg = random.choice(rnp.features("hash algorithm")) calg = random.choice( [ calg for calg in rnp.features("compression algorithm") if calg != "Uncompressed" ] ) signature = rpgp.sign( key, rnp.Input.from_bytes(b"test data"), True, halg, (calg, 1), int(time.time()), 60 * 10, ) assert isinstance(signature, bytes) assert len(signature) >= 1 assert signature.startswith(b"-----BEGIN PGP MESSAGE-----\r\n") rpgp.verify(rnp.Input.from_bytes(signature)) op = rnp.Verify.start(rpgp, rnp.Input.from_bytes(signature)) op.finish() assert len(list(op.signatures())) == 1 sig = next(op.signatures()) if rnp.check('have-rnp-signature-get-expiration'): assert sig.lifetime() == 60 * 10 assert sig.status() == 0 def test_simple_sign_cleartext(rpgp, key): key2 = rpgp.find_key_by_fingerprint("be1c4ab951f4c2f6b604c7f82fcadf05ffa501bb") key2.unlock("password") signature = rpgp.sign_cleartext([key, key2], rnp.Input.from_bytes(b"some data")) assert signature.startswith(b"-----BEGIN PGP SIGNED MESSAGE-----\r\n") pkts = rnp.parse(rnp.Input.from_bytes(signature)) assert [pkt["header"]["tag.str"] for pkt in pkts] == ["Signature", "Signature"] assert { subpkt.get("issuer keyid") for pkt in pkts for subpkt in pkt["subpackets"] if "issuer keyid" in subpkt } == {"7bc6709b15c23a4a", "2fcadf05ffa501bb"} rpgp.verify(rnp.Input.from_bytes(signature)) def test_simple_sign_detached(rpgp, key): signature = rpgp.sign_detached(key, rnp.Input.from_bytes(b"test")) rpgp.verify_detached(rnp.Input.from_bytes(b"test"), rnp.Input.from_bytes(signature)) with pytest.raises(rnp.RnpException): rpgp.verify_detached( rnp.Input.from_bytes(b"test2"), rnp.Input.from_bytes(signature) ) signature = bytearray(signature) signature[int(len(signature) / 2)] ^= 0xFF with pytest.raises(rnp.RnpException): rpgp.verify_detached( rnp.Input.from_bytes(b"test"), rnp.Input.from_bytes(signature) ) py-rnp-main/tests/test_version.py000066400000000000000000000011441432224606000174640ustar00rootroot00000000000000import rnp def test_version_string(): assert isinstance(rnp.version_string(), str) assert isinstance(rnp.version_string_full(), str) def test_version(): assert isinstance(rnp.version(), int) assert rnp.version("1.23.4") == ((1 << 20) | (23 << 10) | (4 << 0)) assert rnp.version_for(1, 23, 4) == ((1 << 20) | (23 << 10) | (4 << 0)) def test_version_components(): assert isinstance(rnp.version_major(), int) assert isinstance(rnp.version_minor(), int) assert isinstance(rnp.version_patch(), int) def test_version_commit_time(): assert isinstance(rnp.commit_time(), int) py-rnp-main/tox.ini000066400000000000000000000004511432224606000145370ustar00rootroot00000000000000[tox] envlist = py39 isolated_build = true [testenv] passenv = HOME require_locked_deps = true install_dev_deps = true whitelist_externals = poetry commands = poetry run black rnp poetry run flake8 rnp poetry run pylint -E rnp poetry run pytest -v [flake8] max-line-length = 88